summaryrefslogtreecommitdiff
path: root/usr.sbin/ipsend
diff options
context:
space:
mode:
authordgregor <dgregor@cvs.openbsd.org>1998-01-26 04:17:12 +0000
committerdgregor <dgregor@cvs.openbsd.org>1998-01-26 04:17:12 +0000
commitfe0239590c82ea51b1a09fd58cde9f1635ceab89 (patch)
treeaf8e00e22aa869bee7596358bc05686c76370f51 /usr.sbin/ipsend
parenta344d388d075c3e901494684772107ed51830e00 (diff)
IPF 3.2.3
Diffstat (limited to 'usr.sbin/ipsend')
-rw-r--r--usr.sbin/ipsend/common/44arp.c13
-rw-r--r--usr.sbin/ipsend/common/ip.c125
-rw-r--r--usr.sbin/ipsend/common/iplang.h51
-rw-r--r--usr.sbin/ipsend/common/ipsend.h67
-rw-r--r--usr.sbin/ipsend/common/sbpf.c21
-rw-r--r--usr.sbin/ipsend/common/sock.c131
-rw-r--r--usr.sbin/ipsend/common/tcpip.h91
-rw-r--r--usr.sbin/ipsend/ipresend/Makefile9
-rw-r--r--usr.sbin/ipsend/ipresend/ipresend.1107
-rw-r--r--usr.sbin/ipsend/ipresend/ipresend.c54
-rw-r--r--usr.sbin/ipsend/ipresend/resend.c80
-rw-r--r--usr.sbin/ipsend/ipsend/Makefile12
-rw-r--r--usr.sbin/ipsend/ipsend/iplang_l.l312
-rw-r--r--usr.sbin/ipsend/ipsend/iplang_y.y1840
-rw-r--r--usr.sbin/ipsend/ipsend/ipsend.1110
-rw-r--r--usr.sbin/ipsend/ipsend/ipsend.5399
-rw-r--r--usr.sbin/ipsend/ipsend/ipsend.c134
-rw-r--r--usr.sbin/ipsend/ipsend/ipsopt.c160
-rw-r--r--usr.sbin/ipsend/iptest/Makefile7
-rw-r--r--usr.sbin/ipsend/iptest/iptest.1102
-rw-r--r--usr.sbin/ipsend/iptest/iptest.c78
-rw-r--r--usr.sbin/ipsend/iptest/iptests.c250
22 files changed, 3793 insertions, 360 deletions
diff --git a/usr.sbin/ipsend/common/44arp.c b/usr.sbin/ipsend/common/44arp.c
index 04afb619f24..290e676d514 100644
--- a/usr.sbin/ipsend/common/44arp.c
+++ b/usr.sbin/ipsend/common/44arp.c
@@ -1,6 +1,9 @@
/*
* Based upon 4.4BSD's /usr/sbin/arp
*/
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
@@ -16,6 +19,14 @@
#include <errno.h>
#include <nlist.h>
#include <stdio.h>
+#include <netinet/in.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include "ipsend.h"
+
/*
* lookup host and return
@@ -49,7 +60,7 @@ char *addr, *eaddr;
{
int mib[6];
size_t needed;
- char *host, *malloc(), *lim, *buf, *next;
+ char *lim, *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin;
struct sockaddr_dl *sdl;
diff --git a/usr.sbin/ipsend/common/ip.c b/usr.sbin/ipsend/common/ip.c
index 97ff1104851..ede14cf1cc9 100644
--- a/usr.sbin/ipsend/common/ip.c
+++ b/usr.sbin/ipsend/common/ip.c
@@ -1,18 +1,19 @@
/*
- * ip.c (C) 1995 Darren Reed
+ * ip.c (C) 1995-1997 Darren Reed
*
- * The author provides this program as-is, with no gaurantee for its
- * suitability for any specific purpose. The author takes no responsibility
- * for the misuse/abuse of this program and provides it for the sole purpose
- * of testing packet filter policies. This file maybe distributed freely
- * providing it is not modified and that this notice remains in tact.
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "%W% %G% (C)1995";
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995";
+static const char rcsid[] = "@(#)$Id: ip.c,v 1.5 1998/01/26 04:16:50 dgregor Exp $";
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <sys/socket.h>
@@ -22,15 +23,15 @@ static char sccsid[] = "%W% %G% (C)1995";
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
+#include <sys/param.h>
#ifndef linux
-#include <netinet/if_ether.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcpip.h>
-#endif
-#include "ip_compat.h"
-#ifdef linux
-#include "tcpip.h"
+# include <netinet/if_ether.h>
+# include <netinet/ip_var.h>
+# if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+# endif
#endif
+#include "ipsend.h"
static char *ipbuf = NULL, *ethbuf = NULL;
@@ -69,8 +70,8 @@ struct in_addr gwip;
bcopy((char *)buf, s + sizeof(*eh), len);
if (gwip.s_addr == last_gw.s_addr)
- bcopy(last_arp, eh->ether_dhost, 6);
- else if (arp((char *)&gwip, &eh->ether_dhost) == -1)
+ bcopy(last_arp, (char *)A_A eh->ether_dhost, 6);
+ else if (arp((char *)&gwip, (char *)A_A eh->ether_dhost) == -1)
{
perror("arp");
return -2;
@@ -95,41 +96,44 @@ int frag;
static u_short id = 0;
ether_header_t *eh;
ip_t ipsv;
- int err;
+ int err, iplen;
if (!ipbuf)
ipbuf = (char *)malloc(65536);
eh = (ether_header_t *)ipbuf;
- bzero(&eh->ether_shost, sizeof(eh->ether_shost));
+ bzero((char *)A_A eh->ether_shost, sizeof(eh->ether_shost));
if (last_gw.s_addr && (gwip.s_addr == last_gw.s_addr))
- bcopy(last_arp, eh->ether_dhost, 6);
- else if (arp((char *)&gwip, &eh->ether_dhost) == -1)
+ bcopy(last_arp, (char *)A_A eh->ether_dhost, 6);
+ else if (arp((char *)&gwip, (char *)A_A eh->ether_dhost) == -1)
{
perror("arp");
return -2;
}
- bcopy(eh->ether_dhost, last_arp, sizeof(last_arp));
+ bcopy((char *)A_A eh->ether_dhost, last_arp, sizeof(last_arp));
eh->ether_type = htons(ETHERTYPE_IP);
bcopy((char *)ip, (char *)&ipsv, sizeof(*ip));
last_gw.s_addr = gwip.s_addr;
- ip->ip_len = htons(ip->ip_len);
+ iplen = ip->ip_len;
+ ip->ip_len = htons(iplen);
ip->ip_off = htons(ip->ip_off);
- if (!ip->ip_v)
- ip->ip_v = IPVERSION;
- if (!ip->ip_id)
- ip->ip_id = htons(id++);
- if (!ip->ip_ttl)
- ip->ip_ttl = 60;
-
- if (!frag || (sizeof(*eh) + ntohs(ip->ip_len) < mtu))
+ if (!(frag & 2)) {
+ if (!ip->ip_v)
+ ip->ip_v = IPVERSION;
+ if (!ip->ip_id)
+ ip->ip_id = htons(id++);
+ if (!ip->ip_ttl)
+ ip->ip_ttl = 60;
+ }
+
+ if (!frag || (sizeof(*eh) + iplen < mtu))
{
ip->ip_sum = 0;
- ip->ip_sum = chksum(ip, ip->ip_hl << 2);
+ ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
- bcopy((char *)ip, ipbuf + sizeof(*eh), ntohs(ip->ip_len));
- err = sendip(nfd, ipbuf, sizeof(*eh) + ntohs(ip->ip_len));
+ bcopy((char *)ip, ipbuf + sizeof(*eh), iplen);
+ err = sendip(nfd, ipbuf, sizeof(*eh) + iplen);
}
else
{
@@ -141,7 +145,7 @@ int frag;
ether_header_t eth;
char optcpy[48], ol;
char *s;
- int i, iplen, sent = 0, ts, hlen, olen;
+ int i, sent = 0, ts, hlen, olen;
hlen = ip->ip_hl << 2;
if (mtu < (hlen + 8)) {
@@ -176,7 +180,7 @@ int frag;
*/
while ((i & 3) && (i & 3) != 3)
optcpy[i++] = IPOPT_NOP;
- if (i & 3 == 3)
+ if ((i & 3) == 3)
optcpy[i++] = IPOPT_EOL;
}
@@ -199,7 +203,7 @@ int frag;
ts += hlen;
ip->ip_len = htons(ts);
ip->ip_sum = 0;
- ip->ip_sum = chksum(ip, hlen);
+ ip->ip_sum = chksum((u_short *)ip, hlen);
bcopy((char *)ip, ipbuf + sizeof(*eh), hlen);
bcopy(s + sent, ipbuf + sizeof(*eh) + hlen, ts - hlen);
err = sendip(nfd, ipbuf, sizeof(*eh) + ts);
@@ -232,43 +236,44 @@ struct in_addr gwip;
{
static tcp_seq iss = 2;
struct tcpiphdr *ti;
- int thlen, i;
- u_long lbuf[20];
+ tcphdr_t *t;
+ int thlen, i, iplen, hlen;
+ u_32_t lbuf[20];
+ iplen = ip->ip_len;
+ hlen = ip->ip_hl << 2;
+ t = (tcphdr_t *)((char *)ip + hlen);
ti = (struct tcpiphdr *)lbuf;
+ thlen = t->th_off << 2;
+ if (!thlen)
+ thlen = sizeof(tcphdr_t);
bzero((char *)ti, sizeof(*ti));
- thlen = sizeof(tcphdr_t);
ip->ip_p = IPPROTO_TCP;
ti->ti_pr = ip->ip_p;
ti->ti_src = ip->ip_src;
ti->ti_dst = ip->ip_dst;
- bcopy((char *)ip + (ip->ip_hl << 2),
- (char *)&ti->ti_sport, sizeof(tcphdr_t));
+ bcopy((char *)ip + hlen, (char *)&ti->ti_sport, thlen);
if (!ti->ti_win)
ti->ti_win = htons(4096);
- if (!ti->ti_seq)
- ti->ti_seq = htonl(iss);
- iss += 64;
+ iss += 63;
- if ((ti->ti_flags == TH_SYN) && !ip->ip_off)
- {
- ip = (ip_t *)realloc((char *)ip, ntohs(ip->ip_len) + 4);
- i = sizeof(struct tcpiphdr) / sizeof(long);
+ i = sizeof(struct tcpiphdr) / sizeof(long);
+
+ if ((ti->ti_flags == TH_SYN) && !ip->ip_off &&
+ (lbuf[i] != htonl(0x020405b4))) {
lbuf[i] = htonl(0x020405b4);
- bcopy((char *)(lbuf + i), (char*)ip + ntohs(ip->ip_len),
- sizeof(u_long));
+ bcopy((char *)ip + hlen + thlen, (char *)ip + hlen + thlen + 4,
+ iplen - thlen - hlen);
thlen += 4;
}
- if (!ti->ti_off)
- ti->ti_off = thlen >> 2;
+ ti->ti_off = thlen >> 2;
ti->ti_len = htons(thlen);
- ip->ip_len = (ip->ip_hl << 2) + thlen;
+ ip->ip_len = hlen + thlen;
ti->ti_sum = 0;
- ti->ti_sum = chksum(ti, thlen + sizeof(ip_t));
+ ti->ti_sum = chksum((u_short *)ti, thlen + sizeof(ip_t));
- bcopy((char *)&ti->ti_sport,
- (char *)ip + (ip->ip_hl << 2), thlen);
+ bcopy((char *)&ti->ti_sport, (char *)ip + hlen, thlen);
return send_ip(nfd, mtu, ip, gwip, 1);
}
@@ -282,7 +287,7 @@ ip_t *ip;
struct in_addr gwip;
{
struct tcpiphdr *ti;
- int thlen, i;
+ int thlen;
u_long lbuf[20];
ti = (struct tcpiphdr *)lbuf;
@@ -297,7 +302,7 @@ struct in_addr gwip;
ti->ti_len = htons(thlen);
ip->ip_len = (ip->ip_hl << 2) + thlen;
ti->ti_sum = 0;
- ti->ti_sum = chksum(ti, thlen + sizeof(ip_t));
+ ti->ti_sum = chksum((u_short *)ti, thlen + sizeof(ip_t));
bcopy((char *)&ti->ti_sport,
(char *)ip + (ip->ip_hl << 2), sizeof(udphdr_t));
@@ -318,7 +323,7 @@ struct in_addr gwip;
ic = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
ic->icmp_cksum = 0;
- ic->icmp_cksum = chksum((char *)ic, sizeof(struct icmp));
+ ic->icmp_cksum = chksum((u_short *)ic, sizeof(struct icmp));
return send_ip(nfd, mtu, ip, gwip, 1);
}
diff --git a/usr.sbin/ipsend/common/iplang.h b/usr.sbin/ipsend/common/iplang.h
new file mode 100644
index 00000000000..a7a13f91503
--- /dev/null
+++ b/usr.sbin/ipsend/common/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/usr.sbin/ipsend/common/ipsend.h b/usr.sbin/ipsend/common/ipsend.h
new file mode 100644
index 00000000000..5d4aab9c300
--- /dev/null
+++ b/usr.sbin/ipsend/common/ipsend.h
@@ -0,0 +1,67 @@
+/*
+ * ipsend.h (C) 1997 Darren Reed
+ *
+ * This was written to test what size TCP fragments would get through
+ * various TCP/IP packet filters, as used in IP firewalls. In certain
+ * conditions, enough of the TCP header is missing for unpredictable
+ * results unless the filter is aware that this can happen.
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ *
+ */
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+#include "ip_fil_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#endif
+#include "tcpip.h"
+#include "ipt.h"
+#include "ipf.h"
+
+extern int resolve __P((char *, char *));
+extern int arp __P((char *, char *));
+extern u_short chksum __P((u_short *, int));
+extern int send_ether __P((int, char *, int, struct in_addr));
+extern int send_ip __P((int, int, ip_t *, struct in_addr, int));
+extern int send_tcp __P((int, int, ip_t *, struct in_addr));
+extern int send_udp __P((int, int, ip_t *, struct in_addr));
+extern int send_icmp __P((int, int, ip_t *, struct in_addr));
+extern int send_packet __P((int, int, ip_t *, struct in_addr));
+extern int send_packets __P((char *, int, ip_t *, struct in_addr));
+extern u_short seclevel __P((char *));
+extern u_32_t buildopts __P((char *, char *, int));
+extern int addipopt __P((char *, struct ipopt_names *, int, char *));
+extern int initdevice __P((char *, int, int));
+extern int sendip __P((int, char *, int));
+#ifdef linux
+extern struct sock *find_tcp __P((int, struct tcpiphdr *));
+#else
+extern struct tcpcb *find_tcp __P((int, struct tcpiphdr *));
+#endif
+extern int ip_resend __P((char *, int, struct ipread *, struct in_addr, char *));
+
+extern void ip_test1 __P((char *, int, ip_t *, struct in_addr, int));
+extern void ip_test2 __P((char *, int, ip_t *, struct in_addr, int));
+extern void ip_test3 __P((char *, int, ip_t *, struct in_addr, int));
+extern void ip_test4 __P((char *, int, ip_t *, struct in_addr, int));
+extern void ip_test5 __P((char *, int, ip_t *, struct in_addr, int));
+extern void ip_test6 __P((char *, int, ip_t *, struct in_addr, int));
+extern void ip_test7 __P((char *, int, ip_t *, struct in_addr, int));
+extern int do_socket __P((char *, int, struct tcpiphdr *, struct in_addr));
+extern int openkmem __P((void));
+extern int kmemcpy __P((char *, void *, int));
+
+#define KMCPY(a,b,c) kmemcpy((char *)(a), (void *)(b), (int)(c))
+
+#define OPT_RAW 0x80000
diff --git a/usr.sbin/ipsend/common/sbpf.c b/usr.sbin/ipsend/common/sbpf.c
index 9bc557a1a9e..e03d2040ee0 100644
--- a/usr.sbin/ipsend/common/sbpf.c
+++ b/usr.sbin/ipsend/common/sbpf.c
@@ -1,13 +1,15 @@
/*
- * (C)opyright October 1995 Darren Reed. (from tcplog)
- *
- * This software may be freely distributed as long as it is not altered
- * in any way and that this messagge always accompanies it.
+ * (C)opyright 1995-1997 Darren Reed. (from tcplog)
*
+ * 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.
*/
#include <stdio.h>
-#include <stdlib.h>
#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
@@ -29,15 +31,15 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
-#include <netinet/tcpip.h>
+#include "ipsend.h"
-#ifndef lint
-static char sbpf[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: sbpf.c,v 1.3 1998/01/26 04:16:53 dgregor Exp $";
#endif
/*
@@ -51,7 +53,6 @@ int initdevice(device, sport, tout)
char *device;
int sport, tout;
{
- struct bpf_program prog;
struct bpf_version bv;
struct timeval to;
struct ifreq ifr;
diff --git a/usr.sbin/ipsend/common/sock.c b/usr.sbin/ipsend/common/sock.c
index 736f616f7a5..53e2db08a60 100644
--- a/usr.sbin/ipsend/common/sock.c
+++ b/usr.sbin/ipsend/common/sock.c
@@ -1,14 +1,13 @@
/*
- * sock.c (C) 1995 Darren Reed
+ * sock.c (C) 1995-1997 Darren Reed
*
- * The author provides this program as-is, with no gaurantee for its
- * suitability for any specific purpose. The author takes no responsibility
- * for the misuse/abuse of this program and provides it for the sole purpose
- * of testing packet filter policies. This file maybe distributed freely
- * providing it is not modified and that this notice remains in tact.
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: sock.c,v 1.3 1998/01/26 04:16:54 dgregor Exp $";
#endif
#include <stdio.h>
#include <unistd.h>
@@ -20,10 +19,16 @@ static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
#include <sys/time.h>
#include <sys/param.h>
#include <sys/stat.h>
+#ifndef ultrix
#include <fcntl.h>
+#endif
#include <sys/dir.h>
#define _KERNEL
#define KERNEL
+#ifdef ultrix
+# undef LOCORE
+# include <sys/smp_lock.h>
+#endif
#include <sys/file.h>
#undef _KERNEL
#undef KERNEL
@@ -32,7 +37,9 @@ static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/proc.h>
-#include <kvm.h>
+#if !defined(ultrix) && !defined(hpux)
+# include <kvm.h>
+#endif
#ifdef sun
#include <sys/systm.h>
#include <sys/session.h>
@@ -53,7 +60,7 @@ static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
#include <netinet/in_pcb.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
-#include <netinet/tcpip.h>
+#include "ipsend.h"
int nproc;
struct proc *proc;
@@ -75,17 +82,26 @@ struct proc *proc;
# define KERNEL "/vmunix"
#endif
+
+#if BSD < 199103
+static struct proc *getproc __P((void));
+#else
+static struct kinfo_proc *getproc __P((void));
+#endif
+
+
int kmemcpy(buf, pos, n)
char *buf;
void *pos;
int n;
{
static int kfd = -1;
+ off_t offset = (u_long)pos;
if (kfd == -1)
kfd = open(KMEM, O_RDONLY);
- if (lseek(kfd, (off_t)(u_long)pos, SEEK_SET) == -1)
+ if (lseek(kfd, offset, SEEK_SET) == -1)
{
perror("lseek");
return -1;
@@ -98,14 +114,19 @@ int n;
return n;
}
-struct nlist names[3] = {
+struct nlist names[4] = {
{ "_proc" },
{ "_nproc" },
+#ifdef ultrix
+ { "_u" },
+#else
+ { NULL },
+#endif
{ NULL }
};
#if BSD < 199103
-struct proc *getproc()
+static struct proc *getproc()
{
struct proc *p;
pid_t pid = getpid();
@@ -117,21 +138,20 @@ struct proc *getproc()
fprintf(stderr, "nlist(%#x) == %d\n", names, n);
return NULL;
}
- if (kmemcpy((char *)&nproc, (void *)names[1].n_value,
- sizeof(nproc)) == -1)
+ if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1)
{
fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
return NULL;
}
siz = nproc * sizeof(struct proc);
- if (kmemcpy((char *)&p, (void *)names[0].n_value, sizeof(p)) == -1)
+ if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
names[0].n_value, &p, sizeof(p));
return NULL;
}
proc = (struct proc *)malloc(siz);
- if (kmemcpy((char *)proc, (void *)p, siz) == -1)
+ if (KMCPY(proc, p, siz) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) proc\n",
p, proc, siz);
@@ -163,32 +183,40 @@ struct tcpiphdr *ti;
if (!(p = getproc()))
return NULL;
-
+printf("fl %x ty %x cn %d mc %d\n",
+f->f_flag, f->f_type, f->f_count, f->f_msgcount);
up = (struct user *)malloc(sizeof(*up));
- if (kmemcpy((char *)up, (void *)p->p_uarea, sizeof(*up)) == -1)
+#ifndef ultrix
+ if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1)
{
fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea);
return NULL;
}
+#else
+ if (KMCPY(up, names[2].n_value, sizeof(*up)) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x) failed\n", p, names[2].n_value);
+ return NULL;
+ }
+#endif
o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1));
- if (kmemcpy((char *)o, (void *)up->u_ofile,
- (up->u_lastfile + 1) * sizeof(*o)) == -1)
+ if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n",
- up->u_ofile_arr, o, sizeof(*o));
+ up->u_ofile, o, sizeof(*o));
return NULL;
}
f = (struct file *)calloc(1, sizeof(*f));
- if (kmemcpy((char *)f, (void *)o[fd], sizeof(*f)) == -1)
+ if (KMCPY(f, o[fd], sizeof(*f)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
- up->u_ofile_arr[fd], f, sizeof(*f));
+ up->u_ofile[fd], f, sizeof(*f));
return NULL;
}
s = (struct socket *)calloc(1, sizeof(*s));
- if (kmemcpy((char *)s, (void *)f->f_data, sizeof(*s)) == -1)
+ if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n",
o[fd], s, sizeof(*s));
@@ -196,7 +224,7 @@ struct tcpiphdr *ti;
}
i = (struct inpcb *)calloc(1, sizeof(*i));
- if (kmemcpy((char *)i, (void *)s->so_pcb, sizeof(*i)) == -1)
+ if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
{
fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n",
s->so_pcb, i, sizeof(*i));
@@ -204,7 +232,7 @@ struct tcpiphdr *ti;
}
t = (struct tcpcb *)calloc(1, sizeof(*t));
- if (kmemcpy((char *)t, (void *)i->inp_ppcb, sizeof(*t)) == -1)
+ if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
{
fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n",
i->inp_ppcb, t, sizeof(*t));
@@ -213,7 +241,7 @@ struct tcpiphdr *ti;
return (struct tcpcb *)i->inp_ppcb;
}
#else
-struct kinfo_proc *getproc()
+static struct kinfo_proc *getproc()
{
static struct kinfo_proc kp;
pid_t pid = getpid();
@@ -225,7 +253,7 @@ struct kinfo_proc *getproc()
mib[2] = KERN_PROC_PID;
mib[3] = pid;
- n = 1;
+ n = sizeof(kp);
if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
{
perror("sysctl");
@@ -250,61 +278,60 @@ struct tcpiphdr *ti;
return NULL;
fd = (struct filedesc *)malloc(sizeof(*fd));
- if (kmemcpy((char *)fd, (void *)p->kp_proc.p_fd, sizeof(*fd)) == -1)
+ if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
{
- fprintf(stderr, "read(%#x,%#x) failed\n", p, p->kp_proc.p_fd);
+ fprintf(stderr, "read(%#lx,%#lx) failed\n",
+ (u_long)p, (u_long)p->kp_proc.p_fd);
return NULL;
}
o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1));
- if (kmemcpy((char *)o, (void *)fd->fd_ofiles,
- (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
+ if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
{
- fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n",
- fd->fd_ofiles, o, sizeof(*o));
+ fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
+ (u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
return NULL;
}
f = (struct file *)calloc(1, sizeof(*f));
- if (kmemcpy((char *)f, (void *)o[tfd], sizeof(*f)) == -1)
+ if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
{
- fprintf(stderr, "read(%#x,%#x,%d) - o[tfd] - failed\n",
- o[tfd], f, sizeof(*f));
+ fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
+ (u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
return NULL;
}
s = (struct socket *)calloc(1, sizeof(*s));
- if (kmemcpy((char *)s, (void *)f->f_data, sizeof(*s)) == -1)
+ if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
{
- fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n",
- f->f_data, s, sizeof(*s));
+ fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
+ (u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
return NULL;
}
i = (struct inpcb *)calloc(1, sizeof(*i));
- if (kmemcpy((char *)i, (void *)s->so_pcb, sizeof(*i)) == -1)
+ if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
{
- fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n",
- s->so_pcb, i, sizeof(*i));
+ fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
+ (u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
return NULL;
}
t = (struct tcpcb *)calloc(1, sizeof(*t));
- if (kmemcpy((char *)t, (void *)i->inp_ppcb, sizeof(*t)) == -1)
+ if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
{
- fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n",
- i->inp_ppcb, t, sizeof(*t));
+ fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
+ (u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
return NULL;
}
return (struct tcpcb *)i->inp_ppcb;
}
#endif /* BSD < 199301 */
-int do_socket(dev, mtu, ti, gwip, flags)
+int do_socket(dev, mtu, ti, gwip)
char *dev;
int mtu;
struct tcpiphdr *ti;
struct in_addr gwip;
-int flags;
{
struct sockaddr_in rsin, lsin;
struct tcpcb *t, tcb;
@@ -338,7 +365,7 @@ int flags;
(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
ti->ti_sport = lsin.sin_port;
printf("sport %d\n", ntohs(lsin.sin_port));
- nfd = initdevice(dev, ntohs(lsin.sin_port));
+ nfd = initdevice(dev, ntohs(lsin.sin_port), 1);
if (!(t = find_tcp(fd, ti)))
return -1;
@@ -354,12 +381,12 @@ int flags;
perror("connect");
return -1;
}
- kmemcpy((char*)&tcb, (void *)t, sizeof(tcb));
+ KMCPY(&tcb, t, sizeof(tcb));
ti->ti_win = tcb.rcv_adv;
ti->ti_seq = tcb.snd_nxt - 1;
ti->ti_ack = tcb.rcv_nxt;
- if (send_tcp(nfd, mtu, ti, gwip, TH_SYN) == -1)
+ if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
return -1;
(void)write(fd, "Hello World\n", 12);
sleep(2);
diff --git a/usr.sbin/ipsend/common/tcpip.h b/usr.sbin/ipsend/common/tcpip.h
new file mode 100644
index 00000000000..72c8737f443
--- /dev/null
+++ b/usr.sbin/ipsend/common/tcpip.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ *
+ * @(#)tcpip.h 8.1 (Berkeley) 6/10/93
+ * $Id: tcpip.h,v 1.3 1998/01/26 04:16:55 dgregor Exp $
+ */
+
+#ifndef _NETINET_TCPIP_H_
+#define _NETINET_TCPIP_H_
+
+# if defined(linux) && !defined(LINUX_IPOVLY)
+# define LINUX_IPOVLY
+struct ipovly {
+ caddr_t ih_next, ih_prev; /* for protocol sequence q's */
+ u_char ih_x1; /* (unused) */
+ u_char ih_pr; /* protocol */
+ short ih_len; /* protocol length */
+ struct in_addr ih_src; /* source internet address */
+ struct in_addr ih_dst; /* destination internet address */
+};
+# endif
+
+/*
+ * Tcp+ip header, after ip options removed.
+ */
+struct tcpiphdr {
+ struct ipovly ti_i; /* overlaid ip structure */
+#ifdef linux
+ tcphdr_t ti_t;
+#else
+ struct tcphdr ti_t; /* tcp header */
+#endif
+};
+#ifdef notyet
+/*
+ * Tcp+ip header, after ip options removed but including TCP options.
+ */
+struct full_tcpiphdr {
+ struct ipovly ti_i; /* overlaid ip structure */
+ struct tcphdr ti_t; /* tcp header */
+ char ti_o[TCP_MAXOLEN]; /* space for tcp options */
+};
+#endif /* notyet */
+#define ti_next ti_i.ih_next
+#define ti_prev ti_i.ih_prev
+#define ti_x1 ti_i.ih_x1
+#define ti_pr ti_i.ih_pr
+#define ti_len ti_i.ih_len
+#define ti_src ti_i.ih_src
+#define ti_dst ti_i.ih_dst
+#define ti_sport ti_t.th_sport
+#define ti_dport ti_t.th_dport
+#define ti_seq ti_t.th_seq
+#define ti_ack ti_t.th_ack
+#define ti_x2 ti_t.th_x2
+#define ti_off ti_t.th_off
+#define ti_flags ti_t.th_flags
+#define ti_win ti_t.th_win
+#define ti_sum ti_t.th_sum
+#define ti_urp ti_t.th_urp
+
+#endif
diff --git a/usr.sbin/ipsend/ipresend/Makefile b/usr.sbin/ipsend/ipresend/Makefile
index 99d65114bcb..f0d7c827559 100644
--- a/usr.sbin/ipsend/ipresend/Makefile
+++ b/usr.sbin/ipsend/ipresend/Makefile
@@ -1,10 +1,11 @@
-# $Id: Makefile,v 1.2 1996/07/18 05:00:22 dm Exp $
+# $OpenBSD: Makefile,v 1.3 1998/01/26 04:16:56 dgregor Exp $
PROG= ipresend
BINDIR= /usr/sbin
-NOMAN=
-SRCS= ipresend.c resend.c ip.c sbpf.c sock.c 44arp.c opt.c \
- ipft_ef.c ipft_hx.c ipft_pc.c ipft_sn.c ipft_tx.c ipft_td.c
+MAN= ipresend.1
+SRCS= ipresend.o resend.o \
+ ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o opt.o \
+ sock.o 44arp.o sbpf.o ip.o
CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest \
-I${.CURDIR}/../../../sbin/ipf \
-I${.CURDIR}/../../../sys/netinet
diff --git a/usr.sbin/ipsend/ipresend/ipresend.1 b/usr.sbin/ipsend/ipresend/ipresend.1
new file mode 100644
index 00000000000..40f98256209
--- /dev/null
+++ b/usr.sbin/ipsend/ipresend/ipresend.1
@@ -0,0 +1,107 @@
+.TH IPRESEND 1
+.SH NAME
+ipresend \- resend IP packets out to network
+.SH SYNOPSIS
+.B ipsend
+[
+.B \-EHPRSTX
+] [
+.B \-d
+<device>
+] [
+.B \-g
+<\fIgateway\fP>
+] [
+.B \-m
+<\fIMTU\fP>
+] [
+.B \-r
+<\fIfilename\fP>
+]
+.SH DESCRIPTION
+.PP
+\fBipresend\fP was designed to allow packets to be resent, once captured,
+back out onto the network for use in testing. \fIipresend\fP supports a
+number of different file formats as input, including saved snoop/tcpdump
+binary data.
+.SH OPTIONS
+.TP
+.BR \-d \0<interface>
+Set the interface name to be the name supplied. This is useful with the
+\fB\-P, \-S, \-T\fP and \fB\-E\fP options, where it is not otherwise possible
+to associate a packet with an interface. Normal "text packets" can override
+this setting.
+.TP
+.BR \-g \0<gateway>
+Specify the hostname of the gateway through which to route packets. This
+is required whenever the destination host isn't directly attached to the
+same network as the host from which you're sending.
+.TP
+.BR \-m \0<MTU>
+Specify the MTU to be used when sending out packets. This option allows you
+to set a fake MTU, allowing the simulation of network interfaces with small
+MTU's without setting them so.
+.TP
+.BR \-r \0<filename>
+Specify the filename from which to take input. Default is stdin.
+.B \-E
+The input file is to be text output from etherfind. The text formats which
+are currently supported are those which result from the following etherfind
+option combinations:
+.PP
+.nf
+ etherfind -n
+ etherfind -n -t
+.fi
+.LP
+.TP
+.B \-H
+The input file is to be hex digits, representing the binary makeup of the
+packet. No length correction is made, if an incorrect length is put in
+the IP header.
+.TP
+.B \-P
+The input file specified by \fB\-i\fP is a binary file produced using libpcap
+(i.e., tcpdump version 3). Packets are read from this file as being input
+(for rule purposes).
+.TP
+.B \-R
+When sending packets out, send them out "raw" (the way they came in). The
+only real significance here is that it will expect the link layer (i.e.
+ethernet) headers to be prepended to the IP packet being output.
+.TP
+.B \-S
+The input file is to be in "snoop" format (see RFC 1761). Packets are read
+from this file and used as input from any interface. This is perhaps the
+most useful input type, currently.
+.TP
+.B \-T
+The input file is to be text output from tcpdump. The text formats which
+are currently supported are those which result from the following tcpdump
+option combinations:
+.PP
+.nf
+ tcpdump -n
+ tcpdump -nq
+ tcpdump -nqt
+ tcpdump -nqtt
+ tcpdump -nqte
+.fi
+.LP
+.TP
+.B \-X
+The input file is composed of text descriptions of IP packets.
+.TP
+.SH FILES
+.DT
+.SH SEE ALSO
+snoop(1m), tcpdump(8), etherfind(8c), ipftest(1), ipresend(1), iptest(1), bpf(4), dlpi(7p)
+.SH DIAGNOSTICS
+.PP
+Needs to be run as root.
+.SH BUGS
+.PP
+Not all of the input formats are sufficiently capable of introducing a
+wide enough variety of packets for them to be all useful in testing.
+If you find any, please send email to me at darrenr@cyber.com.au
+
diff --git a/usr.sbin/ipsend/ipresend/ipresend.c b/usr.sbin/ipsend/ipresend/ipresend.c
index 863c8b754da..52e2273574c 100644
--- a/usr.sbin/ipsend/ipresend/ipresend.c
+++ b/usr.sbin/ipsend/ipresend/ipresend.c
@@ -1,29 +1,30 @@
+/* $OpenBSD: ipresend.c,v 1.3 1998/01/26 04:16:58 dgregor Exp $ */
/*
- * ipsend.c (C) 1995 Darren Reed
+ * ipresend.c (C) 1995-1997 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
- * The author provides this program as-is, with no gaurantee for its
- * suitability for any specific purpose. The author takes no responsibility
- * for the misuse/abuse of this program and provides it for the sole purpose
- * of testing packet filter policies. This file maybe distributed freely
- * providing it is not modified and that this notice remains in tact.
- *
- * This was written and tested (successfully) on SunOS 4.1.x.
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: ipresend.c,v 1.3 1998/01/26 04:16:58 dgregor Exp $";
#endif
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -31,19 +32,15 @@ static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
-#include <netinet/tcpip.h>
-#endif
-#include "ip_compat.h"
-#ifdef linux
-#include <linux/sockios.h>
-#include "tcpip.h"
#endif
-#include "ipt.h"
+#include "ipsend.h"
extern char *optarg;
extern int optind;
+#ifndef NO_IPF
extern struct ipread snoop, pcap, etherf, iphex, tcpd, iptext;
+#endif
int opts = 0;
#ifndef DEFAULT_DEVICE
@@ -59,7 +56,11 @@ char default_device[] = "ln0";
# ifdef __bsdi__
char default_device[] = "ef0";
# else
+# ifdef __sgi
+char default_device[] = "ec0";
+# else
char default_device[] = "lan0";
+# endif
# endif
# endif
# endif
@@ -69,7 +70,11 @@ char default_device[] = DEFAULT_DEVICE;
#endif
-void usage(prog)
+static void usage __P((char *));
+int main __P((int, char **));
+
+
+static void usage(prog)
char *prog;
{
fprintf(stderr, "Usage: %s [options] <-r filename|-R filename>\n\
@@ -84,17 +89,17 @@ char *prog;
}
-main(argc, argv)
+int main(argc, argv)
int argc;
char **argv;
{
struct in_addr gwip;
struct ipread *ipr = NULL;
char *name = argv[0], *gateway = NULL, *dev = NULL;
- char c, *s, *resend = NULL;
- int mtu = 1500;
+ char *resend = NULL;
+ int mtu = 1500, c;
- while ((c = getopt(argc, argv, "EHPSTXd:g:m:r:")) != -1)
+ while ((c = getopt(argc, argv, "EHPRSTXd:g:m:r:")) != -1)
switch (c)
{
case 'd' :
@@ -113,6 +118,10 @@ char **argv;
case 'r' :
resend = optarg;
break;
+ case 'R' :
+ opts |= OPT_RAW;
+ break;
+#ifndef NO_IPF
case 'E' :
ipr = &etherf;
break;
@@ -131,6 +140,7 @@ char **argv;
case 'X' :
ipr = &iptext;
break;
+#endif
default :
fprintf(stderr, "Unknown option \"%c\"\n", c);
usage(name);
diff --git a/usr.sbin/ipsend/ipresend/resend.c b/usr.sbin/ipsend/ipresend/resend.c
index 6762ae6048c..4beec1ac887 100644
--- a/usr.sbin/ipsend/ipresend/resend.c
+++ b/usr.sbin/ipsend/ipresend/resend.c
@@ -1,46 +1,52 @@
+/* $OpenBSD: resend.c,v 1.3 1998/01/26 04:16:59 dgregor Exp $ */
/*
- * resend.c (C) 1995 Darren Reed
+ * resend.c (C) 1995-1997 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: resend.c,v 1.3 1998/01/26 04:16:59 dgregor Exp $";
#endif
#include <stdio.h>
-#include <stdlib.h>
#include <netdb.h>
#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#ifndef linux
-#include <netinet/ip_var.h>
-#include <netinet/tcpip.h>
-#include <netinet/if_ether.h>
+# include <netinet/ip_var.h>
+# include <netinet/if_ether.h>
+# if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+# endif
#endif
-#include "ip_compat.h"
-#ifdef linux
-#include <linux/sockios.h>
-#include "tcpip.h"
-#endif
-#include "ipt.h"
+#include "ipsend.h"
+extern int opts;
static u_char buf[65536]; /* 1 big packet */
+void printpacket __P((ip_t *));
-printpacket(ip)
+void printpacket(ip)
ip_t *ip;
{
tcphdr_t *t;
@@ -58,9 +64,10 @@ ip_t *ip;
printf(",%d", t->th_sport);
printf(" dst %s", inet_ntoa(ip->ip_dst));
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
- printf(",%d", t->th_sport);
+ printf(",%d", t->th_dport);
if (ip->ip_p == IPPROTO_TCP) {
- printf(" seq %u:%u flags ", t->th_seq, t->th_ack);
+ printf(" seq %lu:%lu flags ",
+ (u_long)t->th_seq, (u_long)t->th_ack);
for (j = 0, i = 1; i < 256; i *= 2, j++)
if (t->th_flags & i)
printf("%c", "FSRPAU--"[j]);
@@ -71,6 +78,7 @@ ip_t *ip;
int ip_resend(dev, mtu, r, gwip, datain)
char *dev;
+int mtu;
struct in_addr gwip;
struct ipread *r;
char *datain;
@@ -91,7 +99,7 @@ char *datain;
ip = (struct ip *)buf;
eh = (ether_header_t *)malloc(sizeof(*eh));
- bzero(&eh->ether_shost, sizeof(eh->ether_shost));
+ bzero((char *)A_A eh->ether_shost, sizeof(eh->ether_shost));
if (gwip.s_addr && (arp((char *)&gwip, dhost) == -1))
{
perror("arp");
@@ -100,21 +108,31 @@ char *datain;
while ((i = (*r->r_readip)(buf, sizeof(buf), NULL, NULL)) > 0)
{
- len = ntohs(ip->ip_len);
- eh = (ether_header_t *)realloc((char *)eh, sizeof(*eh) + len);
- eh->ether_type = htons((u_short)ETHERTYPE_IP);
- if (!gwip.s_addr) {
- if (arp((char *)&gwip,
- (char *)&eh->ether_dhost) == -1) {
- perror("arp");
- continue;
- }
- } else
- bcopy(dhost, (char *)&eh->ether_dhost, sizeof(dhost));
- bcopy(ip, (char *)(eh + 1), len);
- printpacket(ip);
+ if (!(opts & OPT_RAW)) {
+ len = ntohs(ip->ip_len);
+ eh = (ether_header_t *)realloc((char *)eh, sizeof(*eh) + len);
+ eh->ether_type = htons((u_short)ETHERTYPE_IP);
+ if (!gwip.s_addr) {
+ if (arp((char *)&gwip,
+ (char *)A_A eh->ether_dhost) == -1) {
+ perror("arp");
+ continue;
+ }
+ } else
+ bcopy(dhost, (char *)A_A eh->ether_dhost,
+ sizeof(dhost));
+ if (!ip->ip_sum)
+ ip->ip_sum = chksum((u_short *)ip,
+ ip->ip_hl << 2);
+ bcopy(ip, (char *)(eh + 1), len);
+ len += sizeof(*eh);
+ printpacket(ip);
+ } else {
+ eh = (ether_header_t *)buf;
+ len = i;
+ }
- if (sendip(wfd, eh, sizeof(*eh) + len) == -1)
+ if (sendip(wfd, (char *)eh, len) == -1)
{
perror("send_packet");
break;
diff --git a/usr.sbin/ipsend/ipsend/Makefile b/usr.sbin/ipsend/ipsend/Makefile
index 4b2770b47ac..26e3192a88e 100644
--- a/usr.sbin/ipsend/ipsend/Makefile
+++ b/usr.sbin/ipsend/ipsend/Makefile
@@ -1,10 +1,14 @@
-# $Id: Makefile,v 1.1 1996/05/10 21:40:58 dm Exp $
+# $OpenBSD: Makefile,v 1.2 1998/01/26 04:17:01 dgregor Exp $
PROG= ipsend
BINDIR= /usr/sbin
-NOMAN=
-SRCS= ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c
-CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest
+MAN= ipsend.1 ipsend.5
+SRCS= ipsend.c ip.c ipsopt.c sbpf.c sock.c 44arp.c iplang_y.y iplang_l.l
+CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest \
+ -I${.CURDIR}/../../../sbin/ipf -I${.CURDIR}/../../../sys/netinet
+LDADD = -lfl
+CLEANFILES+=y.tab.h
+
.PATH: ${.CURDIR}/../common
.include <bsd.prog.mk>
diff --git a/usr.sbin/ipsend/ipsend/iplang_l.l b/usr.sbin/ipsend/ipsend/iplang_l.l
new file mode 100644
index 00000000000..c4dcad9fe3e
--- /dev/null
+++ b/usr.sbin/ipsend/ipsend/iplang_l.l
@@ -0,0 +1,312 @@
+%e 1500
+%p 4000
+%a 4000
+%o 6000
+%{
+/* $OpenBSD: iplang_l.l,v 1.1 1998/01/26 04:17:01 dgregor Exp $ */
+/*
+ * 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 1.1 1998/01/26 04:17:01 dgregor 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_fil_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); }
+\377 { return 0; } /* EOF */
+\{ { 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()
+{
+
+ 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/usr.sbin/ipsend/ipsend/iplang_y.y b/usr.sbin/ipsend/ipsend/iplang_y.y
new file mode 100644
index 00000000000..ace441a6366
--- /dev/null
+++ b/usr.sbin/ipsend/ipsend/iplang_y.y
@@ -0,0 +1,1840 @@
+%{
+/* $OpenBSD: iplang_y.y,v 1.1 1998/01/26 04:17:02 dgregor Exp $ */
+/*
+ * 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 1.1 1998/01/26 04:17:02 dgregor 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_fil_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 <str> IL_IPS_RESERV4 IL_IPS_TOPSECRET IL_IPS_SECRET IL_IPS_RESERV3
+%token <str> 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(&$2); }
+ | IL_MTU number { set_ifmtu($2); }
+ | IL_V4ADDR token { set_ifv4addr(&$2); }
+ | IL_EADDR token { set_ifeaddr(&$2); }
+ ;
+
+send: sendhdr '{' sendbody '}' ';' { packet_done(); }
+ | sendhdr ';' { packet_done(); }
+ ;
+
+sendhdr:
+ IL_SEND { reset_send(); }
+ ;
+
+sendbody:
+ sendopt
+ | sendbody sendopt
+ ;
+
+sendopt:
+ IL_IFNAME token { set_sendif(&$2); }
+ | IL_VIA token { set_sendvia(&$2); }
+ ;
+
+arp: arphdr '{' arpbody '}' ';'
+ ;
+
+arphdr: IL_ARP { new_arp(); }
+ ;
+
+arpbody:
+ arpopt
+ | arpbody arpopt
+ ;
+
+arpopt: IL_V4ADDR token { set_arpv4addr(&$2); }
+ | IL_EADDR token { set_arpeaddr(&$2); }
+ ;
+
+defrouter:
+ IL_DEFROUTER token { set_defaultrouter(&$2); }
+ ;
+
+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(&$2); }
+ | IL_V4SRC token { set_ipv4src(&$2); }
+ | IL_V4DST token { set_ipv4dst(&$2); }
+ | IL_V4OFF token { set_ipv4off(&$2); }
+ | IL_V4V token { set_ipv4v(&$2); }
+ | IL_V4HL token { set_ipv4hl(&$2); }
+ | IL_V4ID token { set_ipv4id(&$2); }
+ | IL_V4TTL token { set_ipv4ttl(&$2); }
+ | IL_V4TOS token { set_ipv4tos(&$2); }
+ | IL_V4SUM token { set_ipv4sum(&$2); }
+ | IL_V4LEN token { set_ipv4len(&$2); }
+ | ipv4opt '{' ipv4optlist '}' ';' { end_ipopt(); }
+ ;
+
+tcp: IL_TCP { new_tcpheader(); }
+ ;
+
+tcpline:
+ '{' tcpheader '}' ';' { end_tcp(); }
+ ;
+
+tcpheader:
+ tcpbody
+ | tcpbody tcpheader
+ | bodyline
+ ;
+
+tcpbody:
+ IL_SPORT token { set_tcpsport(&$2); }
+ | IL_DPORT token { set_tcpdport(&$2); }
+ | IL_TCPSEQ token { set_tcpseq(&$2); }
+ | IL_TCPACK token { set_tcpack(&$2); }
+ | IL_TCPOFF token { set_tcpoff(&$2); }
+ | IL_TCPURP token { set_tcpurp(&$2); }
+ | IL_TCPWIN token { set_tcpwin(&$2); }
+ | IL_TCPSUM token { set_tcpsum(&$2); }
+ | IL_TCPFL token { set_tcpflags(&$2); }
+ | 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,&$2);}
+ | IL_TCPO_WSCALE optoken { set_tcpopt(IL_TCPO_MSS,&$2);}
+ | IL_TCPO_TS optoken { set_tcpopt(IL_TCPO_TS, &$2);}
+ ;
+
+udp: IL_UDP { new_udpheader(); }
+ ;
+
+udpline:
+ '{' udpheader '}' ';' { end_udp(); }
+ ;
+
+
+udpheader:
+ udpbody
+ | udpbody udpheader
+ | bodyline
+ ;
+
+udpbody:
+ IL_SPORT token { set_tcpsport(&$2); }
+ | IL_DPORT token { set_tcpdport(&$2); }
+ | IL_UDPLEN token { set_udplen(&$2); }
+ | IL_UDPSUM token { set_udpsum(&$2); }
+ ;
+
+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(&$2); }
+ ;
+
+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(&$1); }
+ ;
+
+icmpechoopts:
+ | icmpechoopts icmpecho
+ ;
+
+icmpecho:
+ IL_ICMP_SEQ number { set_icmpseq($2); }
+ | IL_ICMP_ID number { set_icmpid($2); }
+ ;
+
+icmptsopts:
+ | icmptsopts icmpts ';'
+ ;
+
+icmpts: IL_ICMP_OTIME number { set_icmpotime($2); }
+ | IL_ICMP_RTIME number { set_icmprtime($2); }
+ | IL_ICMP_TTIME number { set_icmpttime($2); }
+ ;
+
+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($2); }
+ | 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, &$2); }
+ | IL_ICMP_REDIRECT_HOST token { set_redir(1, &$2); }
+ | IL_ICMP_REDIRECT_TOSNET token { set_redir(2, &$2); }
+ | IL_ICMP_REDIRECT_TOSHOST token { set_redir(3, &$2); }
+ ;
+
+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($2); }
+ ;
+
+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, &$2); }
+ | 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,&$2); }
+ | 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,&$2);}
+ | IL_IPO_SSRR token { add_ipopt(IL_IPO_SSRR,&$2); }
+ | 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(&$1); }
+ | IL_IPS_TOPSECRET ';' { set_secclass(&$1); }
+ | IL_IPS_SECRET ';' { set_secclass(&$1); }
+ | IL_IPS_RESERV3 ';' { set_secclass(&$1); }
+ | IL_IPS_CONFID ';' { set_secclass(&$1); }
+ | IL_IPS_UNCLASS ';' { set_secclass(&$1); }
+ | IL_IPS_RESERV2 ';' { set_secclass(&$1); }
+ | IL_IPS_RESERV1 ';' { set_secclass(&$1); }
+ ;
+
+data: IL_DATA { new_data(); }
+ ;
+
+dataline:
+ '{' databody '}' ';' { end_data(); }
+ ;
+
+databody: dataopts
+ | dataopts databody
+ ;
+
+dataopts:
+ IL_DLEN token { set_datalen(&$2); }
+ | IL_DVALUE token { set_data(&$2); }
+ | IL_DFILE token { set_datafile(&$2); }
+ ;
+
+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
+
+
+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 htons(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;
+ }
+
+ if (canip)
+ 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;
+}
diff --git a/usr.sbin/ipsend/ipsend/ipsend.1 b/usr.sbin/ipsend/ipsend/ipsend.1
new file mode 100644
index 00000000000..8acb6821060
--- /dev/null
+++ b/usr.sbin/ipsend/ipsend/ipsend.1
@@ -0,0 +1,110 @@
+.\" $OpenBSD: ipsend.1,v 1.1 1998/01/26 04:17:03 dgregor Exp $
+.TH IPSEND 1
+.SH NAME
+ipsend \- sends IP packets
+.SH SYNOPSIS
+.B ipsend
+[
+.B \-dITUv
+] [
+.B \-i
+<interface>
+] [
+.B \-f
+<\fIoffset\fP>
+] [
+.B \-g
+<\fIgateway\fP>
+] [
+.B \-m
+<\fIMTU\fP>
+] [
+.B \-o
+<\fIoption\fP>
+] [
+.B \-P
+<protocol>
+] [
+.B \-s
+<\fIsource\fP>
+] [
+.B \-t
+<\fIdest. port\fP>
+] [
+.B \-w
+<\fIwindow\fP>
+] <destination> [TCP-flags]
+.SH DESCRIPTION
+.PP
+\fBipsend\fP can be compiled in two ways. The first is used to send one-off
+packets to a destination host, using command line options to specify various
+attributes present in the headers. The \fIdestination\fP must be given as
+the last command line option, except for when TCP flags are specified as
+a combination of A, S, F, U, P and R, last.
+.PP
+The other way it may be compiled, with DOSOCKET defined, is to allow an
+attempt at making a TCP connection using a with ipsend resending the SYN
+packet as per the command line options.
+.SH OPTIONS
+.TP
+.BR \-d
+enable debugging mode.
+.TP
+.BR \-f \0<offset>
+The \fI-f\fP allows the IP offset field in the IP header to be set to an
+arbitrary value, which can be specified in decimal or hexidecimal.
+.TP
+.BR \-g \0<gateway>
+Specify the hostname of the gateway through which to route packets. This
+is required whenever the destination host isn't directly attached to the
+same network as the host from which you're sending.
+.TP
+.BR \-i \0<interface>
+Set the interface name to be the name supplied.
+.TP
+.TP
+.BR \-m \0<MTU>
+Specify the MTU to be used when sending out packets. This option allows you
+to set a fake MTU, allowing the simulation of network interfaces with small
+MTU's without setting them so.
+.TP
+.BR \-o \0<option>
+Specify options to be included at the end of the IP header. An EOL option
+is automatically appended and need not be given. If an option would also
+have data associated with it (source as an IP# for a lsrr option), then
+this will not be initialised.
+.TP
+.BR \-s \0<source>
+Set the source address in the packet to that provided - maybe either a
+hostname or IP#.
+.TP
+.BR \-t \0<dest. port>
+Set the destination port for TCP/UDP packets.
+.TP
+.BR \-w \0<window>
+Set the window size for TCP packets.
+.TP
+.B \-I
+Set the protocol to ICMP.
+.TP
+.B \-P <protocol>
+Set the protocol to the value given. If the parameter is a name, the name
+is looked up in the \fI/etc/protocols\fP file.
+.TP
+.B \-T
+Set the protocol to TCP.
+.TP
+.B \-U
+Set the protocol to UDP.
+.TP
+.BR \-d
+enable verbose mode.
+.DT
+.SH SEE ALSO
+ipsend(1), ipresend(1), iptest(1), protocols(4), bpf(4), dlpi(7p)
+.SH DIAGNOSTICS
+.PP
+Needs to be run as root.
+.SH BUGS
+.PP
+If you find any, please send email to me at darrenr@cyber.com.au
diff --git a/usr.sbin/ipsend/ipsend/ipsend.5 b/usr.sbin/ipsend/ipsend/ipsend.5
new file mode 100644
index 00000000000..dae402b4f05
--- /dev/null
+++ b/usr.sbin/ipsend/ipsend/ipsend.5
@@ -0,0 +1,399 @@
+.\" $OpenBSD: ipsend.5,v 1.1 1998/01/26 04:17:03 dgregor Exp $
+.TH IPSEND 5
+.SH NAME
+ipsend \- IP packet description language
+.SH DESCRIPTION
+The \fBipsend\fP program expects, with the \fB-L\fP option, input to be a
+text file which fits the grammar described below. The purpose of this
+grammar is to allow IP packets to be described in an arbitary way which
+also allows encapsulation to be so done to an arbitary level.
+.SH GRAMMAR
+.LP
+.nf
+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 .
+.fi
+.SH COMMANDS
+.PP
+Before sending any packets or defining any packets, it is necessary to
+describe the interface(s) which will be used to send packets out.
+.TP
+.B interface
+is used to describe a network interface. The description included need
+not match the actual configuration currently employed by the operating
+system.
+.TP
+.B send
+is used to actually send out a packet across the network. If the
+destination is not specified, it will attempt to send the packet
+directly out on the network to the destination without routing it.
+.TP
+.B router
+configures the default router for ipsend, as distinct from the default
+route installed in the kernel.
+.TP
+.B ipv4
+is used to describe an IP (version 4) packet. IP header fields can be
+specified, including options, followed by a data section which may contain
+further protocol headers.
+.SH IPV4
+.TP
+.B hl <number>
+manually specifies the IP header length (automatically adjusts with the
+presence of IP options and defaults to 5);
+.TP
+.B v <number>
+set the IP version. Default is 4.
+.TP
+.B tos <number>
+set the type of service (TOS) field in the IP header. Default is 0.
+.TP
+.B len <number>
+manually specifies the length of the IP packet. The length will automatically
+be adjusted to accomodate data or further protocol headers.
+.TP
+.B off <number>
+sets the fragment offset field of the IP packet. Default is 0.
+.TP
+.B ttl <number>
+sets the time to live (TTL) field of the IP header. Default is 60.
+.TP
+.B proto <protocol>
+sets the protocol field of the IP header. The protocol can either be a
+number or a name found in \fB/etc/protocols\fP.
+.TP
+.B sum
+manually specifies the checksum for the IP header. If left unset (0), it
+will be calculated prior to being sent.
+.TP
+.B src
+manually specifies the source address of the IP header. If left unset, it
+will default to the host's IP address.
+.TP
+.B dst
+sets the destination of the IP packet. The default is 0.0.0.0.
+.TP
+.B opt
+is used to include IP options in the IP header.
+.TP
+.B tcp
+is used to indicate the a TCP protocol header is to follow. See the \fBTCP\fP
+section for TCP header options.
+.TP
+.B udp
+is used to indicate the a UDP protocol header is to follow. See the \fBUDP\fP
+section for UDP header options.
+.TP
+.B icmp
+is used to indicate the a ICMP protocol header is to follow. See the
+\fBICMP\fP section for ICMP header options.
+.TP
+.B data
+is used to indicate that raw data is to be included in the IP packet. See the
+\fBDATA\fP section for details on options available.
+.SH "IPv4 Options"
+these keywords indicate that the releveant IP option should be added to the
+IP header (the header length field will be adjusted appropriately).
+.TP
+.B nop
+No Operation [RFC 791] (space filler).
+.TP
+.B rr <number>
+Record Router [RFC 791]. The number given specifies the number of
+\fBbytes\fP to be used for storage. This should be a multiple of 4 for
+proper operation.
+.TP
+.B zsu
+Experimental Measurement.
+.TP
+.B mtup [RFC 1191].
+MTU Probe.
+.TP
+.B mtur [RFC 1191].
+MTU Ready.
+.TP
+.B encode
+.TP
+.B ts
+Timestamp [RFC 791].
+.TP
+.B tr
+Traceroute [RFC 1393].
+.TP
+.B "sec-class <security-level>, sec"
+Security [RFC 1108]. This option specifies the security label for the packet.
+Using \fBsec\fP sets up the framework of the security option but unless
+\fBsec-class\fP is given, the level may not be set.
+.TP
+.B "lsrr <ip-address>"
+Loose Source Route [RFC 791].
+.TP
+.B e-sec
+Extended Security [RFC 1108].
+.TP
+.B cipso
+Commercial Security.
+.TP
+.B satid
+Stream ID [RFC 791].
+.TP
+.B "ssrr <ip-address>"
+Strict Source Route [RFC 791].
+.TP
+.B addext
+Address Extension
+.TP
+.B visa
+Expermental Access Control.
+.TP
+.B imitd
+IMI Traffic Descriptor.
+.TP
+.B eip
+[RFC 1358].
+.TP
+.B finn
+Experimental Flow Control.
+.SH TCP
+.TP
+.B sport <port>
+sets the source port to the number/name given. Default is 0.
+.TP
+.B dport <port>
+sets the destination port to the number/name given. Default is 0.
+.TP
+.B seq <number>
+sets the sequence number to the number specified. Default is 0.
+.TP
+.B ack <number>
+sets the acknowledge number to the number specified. Default is 0.
+.TP
+.B off <number>
+sets the offset value for the start of data to the number specified. This
+implies the size of the TCP header. It is automatically adjusted if TCP
+options are included and defaults to 5.
+.TP
+.B urp <number>
+sets the value of the urgent data pointer to the number specified. Default
+is 0.
+.TP
+.B win <number>
+sets the size of the TCP window to the number specified. Default is 4096.
+.TP
+.B sum <number>
+manually specifies the checksum for the TCP pseudo-header and data. If left
+unset, it defaults to 0 and is automatically calculated.
+.TP
+.B flags <tcp-flags>
+sets the TCP flags field to match the flags specified. Valid flags are
+"S" (SYN), "A" (ACK), "R" (RST), "F" (FIN), "U" (URG), "P" (PUSH).
+.TP
+.B opt
+indicates that TCP header options follow. As TCP options are added to the
+TCP header, the \fBoff\fP field is updated to match.
+.TP
+.B data
+indicates that a data section is to follow and is to be included as raw
+data, being appended to the header.
+.SH "TCP options"
+With a TCP header, it is possible to append a number of header options.
+The TCP header offset will be updated automatically to reflect the change
+in size. The valid options are: \fBnop\fP No Operation,
+\fBeol\fP End Of (option) List, \fBmss [ size ]\fP Maximum Segment Size - this
+sets the maximum receivable size of a packet containing data,
+\fBwscale\fP Window Scale, \fBts\fP Timestamp.
+.SH UDP
+.TP
+.B sport <port>
+sets the source port to the number/name given. Default is 0.
+.TP
+.B dport <port>
+sets the destination port to the number/name given. Default is 0.
+.TP
+.B len <number>
+manually specifies the length of the UDP header and data. If left unset,
+it is automatically adjusted to match the header presence and any data if
+present.
+.TP
+.B sum <number>
+manually specifies the checksum for the UDP pseudo-header and data. If left
+unset, it defaults to 0 and is automatically calculated.
+.TP
+.B data
+indicates that a data section is to follow and is to be included as raw
+data, being appended to the header.
+.SH ICMP
+.TP
+.B type <icmptype>
+sets the ICMP type according the to the icmptype tag. This may either be
+a number or one of the recognised tags (see the \fBICMP TYPES\fP section for a
+list of names recognised).
+.TP
+.B code <icmpcode>
+sets the ICMP code.
+.TP
+.B data
+indicates that a data section is to follow and is to be included as raw
+data, being appended to the header.
+.SH DATA
+Each of the following extend the packet in a different way. \fBLen\fP just
+increases the length (without adding any content), \fBvalue\fP uses a string
+and \fBfile\fP a file.
+.TP
+.B len <number>
+extend the length of the packet by \fBnumber\fP bytes (without filling those
+bytes with any particular data).
+.TP
+.B value <string>
+indicates that the string provided should be added to the current packet as
+data. A string may be a consecutive list of characters and numbers (with
+no white spaces) or bounded by "'s (may not contain them, even if \\'d).
+The \\ charcater is recognised with the appropriate C escaped values, including
+octal numbers.
+.TP
+.B file <filename>
+reads data in from the specified file and appends it to the current packet.
+If the new total length would exceed 64k, an error will be reported.
+.SH "ICMP TYPES"
+.TP
+.B echorep
+Eecho Reply.
+.TP
+.B "unreach [ unreachable-code ]"
+Generic Unreachable error. This is used to indicate that an error has
+occurred whilst trying to send the packet across the network and that the
+destination cannot be reached. The unreachable code names are:
+\fBnet-unr\fP network unreachable, \fBhost-unr\fP host unreachable,
+\fBproto-unr\fP protocol unreachable, \fBport-unr\fP port unreachable,
+\fBneedfrag\fP, \fBsrcfail\fP source route failed,
+\fBnet-unk\fP network unknown, \fBhost-unk\fP host unknown,
+\fBisolate\fP, \fBnet-prohib\fP administratively prohibited contact with
+network,
+\fBhost-prohib\fP administratively prohibited contact with host,
+\fBnet-tos\fP network unreachable with given TOS,
+\fBhost-tos\fP host unreachable with given TOS,
+\fBfilter-prohib\fP packet prohibited by packet filter,
+\fBhost-preced\fP,
+\fBcutoff-preced\fP.
+.TP
+.B squench
+Source Quence.
+.TP
+.B "redir [ redirect-code ]"
+Redirect (routing). This is used to indicate that the route being chosen
+for forwarding the packet is suboptimal and that the sender of the packet
+should be routing packets via another route. The redirect code names are:
+\fBnet-redir\fP redirect packets for a network,
+\fBhost-redir\fP redirect packets for a host,
+\fBtos-net-redir\fP redirect packets for a network with a given TOS,
+\fBtos-host-redir\fP redirect packets for a host with a given TOS.
+.TP
+.B echo
+Echo.
+.TP
+.B routerad
+Router Advertisment.
+.TP
+.B routersol
+Router solicitation.
+.TP
+.B "timex [ timexceed-code ]"
+Time Exceeded. This is used to indicate that the packet failed to reach the
+destination because it was in transit too long (i.e. ttl reached 0). The
+valid code names are: \fBintrans\fP,
+\fBreass\fP could not reassemble packet from fragments within a given time.
+.TP
+.B "paramprob [ paramprob-code ]"
+Parameter problem. There is only one available parameter problem code name:
+\fBoptabsent\fP.
+.TP
+.B timest
+Time stamp request.
+.TP
+.B "timestrep [ { timestamp-code } ]"
+Time stamp reply. In a timestamp reply, it is possible to supply the
+following values: \fBrtime\fP, \fBotime\fP, \fBttime\fP.
+.TP
+.B inforeq
+Information request.
+.TP
+.B inforep
+Information reply.
+.TP
+.B maskreq
+Address mask request.
+.TP
+.B maskrep
+Address mask reply.
+.SH FILES
+/etc/protocols
+/etc/services
+/etc/hosts
+.SH SEE ALSO
diff --git a/usr.sbin/ipsend/ipsend/ipsend.c b/usr.sbin/ipsend/ipsend/ipsend.c
index afd41fa8a58..af87ff1410e 100644
--- a/usr.sbin/ipsend/ipsend/ipsend.c
+++ b/usr.sbin/ipsend/ipsend/ipsend.c
@@ -1,30 +1,30 @@
+/* $OpenBSD: ipsend.c,v 1.5 1998/01/26 04:17:04 dgregor Exp $ */
/*
- * ipsend.c (C) 1995 Darren Reed
+ * ipsend.c (C) 1995-1997 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
- * The author provides this program as-is, with no gaurantee for its
- * suitability for any specific purpose. The author takes no responsibility
- * for the misuse/abuse of this program and provides it for the sole purpose
- * of testing packet filter policies. This file maybe distributed freely
- * providing it is not modified and that this notice remains in tact.
- *
- * This was written and tested (successfully) on SunOS 4.1.x.
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: ipsend.c,v 1.5 1998/01/26 04:17:04 dgregor Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -32,20 +32,18 @@ static char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
-#include <netinet/tcpip.h>
-#endif
-#include "ip_compat.h"
-#ifdef linux
-#include <linux/sockios.h>
-#include "tcpip.h"
#endif
-#include "ipt.h"
+#include "ip_fil_compat.h"
+#include "ipsend.h"
+#include "ipf.h"
extern char *optarg;
extern int optind;
+extern void iplang __P((FILE *));
char options[68];
+int opts;
#ifdef linux
char default_device[] = "eth0";
#else
@@ -58,19 +56,29 @@ char default_device[] = "ln0";
# ifdef __bsdi__
char default_device[] = "ef0";
# else
+# ifdef __sgi
+char default_device[] = "ec0";
+# else
char default_device[] = "lan0";
+# endif
# endif
# endif
# endif
#endif
-void usage(prog)
+static void usage __P((char *));
+static void do_icmp __P((ip_t *, char *));
+int main __P((int, char **));
+
+
+static void usage(prog)
char *prog;
{
fprintf(stderr, "Usage: %s [options] dest [flags]\n\
\toptions:\n\
-\t\t-d device\tSend out on this device\n\
+\t\t-d\tdebug mode\n\
+\t\t-i device\tSend out on this device\n\
\t\t-f fragflags\tcan set IP_MF or IP_DF\n\
\t\t-g gateway\tIP gateway to use if non-local dest.\n\
\t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\
@@ -80,12 +88,20 @@ char *prog;
\t\t-T\t\tSet TCP protocol\n\
\t\t-t port\t\tdestination port\n\
\t\t-U\t\tSet UDP protocol\n\
+\t\t-v\tverbose mode\n\
+\t\t-w <window>\tSet the TCP window size\n\
+", prog);
+ fprintf(stderr, "Usage: %s [-dv] -L <filename>\n\
+\toptions:\n\
+\t\t-d\tdebug mode\n\
+\t\t-L filename\tUse IP language for sending packets\n\
+\t\t-v\tverbose mode\n\
", prog);
exit(1);
}
-void do_icmp(ip, args)
+static void do_icmp(ip, args)
ip_t *ip;
char *args;
{
@@ -153,17 +169,18 @@ struct in_addr gwip;
}
-main(argc, argv)
+int main(argc, argv)
int argc;
char **argv;
{
+ FILE *langfile = NULL;
struct tcpiphdr *ti;
struct in_addr gwip;
tcphdr_t *tcp;
ip_t *ip;
char *name = argv[0], host[64], *gateway = NULL, *dev = NULL;
char *src = NULL, *dst, *s;
- int mtu = 1500, olen = 0, c;
+ int mtu = 1500, olen = 0, c, nonl = 0;
/*
* 65535 is maximum packet size...you never know...
@@ -174,10 +191,11 @@ char **argv;
ip->ip_len = sizeof(*ip);
ip->ip_hl = sizeof(*ip) >> 2;
- while ((c = getopt(argc, argv, "IP:TUd:f:g:m:o:s:t:")) != -1)
+ while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1)
switch (c)
{
case 'I' :
+ nonl++;
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
@@ -186,10 +204,26 @@ char **argv;
}
do_icmp(ip, optarg);
break;
+ case 'L' :
+ if (nonl) {
+ fprintf(stderr,
+ "Incorrect usage of -L option.\n");
+ usage(name);
+ }
+ if (!strcmp(optarg, "-"))
+ langfile = stdin;
+ else if (!(langfile = fopen(optarg, "r"))) {
+ fprintf(stderr, "can't open file %s\n",
+ optarg);
+ exit(1);
+ }
+ iplang(langfile);
+ return 0;
case 'P' :
{
struct protoent *p;
+ nonl++;
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
@@ -204,6 +238,7 @@ char **argv;
break;
}
case 'T' :
+ nonl++;
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
@@ -214,6 +249,7 @@ char **argv;
ip->ip_len += sizeof(tcphdr_t);
break;
case 'U' :
+ nonl++;
if (ip->ip_p)
{
fprintf(stderr, "Protocol already set: %d\n",
@@ -224,15 +260,22 @@ char **argv;
ip->ip_len += sizeof(udphdr_t);
break;
case 'd' :
- dev = optarg;
+ opts |= OPT_DEBUG;
break;
case 'f' :
+ nonl++;
ip->ip_off = strtol(optarg, NULL, 0);
break;
case 'g' :
+ nonl++;
gateway = optarg;
break;
+ case 'i' :
+ nonl++;
+ dev = optarg;
+ break;
case 'm' :
+ nonl++;
mtu = atoi(optarg);
if (mtu < 28)
{
@@ -241,16 +284,23 @@ char **argv;
}
break;
case 'o' :
- olen = optname(optarg, options);
+ nonl++;
+ olen = buildopts(optarg, options, (ip->ip_hl - 5) << 2);
break;
case 's' :
+ nonl++;
src = optarg;
break;
case 't' :
+ nonl++;
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
tcp->th_dport = htons(atoi(optarg));
break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
case 'w' :
+ nonl++;
if (ip->ip_p == IPPROTO_TCP)
tcp->th_win = atoi(optarg);
else
@@ -291,8 +341,25 @@ char **argv;
exit(2);
}
+ if (olen)
+ {
+ caddr_t ipo = (caddr_t)ip;
+
+ printf("Options: %d\n", olen);
+ ti = (struct tcpiphdr *)malloc(olen + ip->ip_len);
+ bcopy((char *)ip, (char *)ti, sizeof(*ip));
+ ip = (ip_t *)ti;
+ ip->ip_hl = (olen >> 2);
+ bcopy(options, (char *)(ip + 1), olen);
+ bcopy((char *)tcp, (char *)(ip + 1) + olen, sizeof(*tcp));
+ ip->ip_len += olen;
+ bcopy((char *)ip, (char *)ipo, ip->ip_len);
+ ip = (ip_t *)ipo;
+ tcp = (tcphdr_t *)((char *)(ip + 1) + olen);
+ }
+
if (ip->ip_p == IPPROTO_TCP)
- for (s = argv[optind]; c = *s; s++)
+ for (s = argv[optind]; (c = *s); s++)
switch(c)
{
case 'S' : case 's' :
@@ -325,22 +392,9 @@ char **argv;
printf("Flags: %#x\n", tcp->th_flags);
printf("mtu: %d\n", mtu);
- if (olen)
- {
- printf("Options: %d\n", olen);
- ti = (struct tcpiphdr *)malloc(olen + ip->ip_len);
- bcopy((char *)ip, (char *)ti, sizeof(*ip));
- ip = (ip_t *)ti;
- ip->ip_hl += (olen >> 2);
- bcopy(options, (char *)(ip + 1), olen);
- bcopy((char *)tcp, (char *)(ip + 1) + olen, sizeof(*tcp));
- tcp = (tcphdr_t *)((char *)(ip + 1) + olen);
- ip->ip_len += olen;
- }
-
#ifdef DOSOCKET
if (tcp->th_dport)
return do_socket(dev, mtu, ti, gwip);
#endif
- return send_packets(dev, mtu, ti, gwip);
+ return send_packets(dev, mtu, (ip_t *)ti, gwip);
}
diff --git a/usr.sbin/ipsend/ipsend/ipsopt.c b/usr.sbin/ipsend/ipsend/ipsopt.c
index 13d9e49d002..1d598f2757c 100644
--- a/usr.sbin/ipsend/ipsend/ipsopt.c
+++ b/usr.sbin/ipsend/ipsend/ipsopt.c
@@ -1,34 +1,45 @@
+/* $OpenBSD: ipsopt.c,v 1.2 1998/01/26 04:17:06 dgregor Exp $ */
/*
- * (C)opyright 1995 by Darren Reed.
+ * Copyright (C) 1995-1997 by Darren Reed.
*
- * This code may be freely distributed as long as it retains this notice
- * and is not changed in any way. The author accepts no responsibility
- * for the use of this software. I hate legaleese, don't you ?
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: ipsopt.c,v 1.2 1998/01/26 04:17:06 dgregor Exp $";
#endif
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#include "ip_compat.h"
+#ifndef linux
+#include <netinet/ip_var.h>
+#endif
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include "ipsend.h"
+
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
-struct ipopt_names {
- int on_value;
- int on_bit;
- int on_siz;
- char *on_name;
-};
struct ipopt_names ionames[] = {
{ IPOPT_EOL, 0x01, 1, "eol" },
{ IPOPT_NOP, 0x02, 1, "nop" },
- { IPOPT_RR, 0x04, 7, "rr" }, /* 1 route */
+ { IPOPT_RR, 0x04, 3, "rr" }, /* 1 route */
{ IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */
{ IPOPT_SECURITY, 0x08, 11, "sec-level" },
{ IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */
@@ -53,7 +64,6 @@ u_short seclevel(slevel)
char *slevel;
{
struct ipopt_names *so;
- u_short level = 0;
for (so = secnames; so->on_name; so++)
if (!strcasecmp(slevel, so->on_name))
@@ -67,14 +77,82 @@ char *slevel;
}
-u_long optname(cp, op)
+int addipopt(op, io, len, class)
+char *op;
+struct ipopt_names *io;
+int len;
+char *class;
+{
+ struct in_addr ipadr;
+ int olen = len, srr = 0;
+ u_short val;
+ u_char lvl;
+ char *s = op, *t;
+
+ if ((len + io->on_siz) > 48) {
+ fprintf(stderr, "options too long\n");
+ return 0;
+ }
+ len += io->on_siz;
+ *op++ = io->on_value;
+ if (io->on_siz > 1) {
+ /*
+ * Allow option to specify RR buffer length in bytes.
+ */
+ if (io->on_value == IPOPT_RR) {
+ val = (class && *class) ? atoi(class) : 4;
+ *op++ = val + io->on_siz;
+ len += val;
+ } else
+ *op++ = io->on_siz;
+ *op++ = IPOPT_MINOFF;
+
+ while (class && *class) {
+ t = NULL;
+ switch (io->on_value)
+ {
+ case IPOPT_SECURITY :
+ lvl = seclevel(class);
+ *(op - 1) = lvl;
+ break;
+ case IPOPT_LSRR :
+ case IPOPT_SSRR :
+ if ((t = strchr(class, ',')))
+ *t = '\0';
+ ipadr.s_addr = inet_addr(class);
+ srr++;
+ bcopy((char *)&ipadr, op, sizeof(ipadr));
+ op += sizeof(ipadr);
+ break;
+ case IPOPT_SATID :
+ val = atoi(class);
+ bcopy((char *)&val, op, 2);
+ break;
+ }
+
+ if (t)
+ *t++ = ',';
+ class = t;
+ }
+ if (srr)
+ s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4 * srr;
+ if (io->on_value == IPOPT_RR)
+ op += val;
+ else
+ op += io->on_siz - 3;
+ }
+ return len - olen;
+}
+
+
+u_32_t buildopts(cp, op, len)
char *cp, *op;
+int len;
{
- struct ipopt_names *io, *so;
- u_short lvl;
- u_long msk = 0;
- char *s, *sec, *t;
- int len = 0;
+ struct ipopt_names *io;
+ u_32_t msk = 0;
+ char *s, *t;
+ int inc, lastop = -1;
for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) {
if ((t = strchr(s, '=')))
@@ -82,21 +160,10 @@ char *cp, *op;
for (io = ionames; io->on_name; io++) {
if (strcasecmp(s, io->on_name) || (msk & io->on_bit))
continue;
- if ((len + io->on_siz) > 48) {
- fprintf(stderr, "options too long\n");
- return 0;
- }
- len += io->on_siz;
- *op++ = io->on_value;
- if (io->on_siz > 1) {
- *op++ = io->on_siz;
- *op++ = IPOPT_MINOFF;
-
- if (t && !strcasecmp(s, "sec-level")) {
- lvl = seclevel(t);
- bcopy(&lvl, op, sizeof(lvl));
- }
- op += io->on_siz - 3;
+ lastop = io->on_value;
+ if ((inc = addipopt(op, io, len, t))) {
+ op += inc;
+ len += inc;
}
msk |= io->on_bit;
break;
@@ -106,7 +173,24 @@ char *cp, *op;
return 0;
}
}
- *op++ = IPOPT_EOL;
- len++;
+
+ if (len & 3) {
+ while (len & 3) {
+ *op++ = ((len & 3) == 3) ? IPOPT_EOL : IPOPT_NOP;
+ len++;
+ }
+ } else {
+ if (lastop != IPOPT_EOL) {
+ if (lastop == IPOPT_NOP)
+ *(op - 1) = IPOPT_EOL;
+ else {
+ *op++ = IPOPT_NOP;
+ *op++ = IPOPT_NOP;
+ *op++ = IPOPT_NOP;
+ *op = IPOPT_EOL;
+ len += 4;
+ }
+ }
+ }
return len;
}
diff --git a/usr.sbin/ipsend/iptest/Makefile b/usr.sbin/ipsend/iptest/Makefile
index 17cdef66a36..829a0ca4690 100644
--- a/usr.sbin/ipsend/iptest/Makefile
+++ b/usr.sbin/ipsend/iptest/Makefile
@@ -1,10 +1,11 @@
-# $Id: Makefile,v 1.1 1996/05/10 21:40:59 dm Exp $
+# $OpenBSD: Makefile,v 1.2 1998/01/26 04:17:08 dgregor Exp $
PROG= iptest
BINDIR= /usr/sbin
-NOMAN=
+MAN= iptest.1
SRCS= iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c
-CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest
+CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest \
+ -I${.CURDIR}/../../../sys/netinet -I${.CURDIR}/../../../sbin/ipf
.PATH: ${.CURDIR}/../common
.include <bsd.prog.mk>
diff --git a/usr.sbin/ipsend/iptest/iptest.1 b/usr.sbin/ipsend/iptest/iptest.1
new file mode 100644
index 00000000000..5e6c6b5754a
--- /dev/null
+++ b/usr.sbin/ipsend/iptest/iptest.1
@@ -0,0 +1,102 @@
+.\" $OpenBSD: iptest.1,v 1.1 1998/01/26 04:17:09 dgregor Exp $
+.TH IPTEST 1
+.SH NAME
+iptest \- automatically generate a packets to test IP functionality
+.SH SYNOPSIS
+.B iptest
+[
+.B \-1234567
+] [
+.B \-d
+<device>
+] [
+.B \-g
+<gateway>
+] [
+.B \-m
+<\fIMTU\fP>
+] [
+.B \-p
+<\fIpointtest\fP>
+] [
+.B \-s
+<\fIsource\fP>
+] <destination>
+.SH DESCRIPTION
+.PP
+\fBiptest\fP ...
+.SH OPTIONS
+.TP
+.B \-1
+Run IP test group #1. This group of tests generates packets with the IP
+header fields set to invalid values given other packet characteristics.
+The point tests are: 1 (ip_hl < ip_len), 2 (ip_hl > ip_len),
+3 (ip_v < 4), 4 (ip_v > 4), 5 (ip_len < packetsize, long packets),
+6 (ip_len > packet size, short packets), 7 (Zero length fragments),
+8 (packet > 64k after reassembly), 9 (IP offset with MSB set), 10 (ttl
+variations).
+.TP
+.B \-2
+Run IP test group #2. This group of tests generates packets with the IP
+options constructed with invalud values given other packet characteristics.
+The point tests are: 1 (option length > packet length), 2 (option length = 0).
+.TP
+.B \-3
+Run IP test group #3. This group of tests generates packets with the ICMP
+header fields set to non-standard values. The point tests are: 1 (ICMP types
+0-31 & 255), 2 (type 3 & code 0 - 31), 3 (type 4 & code 0, 127, 128, 255),
+4 (type 5 & code 0, 127, 128, 255), 5 (types 8-10,13-18 with codes 0, 127,
+128 and 255), 6 (type 12 & code 0, 127, 128, 129, 255) and 7 (type 3 & codes
+9-10, 13-14 and 17-18 - shortened packets).
+.TP
+.B \-4
+Run IP test group #4. This group of tests generates packets with the UDP
+header fields set to non-standard values. The point tests are: 1 (UDP length
+> packet size), 2 (UDP length < packetsize), 3 (sport = 0, 1, 32767, 32768,
+65535), 4 (dport = 0, 1, 32767, 32768, 65535) and 5 (sizeof(struct ip) <= MTU
+<= sizeof(struct udphdr) + sizeof(struct ip)).
+.TP
+.B \-5
+Run IP test group #5. This group of tests generates packets with the TCP
+header fields set to non-standard values. The point tests are: 1 (TCP flags
+variations, all combinations), 2 (seq = 0, 0x7fffffff, 0x8000000, 0xa0000000,
+0xffffffff), 3 (ack = 0, 0x7fffffff, 0x8000000, 0xa0000000, 0xffffffff),
+4 (SYN packet with window of 0, 32768, 65535), 5 (set urgent pointer to 1,
+0x7fff, 0x8000, 0xffff), 6 (data offset), 7 (sport = 0, 1, 32767, 32768,
+65535) and 8 (dport = 0, 1, 32767, 32768, 65535).
+.TP
+.B \-6
+Run IP test group #6. This test generates a large number of fragments in
+an attempt to exhaust the network buffers used for holding packets for later
+reassembly. WARNING: this may crash or cause serious performance degradation
+to the target host.
+.TP
+.B \-7
+Run IP test group #7. This test generates 1024 random IP packets with only
+the IP version, checksum, length and IP offset field correct.
+.TP
+.BR \-d \0<interface>
+Set the interface name to be the name supplied.
+.TP
+.BR \-g \0<gateway>
+Specify the hostname of the gateway through which to route packets. This
+is required whenever the destination host isn't directly attached to the
+same network as the host from which you're sending.
+.TP
+.BR \-m \0<MTU>
+Specify the MTU to be used when sending out packets. This option allows you
+to set a fake MTU, allowing the simulation of network interfaces with small
+MTU's without setting them so.
+.TP
+.B \-p <test>
+Run a...
+.DT
+.SH SEE ALSO
+ipsend(1), ipresend(1), bpf(4), dlpi(7p)
+.SH DIAGNOSTICS
+Only one of the numeric test options may be given when \fIiptest\fP is run.
+.PP
+Needs to be run as root.
+.SH BUGS
+.PP
+If you find any, please send email to me at darrenr@cyber.com.au
diff --git a/usr.sbin/ipsend/iptest/iptest.c b/usr.sbin/ipsend/iptest/iptest.c
index 85f2d27d542..c5ff22a15b9 100644
--- a/usr.sbin/ipsend/iptest/iptest.c
+++ b/usr.sbin/ipsend/iptest/iptest.c
@@ -1,30 +1,30 @@
+/* $OpenBSD: iptest.c,v 1.4 1998/01/26 04:17:10 dgregor Exp $ */
/*
- * ipsend.c (C) 1995 Darren Reed
+ * ipsend.c (C) 1995-1997 Darren Reed
*
* This was written to test what size TCP fragments would get through
* various TCP/IP packet filters, as used in IP firewalls. In certain
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
- * The author provides this program as-is, with no gaurantee for its
- * suitability for any specific purpose. The author takes no responsibility
- * for the misuse/abuse of this program and provides it for the sole purpose
- * of testing packet filter policies. This file maybe distributed freely
- * providing it is not modified and that this notice remains in tact.
- *
- * This was written and tested (successfully) on SunOS 4.1.x.
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: iptest.c,v 1.4 1998/01/26 04:17:10 dgregor Exp $";
#endif
#include <stdio.h>
-#include <stdlib.h>
#include <netdb.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -32,14 +32,11 @@ static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
#include <netinet/ip_icmp.h>
#ifndef linux
#include <netinet/ip_var.h>
-#include <netinet/tcpip.h>
#endif
-#include "ip_compat.h"
#ifdef linux
#include <linux/sockios.h>
-#include "tcpip.h"
#endif
-#include "ipt.h"
+#include "ipsend.h"
extern char *optarg;
@@ -58,15 +55,22 @@ char default_device[] = "ln0";
# ifdef __bsdi__
char default_device[] = "ef0";
# else
+# ifdef __sgi
+char default_device[] = "ec0";
+# else
char default_device[] = "lan0";
+# endif
# endif
# endif
# endif
#endif
+static void usage __P((char *));
+int main __P((int, char **));
-void usage(prog)
-char *prog;
+
+static void usage(prog)
+char *prog;
{
fprintf(stderr, "Usage: %s [options] dest\n\
\toptions:\n\
@@ -87,15 +91,15 @@ char *prog;
}
-main(argc, argv)
-int argc;
-char **argv;
+int main(argc, argv)
+int argc;
+char **argv;
{
struct tcpiphdr *ti;
struct in_addr gwip;
ip_t *ip;
char *name = argv[0], host[64], *gateway = NULL, *dev = NULL;
- char *src = NULL, *dst, *s;
+ char *src = NULL, *dst;
int mtu = 1500, tests = 0, pointtest = 0, c;
/*
@@ -106,7 +110,7 @@ char **argv;
ip->ip_len = sizeof(*ip);
ip->ip_hl = sizeof(*ip) >> 2;
- while ((c = getopt(argc, argv, "1234567IP:TUd:f:g:m:o:p:s:t:")) != -1)
+ while ((c = getopt(argc, argv, "1234567d:g:m:p:s:")) != -1)
switch (c)
{
case '1' :
@@ -143,7 +147,7 @@ char **argv;
usage(name);
}
- if (argc - optind < 2 && !tests)
+ if ((argc <= optind) || !argv[optind])
usage(name);
dst = argv[optind++];
@@ -185,20 +189,34 @@ char **argv;
switch (tests)
{
case 1 :
- return ip_test1(dev, mtu, ti, gwip, pointtest);
+ ip_test1(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
case 2 :
- return ip_test2(dev, mtu, ti, gwip, pointtest);
+ ip_test2(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
case 3 :
- return ip_test3(dev, mtu, ti, gwip, pointtest);
+ ip_test3(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
case 4 :
- return ip_test4(dev, mtu, ti, gwip, pointtest);
+ ip_test4(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
case 5 :
- return ip_test5(dev, mtu, ti, gwip, pointtest);
+ ip_test5(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
case 6 :
- return ip_test6(dev, mtu, ti, gwip, pointtest);
+ ip_test6(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
case 7 :
- return ip_test7(dev, mtu, ti, gwip, pointtest);
+ ip_test7(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ break;
default :
+ ip_test1(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ ip_test2(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ ip_test3(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ ip_test4(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ ip_test5(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ ip_test6(dev, mtu, (ip_t *)ti, gwip, pointtest);
+ ip_test7(dev, mtu, (ip_t *)ti, gwip, pointtest);
break;
}
return 0;
diff --git a/usr.sbin/ipsend/iptest/iptests.c b/usr.sbin/ipsend/iptest/iptests.c
index 9c74804963a..f18e77b2e70 100644
--- a/usr.sbin/ipsend/iptest/iptests.c
+++ b/usr.sbin/ipsend/iptest/iptests.c
@@ -1,18 +1,23 @@
+/* $OpenBSD: iptests.c,v 1.2 1998/01/26 04:17:11 dgregor Exp $ */
/*
- * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ * Copyright (C) 1993-1997 by Darren Reed.
*
- * This code may be freely distributed as long as it retains this notice
- * and is not changed in any way. The author accepts no responsibility
- * for the use of this software. I hate legaleese, don't you ?
+ * 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.
*/
-#ifndef lint
-static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)$Id: iptests.c,v 1.2 1998/01/26 04:17:11 dgregor Exp $";
#endif
#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
-#if !defined(solaris)
+#if !defined(solaris) && !defined(linux) && !defined(__sgi)
# define _KERNEL
# define KERNEL
# include <sys/file.h>
@@ -22,45 +27,59 @@ static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
# include <sys/user.h>
# include <sys/proc.h>
#endif
-#include <kvm.h>
-#include <sys/socket.h>
+#if !defined(ultrix) && !defined(hpux) && !defined(linux) && !defined(__sgi)
+# include <kvm.h>
+#endif
+#ifndef ultrix
+# include <sys/socket.h>
+#endif
+#if defined(solaris)
+# include <sys/stream.h>
+#endif
#include <sys/socketvar.h>
#ifdef sun
#include <sys/systm.h>
#include <sys/session.h>
#endif
#if BSD >= 199103
-#include <sys/sysctl.h>
-#include <sys/filedesc.h>
-#include <paths.h>
+# include <sys/sysctl.h>
+# include <sys/filedesc.h>
+# include <paths.h>
#endif
#include <netinet/in_systm.h>
#include <sys/socket.h>
#include <net/if.h>
-#include <net/route.h>
+#if defined(linux) && (LINUX >= 0200)
+# include <asm/atomic.h>
+#endif
+#if !defined(linux)
+# include <net/route.h>
+#else
+# define __KERNEL__ /* because there's a macro not wrapped by this */
+# include <net/route.h> /* in this file :-/ */
+#endif
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
-#include <netinet/if_ether.h>
-#include <netinet/ip_var.h>
-#include <netinet/in_pcb.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include "ip_compat.h"
-#ifdef linux
-#include "tcpip.h"
-#else
-#include <netinet/tcpip.h>
-# if defined(__SVR4) || defined(__svr4__)
-#include <sys/sysmacros.h>
-# endif
+#ifndef linux
+# include <netinet/ip_var.h>
+# include <netinet/in_pcb.h>
+# include <netinet/tcp_timer.h>
+# include <netinet/tcp_var.h>
#endif
+#if defined(__SVR4) || defined(__svr4__) || defined(__sgi)
+# include <sys/sysmacros.h>
+#endif
+#include "ipsend.h"
+
#define PAUSE() tv.tv_sec = 0; tv.tv_usec = 10000; \
(void) select(0, NULL, NULL, NULL, &tv)
+
void ip_test1(dev, mtu, ip, gwip, ptest)
char *dev;
int mtu;
@@ -70,7 +89,7 @@ int ptest;
{
struct timeval tv;
udphdr_t *u;
- int nfd, i, len, id = getpid();
+ int nfd, i = 0, len, id = getpid();
ip->ip_hl = sizeof(*ip) >> 2;
ip->ip_v = IPVERSION;
@@ -166,11 +185,11 @@ int ptest;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
printf("1.5.0 ip_len < packet size (size++, long packets)\n");
- for (; i < (ip->ip_len * 2); i++) {
+ for (; i < (ntohs(ip->ip_len) * 2); i++) {
ip->ip_id = htons(id++);
ip->ip_sum = 0;
- ip->ip_sum = chksum(ip, ip->ip_hl << 2);
- (void) send_ether(nfd, ip, i, gwip);
+ ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, (char *)ip, i, gwip);
printf("%d\r", i);
fflush(stdout);
PAUSE();
@@ -181,8 +200,8 @@ int ptest;
ip->ip_id = htons(id++);
ip->ip_len = htons(i);
ip->ip_sum = 0;
- ip->ip_sum = chksum(ip, ip->ip_hl << 2);
- (void) send_ether(nfd, ip, len, gwip);
+ ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, (char *)ip, len, gwip);
printf("%d\r", i);
fflush(stdout);
PAUSE();
@@ -200,8 +219,8 @@ int ptest;
ip->ip_id = htons(id++);
ip->ip_len = htons(i);
ip->ip_sum = 0;
- ip->ip_sum = chksum(ip, ip->ip_hl << 2);
- (void) send_ether(nfd, ip, len, gwip);
+ ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, (char *)ip, len, gwip);
printf("%d\r", i);
fflush(stdout);
PAUSE();
@@ -212,8 +231,8 @@ int ptest;
for (i = len; i > 0; i--) {
ip->ip_id = htons(id++);
ip->ip_sum = 0;
- ip->ip_sum = chksum(ip, ip->ip_hl << 2);
- (void) send_ether(nfd, ip, i, gwip);
+ ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, (char *)ip, i, gwip);
printf("%d\r", i);
fflush(stdout);
PAUSE();
@@ -264,12 +283,47 @@ int ptest;
gettimeofday(&tv, NULL);
srand(tv.tv_sec ^ getpid() ^ tv.tv_usec);
/*
- * Part8: 63k packet + 1k fragment at offset 0x1ffe
+ * Part8.1: 63k packet + 1k fragment at offset 0x1ffe
+ * Mark it as being ICMP (so it doesn't get junked), but
+ * don't bother about the ICMP header, we're not worrying
+ * about that here.
+ */
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_off = IP_MF;
+ u->uh_dport = htons(9);
+ ip->ip_id = htons(id++);
+ printf("1.8.1 63k packet + 1k fragment at offset 0x1ffe\n");
+ ip->ip_len = 768 + 20 + 8;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+
+ ip->ip_len = MIN(768 + 20, mtu - 68);
+ i = 512;
+ for (; i < (63 * 1024 + 768); i += 768) {
+ ip->ip_off = IP_MF | (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ ip->ip_len = 896 + 20;
+ ip->ip_off = (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ putchar('\n');
+ fflush(stdout);
+
+ /*
+ * Part8.2: 63k packet + 1k fragment at offset 0x1ffe
+ * Mark it as being ICMP (so it doesn't get junked), but
+ * don't bother about the ICMP header, we're not worrying
+ * about that here. (Lossage here)
*/
+ ip->ip_p = IPPROTO_ICMP;
ip->ip_off = IP_MF;
u->uh_dport = htons(9);
ip->ip_id = htons(id++);
- printf("1.8. 63k packet + 1k fragment at offset 0x1ffe\n");
+ printf("1.8.2 63k packet + 1k fragment at offset 0x1ffe\n");
ip->ip_len = 768 + 20 + 8;
if ((rand() & 0x1f) != 0) {
(void) send_ip(nfd, mtu, ip, gwip, 1);
@@ -290,7 +344,7 @@ int ptest;
PAUSE();
}
ip->ip_len = 896 + 20;
- ip->ip_off = IP_MF | (i >> 3);
+ ip->ip_off = (i >> 3);
if ((rand() & 0x1f) != 0) {
(void) send_ip(nfd, mtu, ip, gwip, 1);
printf("%d\r", i);
@@ -298,6 +352,37 @@ int ptest;
printf("skip\n");
putchar('\n');
fflush(stdout);
+
+ /*
+ * Part8.3: 33k packet - test for not dealing with -ve length
+ * Mark it as being ICMP (so it doesn't get junked), but
+ * don't bother about the ICMP header, we're not worrying
+ * about that here.
+ */
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_off = IP_MF;
+ u->uh_dport = htons(9);
+ ip->ip_id = htons(id++);
+ printf("1.8.3 33k packet\n");
+ ip->ip_len = 768 + 20 + 8;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+
+ ip->ip_len = MIN(768 + 20, mtu - 68);
+ i = 512;
+ for (; i < (32 * 1024 + 768); i += 768) {
+ ip->ip_off = IP_MF | (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ ip->ip_len = 896 + 20;
+ ip->ip_off = (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ putchar('\n');
+ fflush(stdout);
}
ip->ip_len = len;
@@ -352,8 +437,7 @@ struct in_addr gwip;
int ptest;
{
struct timeval tv;
- udphdr_t *u;
- int nfd, i, len, id = getpid();
+ int nfd;
u_char *s;
s = (u_char *)(ip + 1);
@@ -445,8 +529,7 @@ int ptest;
static int ict2[8] = { 3, 9, 10, 13, 14, 17, 18, 0 };
struct timeval tv;
struct icmp *icp;
- int nfd, i, len, id = getpid();
- u_char *s;
+ int nfd, i;
ip->ip_hl = sizeof(*ip) >> 2;
ip->ip_v = IPVERSION;
@@ -637,8 +720,8 @@ struct in_addr gwip;
int ptest;
{
struct timeval tv;
- struct udphdr *u;
- int nfd, i, len, id = getpid();
+ udphdr_t *u;
+ int nfd, i;
ip->ip_hl = sizeof(*ip) >> 2;
@@ -768,10 +851,10 @@ int ptest;
PAUSE();
}
- if (!ptest || (ptest == 4)) {
+ if (!ptest || (ptest == 5)) {
/*
- * Test 5: sizeof(struct ip) <= MTU <= sizeof(struct udphdr) +
- * sizeof(struct ip)
+ * Test 5: sizeof(ip_t) <= MTU <= sizeof(udphdr_t) +
+ * sizeof(ip_t)
*/
printf("4.5 UDP 20 <= MTU <= 32\n");
for (i = sizeof(*ip); i <= u->uh_ulen; i++) {
@@ -796,10 +879,12 @@ int ptest;
{
struct timeval tv;
tcphdr_t *t;
- int nfd, i, len, id = getpid();
+ int nfd, i;
t = (tcphdr_t *)((char *)ip + (ip->ip_hl << 2));
+#ifndef linux
t->th_x2 = 0;
+#endif
t->th_off = 0;
t->th_sport = 1;
t->th_dport = 1;
@@ -808,6 +893,7 @@ int ptest;
t->th_sum = 0;
t->th_seq = 1;
t->th_ack = 0;
+ ip->ip_len = sizeof(ip_t) + sizeof(tcphdr_t);
nfd = initdevice(dev, t->th_sport, 1);
if (!ptest || (ptest == 1)) {
@@ -937,9 +1023,10 @@ int ptest;
PAUSE();
}
-#if !defined(linux) && !defined(__SVR4) && !defined(__svr4__)
+#if !defined(linux) && !defined(__SVR4) && !defined(__svr4__) && \
+ !defined(__sgi)
{
- struct tcpcb *t, tcb;
+ struct tcpcb *tcbp, tcb;
struct tcpiphdr ti;
struct sockaddr_in sin;
int fd, slen;
@@ -948,10 +1035,13 @@ int ptest;
for (i = 1; i < 63; i++) {
fd = socket(AF_INET, SOCK_STREAM, 0);
+ bzero((char *)&sin, sizeof(sin));
sin.sin_addr.s_addr = ip->ip_dst.s_addr;
sin.sin_port = htons(i);
+ sin.sin_family = AF_INET;
if (!connect(fd, (struct sockaddr *)&sin, sizeof(sin)))
break;
+ close(fd);
}
if (i == 63) {
@@ -962,15 +1052,15 @@ int ptest;
}
bcopy((char *)ip, (char *)&ti, sizeof(*ip));
- ti.ti_dport = i;
+ t->th_dport = htons(i);
slen = sizeof(sin);
if (!getsockname(fd, (struct sockaddr *)&sin, &slen))
- ti.ti_sport = sin.sin_port;
- if (!(t = (struct tcpcb *)find_tcp(fd, &ti))) {
+ t->th_sport = sin.sin_port;
+ if (!(tcbp = find_tcp(fd, &ti))) {
printf("Can't find PCB\n");
goto skip_five_and_six;
}
- kmemcpy((char*)&tcb, (void *)t, sizeof(tcb));
+ KMCPY(&tcb, tcbp, sizeof(tcb));
ti.ti_win = tcb.rcv_adv;
ti.ti_seq = tcb.snd_nxt - 1;
ti.ti_ack = tcb.rcv_nxt;
@@ -979,27 +1069,36 @@ int ptest;
/*
* Test 5: urp
*/
- printf("5.1 TCP Urgent pointer\n");
- ti.ti_urp = 1;
+ t->th_flags = TH_ACK|TH_URG;
+ printf("5.5.1 TCP Urgent pointer, sport %hu dport %hu\n",
+ ntohs(t->th_sport), ntohs(t->th_dport));
+ t->th_urp = htons(1);
(void) send_tcp(nfd, mtu, ip, gwip);
PAUSE();
- ti.ti_urp = 0x7fff;
+
+ t->th_seq = tcb.snd_nxt;
+ ip->ip_len = sizeof(ip_t) + sizeof(tcphdr_t) + 1;
+ t->th_urp = htons(0x7fff);
(void) send_tcp(nfd, mtu, ip, gwip);
PAUSE();
- ti.ti_urp = 0x8000;
+ t->th_urp = htons(0x8000);
(void) send_tcp(nfd, mtu, ip, gwip);
PAUSE();
- ti.ti_urp = 0xffff;
+ t->th_urp = htons(0xffff);
(void) send_tcp(nfd, mtu, ip, gwip);
PAUSE();
+ t->th_urp = htons(0);
+ t->th_flags &= ~TH_URG;
+ ip->ip_len = sizeof(ip_t) + sizeof(tcphdr_t);
}
if (!ptest || (ptest == 6)) {
/*
* Test 6: data offset, off = 0, off is inside, off is outside
*/
- printf("6.1 TCP off = 0-15, len = 40\n");
- for (i = 0; i < 16; i++) {
+ t->th_flags = TH_ACK;
+ printf("5.6.1 TCP off = 1-15, len = 40\n");
+ for (i = 1; i < 16; i++) {
ti.ti_off = ntohs(i);
(void) send_tcp(nfd, mtu, ip, gwip);
printf("%d\r", i);
@@ -1007,6 +1106,7 @@ int ptest;
PAUSE();
}
putchar('\n');
+ ip->ip_len = sizeof(ip_t) + sizeof(tcphdr_t);
}
(void) close(fd);
@@ -1015,9 +1115,9 @@ skip_five_and_six:
#endif
t->th_seq = 1;
t->th_ack = 1;
+ t->th_off = 0;
if (!ptest || (ptest == 7)) {
- t->th_off = 0;
t->th_flags = TH_SYN;
/*
* Test 7: sport = 0, sport = 1, sport = 32767
@@ -1056,6 +1156,7 @@ skip_five_and_six:
if (!ptest || (ptest == 8)) {
t->th_sport = 1;
+ t->th_flags = TH_SYN;
/*
* Test 8: dport = 0, dport = 1, dport = 32767
* dport = 32768, dport = 65535
@@ -1090,6 +1191,22 @@ skip_five_and_six:
fflush(stdout);
PAUSE();
}
+
+ /* LAND attack - self connect, so make src & dst ip/port the same */
+ if (!ptest || (ptest == 9)) {
+ printf("5.9 TCP LAND attack. sport = 25, dport = 25\n");
+ /* chose SMTP port 25 */
+ t->th_sport = htons(25);
+ t->th_dport = htons(25);
+ t->th_flags = TH_SYN;
+ ip->ip_src = ip->ip_dst;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ /* TCP options header checking */
+ /* 0 length options, etc */
}
@@ -1104,7 +1221,7 @@ int ptest;
{
struct timeval tv;
udphdr_t *u;
- int nfd, i, j, k, len, id = getpid();
+ int nfd, i, j, k;
ip->ip_v = IPVERSION;
ip->ip_tos = 0;
@@ -1122,7 +1239,10 @@ int ptest;
u->uh_dport = htons(u->uh_dport);
u->uh_ulen = 7168;
- for (i = 0; i < 65536; i++) {
+ printf("6. Exhaustive mbuf test.\n");
+ printf(" Send 7k packet in 768 & 128 byte fragments, 128 times.\n");
+ printf(" Total of around 8,900 packets\n");
+ for (i = 0; i < 128; i++) {
/*
* First send the entire packet in 768 byte chunks.
*/