diff options
author | dgregor <dgregor@cvs.openbsd.org> | 1998-01-26 04:17:12 +0000 |
---|---|---|
committer | dgregor <dgregor@cvs.openbsd.org> | 1998-01-26 04:17:12 +0000 |
commit | fe0239590c82ea51b1a09fd58cde9f1635ceab89 (patch) | |
tree | af8e00e22aa869bee7596358bc05686c76370f51 /usr.sbin/ipsend | |
parent | a344d388d075c3e901494684772107ed51830e00 (diff) |
IPF 3.2.3
Diffstat (limited to 'usr.sbin/ipsend')
-rw-r--r-- | usr.sbin/ipsend/common/44arp.c | 13 | ||||
-rw-r--r-- | usr.sbin/ipsend/common/ip.c | 125 | ||||
-rw-r--r-- | usr.sbin/ipsend/common/iplang.h | 51 | ||||
-rw-r--r-- | usr.sbin/ipsend/common/ipsend.h | 67 | ||||
-rw-r--r-- | usr.sbin/ipsend/common/sbpf.c | 21 | ||||
-rw-r--r-- | usr.sbin/ipsend/common/sock.c | 131 | ||||
-rw-r--r-- | usr.sbin/ipsend/common/tcpip.h | 91 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipresend/Makefile | 9 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipresend/ipresend.1 | 107 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipresend/ipresend.c | 54 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipresend/resend.c | 80 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/Makefile | 12 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/iplang_l.l | 312 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/iplang_y.y | 1840 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/ipsend.1 | 110 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/ipsend.5 | 399 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/ipsend.c | 134 | ||||
-rw-r--r-- | usr.sbin/ipsend/ipsend/ipsopt.c | 160 | ||||
-rw-r--r-- | usr.sbin/ipsend/iptest/Makefile | 7 | ||||
-rw-r--r-- | usr.sbin/ipsend/iptest/iptest.1 | 102 | ||||
-rw-r--r-- | usr.sbin/ipsend/iptest/iptest.c | 78 | ||||
-rw-r--r-- | usr.sbin/ipsend/iptest/iptests.c | 250 |
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 = ðerf; 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. */ |