diff options
author | dm <dm@cvs.openbsd.org> | 1996-05-10 21:41:01 +0000 |
---|---|---|
committer | dm <dm@cvs.openbsd.org> | 1996-05-10 21:41:01 +0000 |
commit | 76242ad5ccbbf411a0dfd66daab39d9a460c09dc (patch) | |
tree | 92b555bd9197bb7976ae825d415f70d567c37170 | |
parent | 75774d963fafaaaa2cf697156d616e2ebe3db3c8 (diff) |
ipfilter 3.0.4
42 files changed, 1882 insertions, 297 deletions
diff --git a/sbin/ipf/ipf.4 b/sbin/ipf/ipf.4 index f9c65e77c32..011e0a017d7 100644 --- a/sbin/ipf/ipf.4 +++ b/sbin/ipf/ipf.4 @@ -30,8 +30,7 @@ The variations, SIOCADAFR vs SIOCADIFR, allow operation on the two lists, active and inactive, respectively. All of these ioctl's are implemented as being routing ioctls and thus the same rules for the various routing ioctls and the file descriptor are employed, mainly being that the fd must -be that of the device associated with the module (ie /dev/ipl). In addition -to this, these ioctl's will only succeed if made as root. +be that of the device associated with the module (ie /dev/ipl). .LP .PP The three groups of ioctls above perform adding rules to the end of the diff --git a/sbin/ipf/ipf.c b/sbin/ipf/ipf.c index 92fe2e6ee06..af2a985b2ab 100644 --- a/sbin/ipf/ipf.c +++ b/sbin/ipf/ipf.c @@ -34,7 +34,7 @@ extern char *index(); #include "ipf.h" #ifndef lint -static char sccsid[] = "@(#)ipf.c 1.21 1/14/96 (C) 1993-1995 Darren Reed"; +static char sccsid[] = "@(#)ipf.c 1.22 2/3/96 (C) 1993-1995 Darren Reed"; #endif #if SOLARIS @@ -139,6 +139,8 @@ char *file; if (opts & OPT_DEBUG) printf("add %x del %x\n", add, del); + initparse(); + if (!strcmp(file, "-")) fp = stdin; else if (!(fp = fopen(file, "r"))) { diff --git a/sbin/ipf/ipf.h b/sbin/ipf/ipf.h index 794f98c71e3..e0946b864c4 100644 --- a/sbin/ipf/ipf.h +++ b/sbin/ipf/ipf.h @@ -5,7 +5,7 @@ * provided that this notice is preserved and due credit is given * to the original author and the contributors. * - * @(#)ipf.h 1.9 1/7/96 + * @(#)ipf.h 1.11 4/10/96 */ #define OPT_REMOVE 0x0001 @@ -22,10 +22,11 @@ #define OPT_FRSTATES FR_KEEPFRAG /* 0x1000 */ #define OPT_IPSTATES FR_KEEPSTATE /* 0x2000 */ #define OPT_INACTIVE FR_INACTIVE /* 0x4000 */ +#define OPT_SHOWLINENO 0x8000 extern struct frentry *parse(); -extern void printfr(), binprint(); +extern void printfr(), binprint(), initparse(); #if defined(__SVR4) || defined(__svr4__) #define index strchr diff --git a/sbin/ipf/opt.c b/sbin/ipf/opt.c index 8e90965928e..3b475a4aec3 100644 --- a/sbin/ipf/opt.c +++ b/sbin/ipf/opt.c @@ -21,7 +21,7 @@ #include "ipf.h" #ifndef lint -static char sccsid[] = "@(#)opt.c 1.6 11/11/95 (C) 1993-1995 Darren Reed"; +static char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-1995 Darren Reed"; #endif extern int opts; @@ -58,7 +58,7 @@ struct ipopt_names secclass[] = { { IPSO_CLASS_CONF, 0x10, 0, "confid" }, { IPSO_CLASS_UNCL, 0x20, 0, "unclass" }, { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" }, - { IPSO_CLASS_RES1, 0x40, 0, "reserv-1" }, + { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" }, { 0, 0, 0, NULL } /* must be last */ }; @@ -107,7 +107,7 @@ char *cp, *op; if (t && !strcasecmp(s, "sec-class")) { lvl = seclevel(t); - *op = lvl; + *(op - 1) = lvl; } op += io->on_siz - 3; if (len & 3) { diff --git a/sbin/ipf/parse.c b/sbin/ipf/parse.c index efea74e9d57..f3cf027a825 100644 --- a/sbin/ipf/parse.c +++ b/sbin/ipf/parse.c @@ -1,5 +1,5 @@ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * (C)opyright 1993-1996 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -32,7 +32,7 @@ #include <ctype.h> #ifndef lint -static char sccsid[] ="@(#)parse.c 1.33 1/14/96 (C) 1993 Darren Reed"; +static char sccsid[] ="@(#)parse.c 1.41 4/10/96 (C) 1993-1996 Darren Reed"; #endif extern struct ipopt_names ionames[], secclass[]; @@ -352,7 +352,7 @@ char *line; /* * Keep something... */ - if (*cpp && !strcasecmp(*cpp, "keep")) + while (*cpp && !strcasecmp(*cpp, "keep")) if (addkeep(&cpp, &fil)) return NULL; @@ -375,7 +375,14 @@ char *line; "no protocol given for TCP/UDP comparisons\n"); return NULL; } - +/* + if ((fil.fr_flags & FR_KEEPFRAG) && + (!(fil.fr_ip.fi_fl & FI_FRAG) || !(fil.fr_ip.fi_fl & FI_FRAG))) { + (void)fprintf(stderr, + "must use 'with frags' with 'keep frags'\n"); + return NULL; + } +*/ return &fil; } @@ -401,7 +408,7 @@ u_char *cp; return -1; if (index(s, '.')) *msk = inet_addr(s); - else { + if (!index(s, '.') && !index(s, 'x')) { /* * set x most significant bits */ @@ -410,6 +417,9 @@ u_char *cp; *msk |= ntohl(inet_addr("128.0.0.0")); } *msk = htonl(*msk); + } else { + if (inet_aton(s, (struct in_addr *)msk) == -1) + return -1; } *sa = hostnum(**seg, &resolved) & *msk; if (resolved == -1) @@ -427,10 +437,8 @@ u_char *cp; return -1; (*seg)++; (*seg)++; - if (index(**seg, '.')) - *msk = inet_addr(**seg); - else - *msk = (u_long)strtol(**seg, NULL, 0); + if (inet_aton(**seg, (struct in_addr *)msk) == -1) + return -1; (*seg)++; *sa &= *msk; return ports(seg, pp, cp, tp); @@ -490,9 +498,9 @@ u_char *cp; if (!*seg || !**seg || !***seg) return 0; - if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(seg + 2)) { + if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { (*seg)++; - if (isdigit(***seg) && *(seg + 2)) { + if (isdigit(***seg) && *(*seg + 2)) { *pp = portnum(**seg); (*seg)++; if (!strcmp(**seg, "<>")) @@ -539,13 +547,13 @@ char *name; u_short p1 = 0; if (isdigit(*name)) - return htons((u_short)atoi(name)); + return (u_short)atoi(name); if (!proto) proto = "tcp/udp"; if (strcasecmp(proto, "tcp/udp")) { sp = getservbyname(name, proto); if (sp) - return sp->s_port; + return ntohs(sp->s_port); (void) fprintf(stderr, "unknown service \"%s\".\n", name); return 0; } @@ -564,7 +572,7 @@ char *name; (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port); return 0; } - return p1; + return ntohs(p1); } @@ -616,13 +624,21 @@ struct frentry *fr; !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 4) || !strncasecmp(**cp, "frag", 3) || !strncasecmp(**cp, "no", 2) || !strncasecmp(**cp, "short", 5))) { - if (***cp == 'n') + if (***cp == 'n') { notopt = 1; - else if (***cp == 'i') - oflags = FI_OPTIONS; - else if (***cp == 'f') - oflags = FI_FRAG; - else if (***cp == 'o') { + (*cp)++; + continue; + } else if (***cp == 'i') { + if (!notopt) + fr->fr_ip.fi_fl |= FI_OPTIONS; + fr->fr_mip.fi_fl |= FI_OPTIONS; + goto nextopt; + } else if (***cp == 'f') { + if (!notopt) + fr->fr_ip.fi_fl |= FI_FRAG; + fr->fr_mip.fi_fl |= FI_FRAG; + goto nextopt; + } else if (***cp == 'o') { if (!*(*cp + 1)) { (void)fprintf(stderr, "opt missing arguements\n"); @@ -638,12 +654,23 @@ struct frentry *fr; "short cannot be used with TCP flags\n"); return -1; } - oflags = FI_SHORT; + + if (!notopt) + fr->fr_ip.fi_fl |= FI_SHORT; + fr->fr_mip.fi_fl |= FI_SHORT; + goto nextopt; } else return -1; - fr->fr_mip.fi_fl |= oflags; - fr->fr_mip.fi_optmsk |= opts; + if (!notopt || !opts) + fr->fr_mip.fi_fl |= oflags; + if (notopt) + if (!secmsk) + fr->fr_mip.fi_optmsk |= opts; + else + fr->fr_mip.fi_optmsk |= (opts & ~0x0100); + else + fr->fr_mip.fi_optmsk |= opts; fr->fr_mip.fi_secmsk |= secmsk; if (notopt) { @@ -655,6 +682,8 @@ struct frentry *fr; fr->fr_ip.fi_optmsk |= opts; fr->fr_ip.fi_secmsk |= secmsk; } +nextopt: + notopt = 0; opts = 0; oflags = 0; secmsk = 0; @@ -714,26 +743,72 @@ u_short *sp; } -void optprint(optmsk, secmsk) -u_char optmsk, secmsk; +void optprint(secmsk, secbits, optmsk, optbits) +u_short secmsk, secbits; +u_long optmsk, optbits; { struct ipopt_names *io, *so; - char *s = "", *t = ""; + char *s; + int secflag = 0; - printf("opt "); + s = "opt "; for (io = ionames; io->on_name; io++) - if (io->on_bit & optmsk) { - printf("%s%s", s, io->on_name); - s = ","; + if ((io->on_bit & optmsk) && + ((io->on_bit & optmsk) == (io->on_bit & optbits))) { + if ((io->on_value != IPOPT_SECURITY) || + (!secmsk && !secbits)) { + printf("%s%s", s, io->on_name); + if (io->on_value == IPOPT_SECURITY) + io++; + s = ","; + } else + secflag = 1; } - if (secmsk) { - putchar(' '); + + + if (secmsk & secbits) { + printf("%ssec-class", s); + s = " "; for (so = secclass; so->on_name; so++) - if (secmsk & so->on_bit) { - printf("%s%s", t, so->on_name); - t = ","; + if ((secmsk & so->on_bit) && + ((io->on_bit & secmsk) == (io->on_bit & secbits))) { + printf("%s%s", s, so->on_name); + s = ","; } } + + if (strcmp(s, "opt ")) + putchar(' '); + if ((optmsk && (optmsk != optbits)) || + (secmsk && (secmsk != secbits))) { + s = " "; + printf("not opt"); + if (optmsk != optbits) { + for (io = ionames; io->on_name; io++) + if ((io->on_bit & optmsk) && + ((io->on_bit & optmsk) != + (io->on_bit & optbits))) { + if ((io->on_value != IPOPT_SECURITY) || + (!secmsk && !secbits)) { + printf("%s%s", s, io->on_name); + s = ","; + } else + io++; + } + } + + if (secmsk != secbits) { + printf("%ssec-class", s); + s = " "; + for (so = secclass; so->on_name; so++) + if ((so->on_bit & secmsk) && + ((so->on_bit & secmsk) != + (so->on_bit & secbits))) { + printf("%s%s", s, so->on_name); + s = ","; + } + } + } } char *icmptypes[] = { @@ -890,15 +965,17 @@ int pr, port; struct servent *sv = NULL, *sv1 = NULL; if (pr == -1) { - if ((sv = getservbyport(htons(port), "tcp"))) { + if ((sv = getservbyport(port, "tcp"))) { strncpy(buf, sv->s_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; - sv1 = getservbyport(htons(port), "udp"); - if (sv1 && !strcasecmp(buf, sv->s_name)) - return buf; + sv1 = getservbyport(port, "udp"); + sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? + NULL : sv1; } + if (sv) + return buf; } else if (pr && (p = getprotobynumber(pr))) { - if ((sv = getservbyport(htons(port), p->p_name))) { + if ((sv = getservbyport(port, p->p_name))) { strncpy(buf, sv->s_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; return buf; @@ -937,7 +1014,8 @@ struct frentry *fp; (void)printf(" return-icmp"); if (fp->fr_icode) if (fp->fr_icode <= MAX_ICMPCODE) - printf("(%s)",icmpcodes[fp->fr_icode]); + printf("(%s)", + icmpcodes[(int)fp->fr_icode]); else printf("(%d)", fp->fr_icode); } @@ -972,7 +1050,7 @@ struct frentry *fp; if (fp->fr_ip.fi_fl & FI_TCPUDP) { (void)printf("proto tcp/udp "); pr = -1; - } else if ((pr = fp->fr_proto)) { + } else if ((pr = fp->fr_mip.fi_p)) { if ((p = getprotobynumber(fp->fr_proto))) (void)printf("proto %s ", p->p_name); else @@ -988,13 +1066,13 @@ struct frentry *fp; else (void)printf("/%d ", ones); } - if (fp->fr_sport) + if (fp->fr_scmp) if (fp->fr_scmp == FR_INRANGE || fp->fr_scmp == FR_OUTRANGE) - (void)printf("port %d %s %d ", ntohs(fp->fr_sport), - pcmp1[fp->fr_scmp], ntohs(fp->fr_stop)); + (void)printf("port %d %s %d ", fp->fr_sport, + pcmp1[fp->fr_scmp], fp->fr_stop); else (void)printf("port %s %s ", pcmp1[fp->fr_scmp], - portname(pr, ntohs(fp->fr_sport))); + portname(pr, fp->fr_sport)); if (!fp->fr_dst.s_addr & !fp->fr_dmsk.s_addr) (void)printf("to any "); else { @@ -1004,25 +1082,29 @@ struct frentry *fp; else (void)printf("/%d ", ones); } - if (fp->fr_dport) { + if (fp->fr_dcmp) { if (fp->fr_dcmp == FR_INRANGE || fp->fr_dcmp == FR_OUTRANGE) - (void)printf("port %d %s %d ", ntohs(fp->fr_dport), - pcmp1[fp->fr_dcmp], ntohs(fp->fr_dtop)); + (void)printf("port %d %s %d ", fp->fr_dport, + pcmp1[fp->fr_dcmp], fp->fr_dtop); else (void)printf("port %s %s ", pcmp1[fp->fr_dcmp], - portname(pr, ntohs(fp->fr_dport))); + portname(pr, fp->fr_dport)); } - if (fp->fr_mip.fi_fl & (FI_SHORT|FI_OPTIONS|FI_FRAG)) { + if ((fp->fr_ip.fi_fl & ~FI_TCPUDP) || + (fp->fr_mip.fi_fl & ~FI_TCPUDP) || + fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || + fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) { (void)printf("with "); - if (fp->fr_mip.fi_fl & FI_OPTIONS) { - if (fp->fr_ip.fi_optmsk) - optprint(fp->fr_ip.fi_optmsk, - fp->fr_ip.fi_secmsk); - else { - if (!(fp->fr_ip.fi_fl & FI_OPTIONS)) - (void)printf("not "); - (void)printf("ipopt "); - } + if (fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || + fp->fr_ip.fi_secmsk || fp->fr_mip.fi_secmsk) + optprint(fp->fr_mip.fi_secmsk, + fp->fr_ip.fi_secmsk, + fp->fr_mip.fi_optmsk, + fp->fr_ip.fi_optmsk); + else if (fp->fr_mip.fi_fl & FI_OPTIONS) { + if (!(fp->fr_ip.fi_fl & FI_OPTIONS)) + (void)printf("not "); + (void)printf("ipopt "); } if (fp->fr_mip.fi_fl & FI_SHORT) { if (!(fp->fr_ip.fi_fl & FI_SHORT)) diff --git a/sbin/ipfstat/fils.c b/sbin/ipfstat/fils.c index ff91986d540..7ad796e1681 100644 --- a/sbin/ipfstat/fils.c +++ b/sbin/ipfstat/fils.c @@ -1,5 +1,5 @@ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * (C)opyright 1993-1996 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -39,7 +39,7 @@ #endif #ifndef lint -static char sccsid[] = "@(#)fils.c 1.18 1/12/96 (C) 1993 Darren Reed"; +static char sccsid[] = "@(#)fils.c 1.20 3/24/96 (C) 1993-1996 Darren Reed"; #endif #ifdef _PATH_UNIX #define VMUNIX _PATH_UNIX @@ -97,6 +97,9 @@ char *argv[]; case 'i' : opts |= OPT_INQUE|OPT_SHOWLIST; break; + case 'n' : + opts |= OPT_SHOWLINENO; + break; case 'I' : opts |= OPT_INACTIVE; break; @@ -199,6 +202,8 @@ struct friostat *fp; fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); + PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", + fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); PRINTF("Packet log flags set: (%#x)\n", frf); if (frf & FF_LOGPASS) @@ -217,7 +222,7 @@ struct friostat *fiop; { struct frentry fb; struct frentry *fp = NULL; - int i, set; + int i, set, n; set = fiop->f_active; if (opts & OPT_INACTIVE) @@ -248,7 +253,8 @@ struct friostat *fiop; (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); return; } - while (fp) { + + for (n = 1; fp; n++) { if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { perror("kmemcpy"); return; @@ -260,6 +266,8 @@ struct friostat *fiop; PRINTF("%ld ", fp->fr_hits); if (opts & (OPT_ACCNT|OPT_VERBOSE)) PRINTF("%ld ", fp->fr_bytes); + if (opts & OPT_SHOWLINENO) + PRINTF("@%d ", n); printfr(fp); if (opts & OPT_VERBOSE) binprint(fp); diff --git a/sbin/ipnat/Makefile b/sbin/ipnat/Makefile new file mode 100644 index 00000000000..59e676674f5 --- /dev/null +++ b/sbin/ipnat/Makefile @@ -0,0 +1,7 @@ +PROG= ipnat +MAN= ipnat.1 ipnat.4 ipnat.5 +SRCS= ipnat.c kmem.c +.PATH: ${.CURDIR}/../ipfstat +CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sys/netinet + +.include <bsd.prog.mk> diff --git a/sbin/ipnat/ipnat.1 b/sbin/ipnat/ipnat.1 new file mode 100644 index 00000000000..b0ddc59a474 --- /dev/null +++ b/sbin/ipnat/ipnat.1 @@ -0,0 +1,29 @@ +.TH IPFNAT 1 +.SH NAME +ipnat - user interface to the NAT +.SH SYNOPSIS +ipnat [-lnrsv] -f <\fIfilename\fP> +.SH DESCRIPTION +.PP +\fBipnat\fP opens the filename given (treating "-" as stdin) and parses the +file for a set of rules which are to be added or removed from the IP NAT. +.PP +Each rule processed by \fBipnat\fP +is added to the kernels internal lists if there are no parsing problems. +Rules are added to the end of the internal lists, matching the order in +which they appear when given to \fBipnat\fP. +.SH OPTIONS +.IP -l +Show the list of current NAT table entry mappings. +.IP -n +This flag (no-change) prevents \fBipf\fP from actually making any ioctl +calls or doing anything which would alter the currently running kernel. +.IP -s +retrieve and display NAT statistics +.IP -r +remove matching NAT rules rather than add them to the internal lists +.IP -v +turn verbose mode on. Displays information relating to rule processing. +.DT +.SH SEE ALSO +ipfstat(1), ipftest(1), ipf(1), ipnat(5) diff --git a/sbin/ipnat/ipnat.4 b/sbin/ipnat/ipnat.4 new file mode 100644 index 00000000000..4962cf3df28 --- /dev/null +++ b/sbin/ipnat/ipnat.4 @@ -0,0 +1,88 @@ +.TH IPNAT 4 +.SH NAME +ipnat - Network Address Translation kernel interface +.SH SYNOPSIS +#include <sys/ip_fil.h> +.SH IOCTLS +.PP +To add and delete rules to the NAT list, two 'basic' ioctls are provided +for use. The ioctl's are called as: +.LP +.nf + ioctl(fd, SIOCADNAT, struct ipnat *) + ioctl(fd, SIOCRMNAT, struct ipnat *) +.fi +.PP +Unlike \fBipf(4)\fP, there is only a single list supported by the kernel NAT +interface. An inactive list which can be swapped to is not currently +supported. + +These ioctl's are implemented as being routing ioctls and thus the same rules +for the various routing ioctls and the file descriptor are employed, mainly +being that the fd must be that of the device associated with the module +(ie /dev/ipl). +.LP +.PP +The strcture used with the NAT interface is described below: +.LP +.nf +typedef struct ipnat { + struct ipnat *in_next; + void *in_ifp; + u_short in_flags; + u_short in_pnext; + u_short in_port[2]; + struct in_addr in_in[2]; + struct in_addr in_out[2]; + struct in_addr in_nextip; + int in_space; + int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */ + char in_ifname[IFNAMSIZ]; +} ipnat_t; + +#define in_pmin in_port[0] /* Also holds static redir port */ +#define in_pmax in_port[1] +#define in_nip in_nextip.s_addr +#define in_inip in_in[0].s_addr +#define in_inmsk in_in[1].s_addr +#define in_outip in_out[0].s_addr +#define in_outmsk in_out[1].s_addr + +.fi +.PP +Recognised values for in_redir: +.LP +.nf +#define NAT_MAP 0 +#define NAT_REDIRECT 1 +.fi +.PP +.LP +\fBNAT statistics\fP +Statistics on the the number of packets mapped, going in and out are kept, +the number of times a new entry is added and deleted (through expiration) to +the NAT table and the current usage level of the NAT table. +.PP +Pointers to the NAT table inside the kernel, as well as to the top of the +internal NAT lists constructed with the \fBSIOCADNAT\fP ioctls. The table +itself is a hash table of size NAT_SIZE (default size is 367). +.PP +To retrieve the statistics, the \fBSIOCGNATS\fP ioctl must be used, with +the appropriate structure passed by reference, as follows: +.nf + ioctl(fd, SIOCGNATS, struct natstat *) + +typedef struct natstat { + u_long ns_mapped[2]; + u_long ns_added; + u_long ns_expire; + u_long ns_inuse; + nat_t ***ns_table; + ipnat_t *ns_list; +} natstat_t; +.fi +.SH BUGS +It would be nice if there were more flexibility when adding and deleting +filter rules. +.SH SEE ALSO +ipfstat(1), ipf(1), ipf(4), ipnat(5) diff --git a/sbin/ipnat/ipnat.5 b/sbin/ipnat/ipnat.5 new file mode 100644 index 00000000000..51fdbee0def --- /dev/null +++ b/sbin/ipnat/ipnat.5 @@ -0,0 +1,70 @@ +.LP +.TH IPNAT 5 +.SH NAME +ipnat - IP NAT file format +.SH DESCRIPTION +The format for files accepted by ipnat is described by the following grammar: +.LP +.nf +ipmap :: = mapit ifname ipmask "->" ipmask [ mapport ] . + +mapit ::= "map" | "rdr" . +ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask . +mapport ::= "portmap" tcpudp portnumber ":" portnumber . + +tcpudp ::= "tcp" | "udp" | "tcp/udp" . +portnumber ::= number { numbers } . +ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers . + +numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' . +.fi +.PP +For standard NAT functionality, a rule should start with \fBmap\fP and then +proceeds to specify the interface for which outgoing packets will have their +source address rewritten. +.PP +Packets which will be rewritten can only be selected by matching the original +source address. A netmask must be specified with the IP address. +.PP +The address selected for replacing the original is chosen from an IP#/netmask +pair. A netmask of all 1's indicating a hostname is valid. A netmask of +31 1's (255.255.255.254) is considered invalid as there is no space for +allocating host IP#'s after consideration for broadcast and network +addresses. +.PP +When remapping TCP and UDP packets, it is also possible to change the source +port number. Either TCP or UDP or both can be selected by each rule, with a +range of port numbers to remap into given as \fBport-number:port-number\fP. +.SH Examples +.PP +To change IP#'s used internally from network 10 into an ISP provided 8 bit +subnet at 209.1.2.0, the following would be used: +.LP +.nf +map 10.0.0.0/8 -> 209.1.2.0/24 +.fi +.PP +The obvious problem here is we're trying to squeeze over 16,000,000 IP +addresses into a 254 address space. To increase the scope, remapping for TCP +and/or UDP, port remapping can be used; +.LP +.nf +map 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000 +.fi +.PP +which falls only 527,566 `addresses' short of the space available in network +10. If we were to combine these rules, they would need to be specified as +follows: +.LP +.nf +map 10.0.0.0/8 -> 209.1.2.0/24 portmap tcp/udp 1025:65000 +map 10.0.0.0/8 -> 209.1.2.0/24 +.fi +.PP +so that all TCP/UDP packets were port mapped and only other protocols, such as +ICMP, only have their IP# changed. +.SH FILES +/etc/services +/etc/hosts +.SH SEE ALSO +ipnat(1), ipf(5), ipnat(4) diff --git a/sbin/ipnat/ipnat.c b/sbin/ipnat/ipnat.c new file mode 100644 index 00000000000..48d8c252172 --- /dev/null +++ b/sbin/ipnat/ipnat.c @@ -0,0 +1,527 @@ +/* + * (C)opyright 1993,1994,1995 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. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + * + * Broken still: + * Displaying the nat with redirect entries is way confusing + * + * Example redirection line: + * rdr le1 0.0.0.0/0 port 79 -> 199.165.219.129 port 9901 + * + * Will redirect all incoming packets on le1 to any machine, port 79 to + * host 199.165.219.129, port 9901 + */ +#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/param.h> +#include <stdlib.h> +#include <unistd.h> +#include <stddef.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# include <sys/ioccom.h> +# include <sys/sysmacros.h> +#endif +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <net/if.h> +#include "ip_fil.h" +#include <netdb.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <resolv.h> +#include "ip_nat.h" +#include <ctype.h> + + +#ifndef lint +static char sccsid[] ="@(#)ipnat.c 1.8 4/10/96 (C) 1993 Darren Reed"; +#endif + +#if SOLARIS +#define bzero(a,b) memset(a,0,b) +#endif + +extern char *optarg; +extern int kmemcpy(); + +void dostats(), printnat(), parsefile(); + +int main(argc, argv) +int argc; +char *argv[]; +{ + char *file = NULL, c; + int fd, opts = 1; + + while ((c = getopt(argc, argv, "f:lnrsv")) != -1) + switch (c) + { + case 'f' : + file = optarg; + break; + case 'l' : + opts |= 8; + break; + case 'n' : + opts |= 2; + break; + case 'r' : + opts &= ~1; + break; + case 's' : + opts |= 4; + break; + case 'v' : + opts |= 16; + break; + default : + fprintf(stderr, "unknown option \"%c\"\n", c); + break; + } + + if ((fd = open(IPL_NAME, O_RDONLY)) == -1) { + perror("open"); + exit(-1); + } + + if (file) + parsefile(fd, file, opts); + if (opts & 12) + dostats(fd); + return 0; +} + + +void printnat(np) +ipnat_t *np; +{ + if (np->in_redir == NAT_REDIRECT) { + printf("rdr %s %s", np->in_ifname, inet_ntoa(np->in_out[0])); + printf("/%s (%d) -> ", inet_ntoa(np->in_out[1]), + ntohs(np->in_pmin)); + printf("%s (%d)\n", inet_ntoa(np->in_in[0]), + ntohs(np->in_pnext)); + printf("\t%x %u %x %u\n", (u_int)np->in_ifp, np->in_space, + np->in_flags, np->in_pnext); + } else { + np->in_nextip.s_addr = htonl(np->in_nextip.s_addr); + printf("map %s %s/", np->in_ifname, inet_ntoa(np->in_in[0])); + printf("%s -> ", inet_ntoa(np->in_in[1])); + printf("%s/", inet_ntoa(np->in_out[0])); + printf("%s\n", inet_ntoa(np->in_out[1])); + printf("\t%x %u %s %x %u %d:%d\n", (u_int)np->in_ifp, + np->in_space, inet_ntoa(np->in_nextip), np->in_flags, + np->in_pnext, ntohs(np->in_port[0]), + ntohs(np->in_port[1])); + } +} + + +void dostats(fd, opts) +int fd, opts; +{ + natstat_t ns; + ipnat_t ipn; + nat_t **nt, *np, nat; + int i; + + if (ioctl(fd, SIOCGNATS, &ns) == -1) { + perror("ioctl(SIOCGNATS)"); + return; + } + if (opts & 4) { + printf("mapped\tin\t%lu\tout\t%lu\n", + ns.ns_mapped[0], ns.ns_mapped[1]); + printf("added\t%lu\texpired\t%lu\n", + ns.ns_added, ns.ns_expire); + printf("inuse\t%lu\n", ns.ns_inuse); + printf("table %#x list %#x\n", + (u_int)ns.ns_table, (u_int)ns.ns_list); + } + if (opts & 8) { + while (ns.ns_list) { + if (kmemcpy(&ipn, ns.ns_list, sizeof(ipn))) { + perror("kmemcpy"); + break; + } + printnat(&ipn); + ns.ns_list = ipn.in_next; + } + + nt = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE); + if (kmemcpy(nt, ns.ns_table, sizeof(*nt) * NAT_SIZE)) { + perror("kmemcpy"); + return; + } + for (i = 0; i < NAT_SIZE; i++) + for (np = nt[i]; np; np = nat.nat_next) { + if (kmemcpy(&nat, np, sizeof(nat))) + break; + printf("%s %hu <- -> ", + inet_ntoa(nat.nat_inip), + ntohs(nat.nat_inport)); + printf("%s %hu %hu %hu %lx [", + inet_ntoa(nat.nat_outip), + ntohs(nat.nat_outport), + nat.nat_age, nat.nat_use, + nat.nat_sumd); + printf("%s %hu]\n", inet_ntoa(nat.nat_oip), + ntohs(nat.nat_oport)); + } + } +} + + +u_short portnum(name, proto) +char *name, *proto; +{ + struct servent *sp, *sp2; + u_short p1 = 0; + + if (isdigit(*name)) + return htons((u_short)atoi(name)); + if (!proto) + proto = "tcp/udp"; + if (strcasecmp(proto, "tcp/udp")) { + sp = getservbyname(name, proto); + if (sp) + return sp->s_port; + (void) fprintf(stderr, "unknown service \"%s\".\n", name); + return 0; + } + sp = getservbyname(name, "tcp"); + if (sp) + p1 = sp->s_port; + sp2 = getservbyname(name, "udp"); + if (!sp || !sp2) { + (void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n", + name); + return 0; + } + if (p1 != sp2->s_port) { + (void) fprintf(stderr, "%s %d/tcp is a different port to ", + name, p1); + (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port); + return 0; + } + return p1; +} + + +u_long hostmask(msk) +char *msk; +{ + int bits = -1; + u_long mask; + + if (!isdigit(*msk)) + return (u_long)-1; + if (strchr(msk, '.')) + return inet_addr(msk); + if (strchr(msk, 'x')) + return (u_long)strtol(msk, NULL, 0); + /* + * set x most significant bits + */ + for (mask = 0, bits = atoi(msk); bits; bits--) { + mask /= 2; + mask |= ntohl(inet_addr("128.0.0.0")); + } + mask = htonl(mask); + return mask; +} + + +/* + * returns an ip address as a long var as a result of either a DNS lookup or + * straight inet_addr() call + */ +u_long hostnum(host, resolved) +char *host; +int *resolved; +{ + struct hostent *hp; + struct netent *np; + + *resolved = 0; + if (!strcasecmp("any",host)) + return 0L; + if (isdigit(*host)) + return inet_addr(host); + + if (!(hp = gethostbyname(host))) { + if (!(np = getnetbyname(host))) { + *resolved = -1; + fprintf(stderr, "can't resolve hostname: %s\n", host); + return 0; + } + return np->n_net; + } + return *(u_long *)hp->h_addr; +} + + +ipnat_t *parse(line) +char *line; +{ + static ipnat_t ipn; + char *s, *t; + char *shost, *snetm, *dhost, *dnetm, *proto, *dport, *tport; + int resolved; + + bzero((char *)&ipn, sizeof(ipn)); + if ((s = strchr(line, '\n'))) + *s = '\0'; + if ((s = strchr(line, '#'))) + *s = '\0'; + if (!*line) + return NULL; + if (!(s = strtok(line, " \t"))) + return NULL; + if (!strcasecmp(s, "map")) + ipn.in_redir = NAT_MAP; + else if (!strcasecmp(s, "rdr")) + ipn.in_redir = NAT_REDIRECT; + else { + (void)fprintf(stderr, + "expected \"map\" or \"rdr\", got \"%s\"\n", s); + return NULL; + } + + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (interface)\n"); + return NULL; + } + strncpy(ipn.in_ifname, s, sizeof(ipn.in_ifname) - 1); + ipn.in_ifname[sizeof(ipn.in_ifname) - 1] = '\0'; + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (%s)\n", + ipn.in_redir ? "destination": "source"); + return NULL; + } + shost = s; + + if (ipn.in_redir == NAT_REDIRECT) { + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (destination port)\n"); + return NULL; + } + + if (strcasecmp(s, "port")) { + fprintf(stderr, "missing fields (port)\n"); + return NULL; + } + + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (destination port)\n"); + return NULL; + } + + dport = s; + } + + + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (->)\n"); + return NULL; + } + if (!strcmp(s, "->")) { + snetm = strrchr(shost, '/'); + if (!snetm) { + fprintf(stderr, "missing fields (%s netmask)\n", + ipn.in_redir ? "destination":"source"); + return NULL; + } + } else { + if (strcasecmp(s, "netmask")) { + fprintf(stderr, "missing fields (netmask)\n"); + return NULL; + } + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (%s netmask)\n", + ipn.in_redir ? "destination":"source"); + return NULL; + } + snetm = s; + } + + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (%s)\n", + ipn.in_redir ? "destination":"target"); + return NULL; + } + dhost = s; + + if (ipn.in_redir == NAT_MAP) { + if (!(s = strtok(NULL, " \t"))) { + dnetm = strrchr(dhost, '/'); + if (!dnetm) { + fprintf(stderr, + "missing fields (dest netmask)\n"); + return NULL; + } + } + if (!s || !strcasecmp(s, "portmap")) { + dnetm = strrchr(dhost, '/'); + if (!dnetm) { + fprintf(stderr, + "missing fields (dest netmask)\n"); + return NULL; + } + } else { + if (strcasecmp(s, "netmask")) { + fprintf(stderr, + "missing fields (dest netmask)\n"); + return NULL; + } + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, + "missing fields (dest netmask)\n"); + return NULL; + } + dnetm = s; + } + if (*dnetm == '/') + *dnetm++ = '\0'; + } else { + /* If it's a in_redir, expect target port */ + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (destination port)\n"); + return NULL; + } + + if (strcasecmp(s, "port")) { + fprintf(stderr, "missing fields (port)\n"); + return NULL; + } + + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing fields (destination port)\n"); + return NULL; + } + + tport = s; + } + + + if (*snetm == '/') + *snetm++ = '\0'; + + if (ipn.in_redir == NAT_MAP) { + ipn.in_inip = hostnum(shost, &resolved); + ipn.in_inmsk = hostmask(snetm); + ipn.in_outip = hostnum(dhost, &resolved); + ipn.in_outmsk = hostmask(dnetm); + } else { + ipn.in_inip = hostnum(dhost, &resolved); /* Inside is target */ + ipn.in_inmsk = hostmask("255.255.255.255"); + ipn.in_outip = hostnum(shost, &resolved); + ipn.in_outmsk = hostmask(snetm); + if (!(s = strtok(NULL, " \t"))) { + ipn.in_flags = IPN_TCP; /* XXX- TCP only by default */ + proto = "tcp"; + } else { + if (!strcasecmp(s, "tcp")) + ipn.in_flags = IPN_TCP; + else if (!strcasecmp(s, "udp")) + ipn.in_flags = IPN_UDP; + else if (!strcasecmp(s, "tcpudp")) + ipn.in_flags = IPN_TCPUDP; + else { + fprintf(stderr, + "expected protocol - got \"%s\"\n", s); + return NULL; + } + proto = s; + } + ipn.in_pmin = portnum(dport, proto); /* dest port */ + ipn.in_pmax = ipn.in_pmin; /* NECESSARY of removing nats */ + ipn.in_pnext = portnum(tport, proto); /* target port */ + s = NULL; /* That's all she wrote! */ + } + if (!s) + return &ipn; + if (strcasecmp(s, "portmap")) { + fprintf(stderr, "expected \"portmap\" - got \"%s\"\n", s); + return NULL; + } + if (!(s = strtok(NULL, " \t"))) + return NULL; + if (!strcasecmp(s, "tcp")) + ipn.in_flags = IPN_TCP; + else if (!strcasecmp(s, "udp")) + ipn.in_flags = IPN_UDP; + else if (!strcasecmp(s, "tcpudp")) + ipn.in_flags = IPN_TCPUDP; + else { + fprintf(stderr, "expected protocol name - got \"%s\"\n", s); + return NULL; + } + proto = s; + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "no port range found\n"); + return NULL; + } + if (!(t = strchr(s, ':'))) { + fprintf(stderr, "no port range in \"%s\"\n", s); + return NULL; + } + *t++ = '\0'; + ipn.in_pmin = portnum(s, proto); + ipn.in_pmax = portnum(t, proto); + return &ipn; +} + + +void parsefile(fd, file, opts) +int fd; +char *file; +int opts; +{ + char line[512], *s; + ipnat_t *np; + FILE *fp; + int linenum = 1; + + if (strcmp(file, "-")) + fp = fopen(file, "r"); + else + fp = stdin; + + while (fgets(line, sizeof(line) - 1, fp)) { + line[sizeof(line) - 1] = '\0'; + if ((s = strchr(line, '\n'))) + *s = '\0'; + if (!(np = parse(line))) { + if (*line) + fprintf(stderr, "%d: syntax error in \"%s\"\n", + linenum, line); + } else if (!(opts & 2)) { + if ((opts &16) && np) + printnat(np); + if (opts & 1) { + if (ioctl(fd, SIOCADNAT, np) == -1) + perror("ioctl(SIOCADNAT)"); + } else if (ioctl(fd, SIOCRMNAT, np) == -1) + perror("ioctl(SIOCRMNAT)"); + } + linenum++; + } + fclose(stdin); +} diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 4722a171713..cacc87448f0 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,11 +1,11 @@ -# $OpenBSD: Makefile,v 1.7 1996/04/22 01:26:48 deraadt Exp $ +# $OpenBSD: Makefile,v 1.8 1996/05/10 21:39:29 dm Exp $ # $NetBSD: Makefile,v 1.22 1996/03/28 21:32:58 mark Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 MAN= audio.4 bpf.4 ccd.4 clnp.4 cltp.4 ddb.4 drum.4 esis.4 fd.4 icmp.4 \ idp.4 imp.4 inet.4 ip.4 iso.4 lkm.4 lo.4 netintro.4 ns.4 nsip.4 \ null.4 pty.4 rnd.4 route.4 spp.4 tb.4 tcp.4 termios.4 tty.4 tp.4 udp.4 \ - unix.4 vnd.4 + unix.4 vnd.4 ipl.4 MLINKS+=fd.4 stderr.4 fd.4 stdin.4 fd.4 stdout.4 MLINKS+=netintro.4 networking.4 MLINKS+=rnd.4 srnd.4 rnd.4 urnd.4 rnd.4 prnd.4 diff --git a/share/man/man4/ipl.4 b/share/man/man4/ipl.4 new file mode 100644 index 00000000000..377a3383549 --- /dev/null +++ b/share/man/man4/ipl.4 @@ -0,0 +1,58 @@ +.TH IPL 4 +.SH NAME +ipl - IP packet log device +.SH DESCRIPTION +The \fBipl\fP pseudo device's purpose is to provide an easy way to gather +packet headers of packets you wish to log. If a packet header is to be +logged, the entire header is logged (including any IP options - TCP/UDP +options are not included when it calculates header size) or not at all. +The packet contents is also logged after the header. +.LP +.PP +Prepending every packet header logged is a structure containing information +relevant to the packet following and why it was logged. The structure's +format is as follows: +.LP +.nf +struct ipl_ci { + u_long sec; /* time when the packet was logged */ + u_long usec; + u_long plen; /* length of packet data logged */ + u_short hlen; /* length of headers logged */ + u_short rule; /* rule number (for log ...) or 0 if result = log */ + u_short flags:12; /* flags, ie BLOCK, PASS, SHORT, etc */ + u_short unit:4; /* interface unit # */ + u_char ifname[2]; /* 2 character interface abbreviation */ +}; +.nf +.PP +In the case of the header causing the buffer to finish on a non-32bit +boundary, padding will be `appended' to ensure that the next log entry +is aligned to a 32bit boundary. +.LP +.PP +If the packet contents is more then 128 bytes, then only 128 bytes of the +packet contents is logged. Should the packet contents finish on a non-32bit +boundary, then the last few bytes are not logged to ensure the log entry +is aligned to a 32bit boundary. + +\fBipl\fP is a read-only (sequential) character pseudo-device. + +The ioctls which are loaded with this device can be found under \fBipf(4)\fP. +The only ioctl which is used for logging and doesn't affect the filter is: +.LP +.nf + ioctl(fd, SIOCIPFFB, int *) +.fi +.PP +This ioctl flushes the log buffer and returns the number of bytes flushed. +.PP +There is currently no support for non-blocking IO with this device, meaning +all read operations should be considered blocking in nature (if there is no +data to read, it will sleep until some is made available). +.SH SEE ALSO +ipf(4) +.SH BUGS +Packet headers are dropped when the internal buffer (static size) fills. +.SH FILES +/dev/ipl0 diff --git a/usr.sbin/ipftest/Makefile b/usr.sbin/ipftest/Makefile index adfc9c02561..da6d7568f81 100644 --- a/usr.sbin/ipftest/Makefile +++ b/usr.sbin/ipftest/Makefile @@ -1,7 +1,7 @@ PROG= ipftest MAN= ipftest.1 -SRCS= ipt.c fil.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c ipft_tx.c \ - misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c +SRCS= ipt.c fil.c ipft_hx.c ipft_sn.c ipft_ef.c ipft_td.c ipft_pc.c \ + ipft_tx.c misc.c parse.c opt.c ip_frag.c ip_nat.c ip_state.c .PATH: ${.CURDIR}/../../sbin/ipf ${.CURDIR}/../../sbin/ipfstat ${.CURDIR}/../../sys/netinet CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sbin/ipf -I${.CURDIR}/../../sys/netinet diff --git a/usr.sbin/ipftest/ipft_ef.c b/usr.sbin/ipftest/ipft_ef.c index 8c0df1f719f..0febf3a6c3c 100644 --- a/usr.sbin/ipftest/ipft_ef.c +++ b/usr.sbin/ipftest/ipft_ef.c @@ -46,7 +46,7 @@ etherfind -n -t #include "ipt.h" #ifndef lint -static char sccsid[] = "@(#)ipft_ef.c 1.5 10/15/95 (C)1995 Darren Reed"; +static char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed"; #endif static int etherf_open(), etherf_close(), etherf_readip(); @@ -140,13 +140,8 @@ int cnt, *dir; break; } -#ifdef NEED_INET_ATON - ip->ip_src.s_addr = inet_aton(src); - ip->ip_dst.s_addr = inet_aton(dst); -#else (void) inet_aton(src, &ip->ip_src); (void) inet_aton(dst, &ip->ip_dst); -#endif ip->ip_len = atoi(len); ip->ip_hl = sizeof(struct ip); diff --git a/usr.sbin/ipftest/ipft_hx.c b/usr.sbin/ipftest/ipft_hx.c new file mode 100644 index 00000000000..ceed1189dfb --- /dev/null +++ b/usr.sbin/ipftest/ipft_hx.c @@ -0,0 +1,144 @@ +/* + * (C)opyright 1995 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. + */ +#include <stdio.h> +#include <ctype.h> +#include <assert.h> +#include <string.h> +#if !defined(__SVR4) && !defined(__svr4__) +#include <strings.h> +#else +#include <sys/byteorder.h> +#endif +#include <sys/types.h> +#include <sys/param.h> +#include <stdlib.h> +#include <unistd.h> +#include <stddef.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip_var.h> +#include <netinet/ip.h> +#include <netinet/udp.h> +#include <netinet/tcp.h> +#include <netinet/ip_icmp.h> +#include <netinet/tcpip.h> +#include <net/if.h> +#include <netdb.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include "ipf.h" +#include "ipt.h" + +#ifndef lint +static char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed"; +#endif + +extern int opts; +extern u_short portnum(); +extern u_long buildopts(); + +static int hex_open(), hex_close(), hex_readip(); +static char *readhex(); + +struct ipread iphex = { hex_open, hex_close, hex_readip }; +static FILE *tfp = NULL; +static int tfd = -1; + +static int hex_open(fname) +char *fname; +{ + if (tfp && tfd != -1) { + rewind(tfp); + return tfd; + } + + if (!strcmp(fname, "-")) { + tfd = 0; + tfp = stdin; + } else { + tfd = open(fname, O_RDONLY); + if (tfd != -1) + tfp = fdopen(tfd, "r"); + } + return tfd; +} + + +static int hex_close() +{ + int cfd = tfd; + + tfd = -1; + return close(cfd); +} + + +static int hex_readip(buf, cnt, ifn, dir) +char *buf, **ifn; +int cnt, *dir; +{ + register char *s; + struct ip *ip; + char line[513]; + + ip = (struct ip *)buf; + *ifn = NULL; + while (fgets(line, sizeof(line)-1, tfp)) { + if ((s = index(line, '\n'))) { + if (s == line) + return (char *)ip - buf; + *s = '\0'; + } + if ((s = index(line, '\r'))) + *s = '\0'; + if ((s = index(line, '#'))) + *s = '\0'; + if (!*line) + continue; + if (!(opts & OPT_BRIEF)) { + printf("input: %s\n", line); + fflush(stdout); + } + *ifn = NULL; + *dir = 0; + ip = (struct ip *)readhex(line, (char *)ip); + } + return -1; +} + + +static char *readhex(src, dst) +register char *src, *dst; +{ + int state = 0; + char c; + + while ((c = *src++)) { + if (isspace(c)) { + if (state) { + dst++; + state = 0; + } + continue; + } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F')) { + c = isdigit(c) ? (c - '0') : (toupper(c) - 55); + if (state == 0) { + *dst = (c << 4); + state++; + } else { + *dst++ |= c; + state = 0; + } + } else + break; + } + return dst; +} diff --git a/usr.sbin/ipftest/ipft_pc.c b/usr.sbin/ipftest/ipft_pc.c index 18bd29fa95a..72f94900fc0 100644 --- a/usr.sbin/ipftest/ipft_pc.c +++ b/usr.sbin/ipftest/ipft_pc.c @@ -1,5 +1,5 @@ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * (C)opyright 1993-1996 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -58,10 +58,25 @@ static struct llc llcs[DLT_MAX+1] = { static int pcap_open(), pcap_close(), pcap_readip(); -static int pfd = -1, s_type = -1; +static int pfd = -1, s_type = -1, swapped = 0; struct ipread pcap = { pcap_open, pcap_close, pcap_readip }; +#define SWAPLONG(y) \ + ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ + ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) + +static void swap_hdr(p) +pcaphdr_t *p; +{ + p->pc_v_maj = SWAPSHORT(p->pc_v_maj); + p->pc_v_min = SWAPSHORT(p->pc_v_min); + p->pc_zone = SWAPLONG(p->pc_zone); + p->pc_sigfigs = SWAPLONG(p->pc_sigfigs); + p->pc_slen = SWAPLONG(p->pc_slen); + p->pc_type = SWAPLONG(p->pc_type); +} static int pcap_open(fname) char *fname; @@ -80,6 +95,15 @@ char *fname; if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) return -2; + if (ph.pc_id != TCPDUMP_MAGIC) { + if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) { + (void) close(fd); + return -2; + } + swapped = 1; + swap_hdr(&ph); + } + if (ph.pc_v_maj != PCAP_VERSION_MAJ || ph.pc_type > DLT_MAX) { (void) close(fd); return -2; @@ -113,6 +137,12 @@ struct pcap_pkthdr *rec; if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) return -2; + if (swapped) { + rec->ph_clen = SWAPLONG(rec->ph_clen); + rec->ph_len = SWAPLONG(rec->ph_len); + rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec); + rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec); + } p = rec->ph_clen; n = MIN(p, rec->ph_len); if (!n || n < 0) diff --git a/usr.sbin/ipftest/ipft_td.c b/usr.sbin/ipftest/ipft_td.c index 7d9ea2b8849..828ac4e4fe1 100644 --- a/usr.sbin/ipftest/ipft_td.c +++ b/usr.sbin/ipftest/ipft_td.c @@ -55,7 +55,7 @@ tcpdump -nqte #include "ipt.h" #ifndef lint -static char sccsid[] = "@(#)ipft_td.c 1.7 1/12/96 (C)1995 Darren Reed"; +static char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed"; #endif static int tcpd_open(), tcpd_close(), tcpd_readip(); @@ -141,32 +141,19 @@ int cnt, *dir; if ((dots = count_dots(dst)) == 4) { s = strrchr(src, '.'); *s++ = '\0'; -#ifdef NEED_INET_ATON - ip->ip_src.s_addr = inet_aton(src); -#else (void) inet_aton(src, &ip->ip_src); -#endif pkt.ti_sport = htons(atoi(s)); *--s = '.'; s = strrchr(dst, '.'); *s++ = '\0'; -#ifdef NEED_INET_ATON - ip->ip_dst.s_addr = inet_aton(dst); -#else (void) inet_aton(src, &ip->ip_dst); -#endif pkt.ti_dport = htons(atoi(s)); *--s = '.'; } else { -#ifdef NEED_INET_ATON - ip->ip_src.s_addr = inet_aton(src); - ip->ip_dst.s_addr = inet_aton(dst); -#else (void) inet_aton(src, &ip->ip_src); (void) inet_aton(src, &ip->ip_dst); -#endif } ip->ip_len = ip->ip_hl = sizeof(struct ip); diff --git a/usr.sbin/ipftest/ipft_tx.c b/usr.sbin/ipftest/ipft_tx.c index a77c52b5ff9..277613ad356 100644 --- a/usr.sbin/ipftest/ipft_tx.c +++ b/usr.sbin/ipftest/ipft_tx.c @@ -30,15 +30,15 @@ #include <netinet/ip_icmp.h> #include <netinet/tcpip.h> #include <net/if.h> -#include "ip_fil.h" #include <netdb.h> #include <arpa/nameser.h> #include <resolv.h> +#include "ip_fil.h" #include "ipf.h" #include "ipt.h" #ifndef lint -static char sccsid[] = "@(#)ipft_tx.c 1.5 1/12/96 (C) 1993 Darren Reed"; +static char sccsid[] = "@(#)ipft_tx.c 1.6 2/4/96 (C) 1993 Darren Reed"; #endif extern int opts; @@ -185,7 +185,7 @@ int *out; return 1; } *last++ = '\0'; - tcp->th_sport = portnum(last); + tcp->th_sport = htons(portnum(last)); } ip->ip_src.s_addr = hostnum(*cpp, &r); cpp++; @@ -201,7 +201,7 @@ int *out; return 1; } *last++ = '\0'; - tcp->th_dport = portnum(last); + tcp->th_dport = htons(portnum(last)); } ip->ip_dst.s_addr = hostnum(*cpp, &r); cpp++; diff --git a/usr.sbin/ipftest/ipt.c b/usr.sbin/ipftest/ipt.c index f25165063c8..ca2aea33623 100644 --- a/usr.sbin/ipftest/ipt.c +++ b/usr.sbin/ipftest/ipt.c @@ -39,17 +39,18 @@ #include <ctype.h> #ifndef lint -static char sccsid[] = "@(#)ipt.c 1.15 1/7/96 (C) 1993-1996 Darren Reed"; +static char sccsid[] = "@(#)ipt.c 1.17 3/9/96 (C) 1993-1996 Darren Reed"; #endif extern int fr_check(); extern char *optarg; extern struct frentry *ipfilter[2][2]; -extern struct ipread snoop, etherf, tcpd, pcap, iptext; +extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; extern void debug(), verbose(); struct frentry *ft_in = NULL, *ft_out = NULL; -struct ipread *readers[] = { &iptext, ðerf, &tcpd, &snoop, &pcap, NULL }; +struct ipread *readers[] = { &iptext, ðerf, &tcpd, &snoop, &pcap, &iphex, + NULL }; int opts = 0; @@ -65,7 +66,7 @@ char *argv[]; char *rules = NULL, *datain = NULL, *iface = NULL; int fd, i, dir = 0; - while ((c = getopt(argc, argv, "I:PSTEbdi:r:v")) != -1) + while ((c = getopt(argc, argv, "bdEHi:I:Pr:STv")) != -1) switch (c) { case 'b' : @@ -91,6 +92,11 @@ char *argv[]; if (*r == ðerf) break; break; + case 'H' : + for (i = 0, r = readers; *r; i++, r++) + if (*r == &iphex) + break; + break; case 'P' : for (i = 0, r = readers; *r; i++, r++) if (*r == &pcap) @@ -172,6 +178,8 @@ char *argv[]; ip = (struct ip *)buf; while ((i = (*(*r)->r_readip)(buf, sizeof(buf), &iface, &dir)) > 0) { + ip->ip_off = ntohs(ip->ip_off); + ip->ip_len = ntohs(ip->ip_len); switch (fr_check(ip, ip->ip_hl << 2, iface, dir)) { case -1 : diff --git a/usr.sbin/ipftest/misc.c b/usr.sbin/ipftest/misc.c index 6329cd483b4..76069ec1960 100644 --- a/usr.sbin/ipftest/misc.c +++ b/usr.sbin/ipftest/misc.c @@ -38,7 +38,7 @@ #include "ipt.h" #ifndef lint -static char sccsid[] = "@(#)misc.c 1.2 1/12/96 (C) 1995 Darren Reed"; +static char sccsid[] = "@(#)misc.c 1.3 2/4/96 (C) 1995 Darren Reed"; #endif void debug(), verbose(); @@ -68,26 +68,6 @@ struct ip *ip; } -#ifdef NEED_INET_ATON -u_long inet_aton(buf) -char *buf; -{ - u_long n; - char *s = (char *)&n; - int a, b, c, d; - - if (sscanf(buf, "%d.%d.%d.%d", &a, &b, &c, &d) != 4) - return -1; - - *s++ = (u_char)a; - *s++ = (u_char)b; - *s++ = (u_char)c; - *s++ = (u_char)d; - return n; -} -#endif - - void verbose(fmt, p1, p2, p3, p4, p5, p6, p7, p8, p9) char *fmt, *p1, *p2, *p3, *p4, *p5, *p6, *p7,*p8,*p9; { diff --git a/usr.sbin/ipftest/pcap.h b/usr.sbin/ipftest/pcap.h index f7efe142c6e..94373c9c52d 100644 --- a/usr.sbin/ipftest/pcap.h +++ b/usr.sbin/ipftest/pcap.h @@ -1,5 +1,5 @@ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * (C)opyright 1993-1996 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -22,6 +22,8 @@ typedef struct pcap_filehdr { u_int pc_type; } pcaphdr_t; +#define TCPDUMP_MAGIC 0xa1b2c3d4 + #define PCAP_VERSION_MAJ 2 typedef struct pcap_pkthdr { diff --git a/usr.sbin/ipmon/ipmon.c b/usr.sbin/ipmon/ipmon.c index 101f2aa58eb..5f7d377ae71 100644 --- a/usr.sbin/ipmon/ipmon.c +++ b/usr.sbin/ipmon/ipmon.c @@ -1,5 +1,5 @@ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * (C)opyright 1993-1996 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -39,7 +39,7 @@ #include <arpa/inet.h> #ifndef lint -static char sccsid[] = "@(#)ipmon.c 1.16 1/12/96 (C)1995 Darren Reed"; +static char sccsid[] = "@(#)ipmon.c 1.20 3/24/96 (C)1993-1996 Darren Reed"; #endif #include "ip_fil.h" @@ -96,6 +96,34 @@ u_short port; } +static void dumphex(log, ip, lp) +FILE *log; +struct ip *ip; +struct ipl_ci *lp; +{ + int i, j, k; + u_char *s = (u_char *)ip; + + for (i = lp->plen + lp->hlen, j = 0; i; i--, j++, s++) { + if (j && !(j & 0xf)) + putchar('\n'); + printf("%02x", *s); + if (!((j + 1) & 0xf)) { + s -= 16; + printf(" "); + for (k = 16; k; k--, s++) + putchar(isprint(*s) ? *s : '.'); + } + + if ((j + 1) & 0xf) + putchar(' '); + } + + if ((j - 1) & 0xf) + putchar('\n'); +} + + static void printpacket(log, ip, lp, opts) FILE *log; struct ip *ip; @@ -122,9 +150,15 @@ int opts; tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900); t += strlen(t); } +#if !defined (__OpenBSD__) && !defined (__NetBSD__) (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %c%c%ld @%hd ", tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec, lp->ifname[0], lp->ifname[1], lp->unit, lp->rule); +#else /* OpenBSD or NetBSD */ + (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %s @%hd ", + tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec, + lp->ifname, lp->rule); +#endif /* OpenBSD or NetBSD */ pr = getprotobynumber((int)p); if (!pr) { proto = pname; @@ -158,10 +192,6 @@ int opts; c[2] = '\0'; (void) strcat(line, c); t = line + strlen(line); -#if SOLARIS - ip->ip_off = ntohs(ip->ip_off); - ip->ip_len = ntohs(ip->ip_len); -#endif if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !(ip->ip_off & 0x1fff)) { tp = (struct tcphdr *)((char *)ip + hl); @@ -236,6 +266,17 @@ int opts; ip->ip_len - hl, (ip->ip_off & 0x1fff) << 3); } t += strlen(t); + + if (lp->flags & FR_KEEPSTATE) { + (void) strcpy(t, " K-S"); + t += strlen(t); + } + + if (lp->flags & FR_KEEPFRAG) { + (void) strcpy(t, " K-F"); + t += strlen(t); + } + *t++ = '\n'; *t++ = '\0'; if (opts & 1) @@ -243,14 +284,17 @@ int opts; else (void) fprintf(log, "%s", line); fflush(log); + if (opts & 4) + dumphex(log, ip, lp); } -main(argc, argv) +int main(argc, argv) int argc; char *argv[]; { FILE *log; int fd, flushed = 0, opts = 0; + u_int len; char buf[512], c; struct ipl_ci iplci; extern int optind; @@ -261,7 +305,7 @@ char *argv[]; exit(-1); } - while ((c = getopt(argc, argv, "Nfs")) != -1) + while ((c = getopt(argc, argv, "Nfsx")) != -1) switch (c) { case 'f' : @@ -274,6 +318,9 @@ char *argv[]; case 'N' : opts |= 2; break; + case 'x' : + opts |= 4; + break; case 's' : openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC); opts |= 1; @@ -289,7 +336,8 @@ char *argv[]; assert(read(fd, &iplci, sizeof(struct ipl_ci)) == sizeof(struct ipl_ci)); assert(iplci.hlen > 0 && iplci.hlen <= 92); - assert((u_char)iplci.plen <= 128); + len = (u_int)iplci.plen; + assert(len <= 128); assert(read(fd, buf, iplci.hlen + iplci.plen) == (iplci.hlen + iplci.plen)); printpacket(log, buf, &iplci, opts); diff --git a/usr.sbin/ipsend/Makefile b/usr.sbin/ipsend/Makefile index 7d279e58224..b3523babb9f 100644 --- a/usr.sbin/ipsend/Makefile +++ b/usr.sbin/ipsend/Makefile @@ -1,9 +1,5 @@ -PROG= ipsend -NOMAN= -SRCS= iptests.c ip.c ipsend.c ipsopt.c resend.c sbpf.c sock.c 44arp.c ipft_sn.c ipft_pc.c -.PATH: ${.CURDIR}/../../usr.sbin/ipftest -CFLAGS+= -DDOSOCKET -I${.CURDIR}/../../usr.sbin/ipftest -I${.CURDIR}/../../sbin/ipf -I${.CURDIR}/../../sys/netinet -LDADD+= -lpcap +# $Id: Makefile,v 1.3 1996/05/10 21:40:48 dm Exp $ +SUBDIR= ipsend ipresend iptest -.include <bsd.prog.mk> +.include <bsd.subdir.mk> diff --git a/usr.sbin/ipsend/44arp.c b/usr.sbin/ipsend/common/44arp.c index 04afb619f24..04afb619f24 100644 --- a/usr.sbin/ipsend/44arp.c +++ b/usr.sbin/ipsend/common/44arp.c diff --git a/usr.sbin/ipsend/dltest.h b/usr.sbin/ipsend/common/dltest.h index 4c32c30eb1b..4c32c30eb1b 100644 --- a/usr.sbin/ipsend/dltest.h +++ b/usr.sbin/ipsend/common/dltest.h diff --git a/usr.sbin/ipsend/in_var.h b/usr.sbin/ipsend/common/in_var.h index 63980ef304e..63980ef304e 100644 --- a/usr.sbin/ipsend/in_var.h +++ b/usr.sbin/ipsend/common/in_var.h diff --git a/usr.sbin/ipsend/ip.c b/usr.sbin/ipsend/common/ip.c index e71eaabdba0..364f01c4376 100644 --- a/usr.sbin/ipsend/ip.c +++ b/usr.sbin/ipsend/common/ip.c @@ -75,7 +75,7 @@ struct in_addr gwip; free(buf); return -2; } - eh->ether_type = htons((u_short)ETHERTYPE_IP); + eh->ether_type = ETHERTYPE_IP; last_gw.s_addr = gwip.s_addr; err = sendip(nfd, s, sizeof(*eh) + len); free(buf); @@ -85,10 +85,11 @@ struct in_addr gwip; /* */ -int send_ip(nfd, mtu, ip, gwip) +int send_ip(nfd, mtu, ip, gwip, frag) int nfd, mtu; ip_t *ip; struct in_addr gwip; +int frag; { static struct in_addr last_gw; static char last_arp[6] = { 0, 0, 0, 0, 0, 0}; @@ -102,14 +103,15 @@ struct in_addr gwip; eh = (ether_header_t *)ipbuf; bzero(&eh->ether_shost, sizeof(eh->ether_shost)); - if (gwip.s_addr == last_gw.s_addr) + 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) { perror("arp"); return -2; } - eh->ether_type = htons((u_short)ETHERTYPE_IP); + bcopy(eh->ether_dhost, last_arp, sizeof(last_arp)); + eh->ether_type = ETHERTYPE_IP; bcopy((char *)ip, (char *)&ipsv, sizeof(*ip)); last_gw.s_addr = gwip.s_addr; @@ -122,7 +124,7 @@ struct in_addr gwip; if (!ip->ip_ttl) ip->ip_ttl = 60; - if (sizeof(*eh) + ntohs(ip->ip_len) < mtu) + if (!frag || (sizeof(*eh) + ntohs(ip->ip_len) < mtu)) { ip->ip_sum = 0; ip->ip_sum = chksum(ip, ip->ip_hl << 2); @@ -268,7 +270,7 @@ struct in_addr gwip; bcopy((char *)&ti->ti_sport, (char *)ip + (ip->ip_hl << 2), thlen); - return send_ip(nfd, mtu, ip, gwip); + return send_ip(nfd, mtu, ip, gwip, 1); } @@ -300,7 +302,7 @@ struct in_addr gwip; bcopy((char *)&ti->ti_sport, (char *)ip + (ip->ip_hl << 2), sizeof(udphdr_t)); - return send_ip(nfd, mtu, ip, gwip); + return send_ip(nfd, mtu, ip, gwip, 1); } @@ -319,7 +321,7 @@ struct in_addr gwip; ic->icmp_cksum = 0; ic->icmp_cksum = chksum((char *)ic, sizeof(struct icmp)); - return send_ip(nfd, mtu, ip, gwip); + return send_ip(nfd, mtu, ip, gwip, 1); } @@ -337,6 +339,6 @@ struct in_addr gwip; case IPPROTO_ICMP : return send_icmp(nfd, mtu, ip, gwip); default : - return send_ip(nfd, mtu, ip, gwip); + return send_ip(nfd, mtu, ip, gwip, 1); } } diff --git a/usr.sbin/ipsend/ip_compat.h b/usr.sbin/ipsend/common/ip_compat.h index a911fd83c3f..c600f17e258 100644 --- a/usr.sbin/ipsend/ip_compat.h +++ b/usr.sbin/ipsend/common/ip_compat.h @@ -5,7 +5,7 @@ * and is not changed in any way. The author accepts no responsibility * for the use of this software. I hate legaleese, don't you ? * - * @(#)ip_compat.h 1.1 9/14/95 + * @(#)ip_compat.h 1.2 12/7/95 */ /* @@ -194,7 +194,7 @@ typedef struct ether_header ether_header_t; #endif -#ifdef solaris +#if defined(__SVR4) || defined(__svr4__) # define bcopy(a,b,c) memmove(b,a,c) # define bcmp(a,b,c) memcmp(a,b,c) # define bzero(a,b) memset(a,0,b) diff --git a/usr.sbin/ipsend/ip_var.h b/usr.sbin/ipsend/common/ip_var.h index 92eb38a0bef..92eb38a0bef 100644 --- a/usr.sbin/ipsend/ip_var.h +++ b/usr.sbin/ipsend/common/ip_var.h diff --git a/usr.sbin/ipsend/sbpf.c b/usr.sbin/ipsend/common/sbpf.c index b6a6d36f6c1..b6a6d36f6c1 100644 --- a/usr.sbin/ipsend/sbpf.c +++ b/usr.sbin/ipsend/common/sbpf.c diff --git a/usr.sbin/ipsend/sock.c b/usr.sbin/ipsend/common/sock.c index a35ffc64d48..70c2e390cfc 100644 --- a/usr.sbin/ipsend/sock.c +++ b/usr.sbin/ipsend/common/sock.c @@ -8,7 +8,7 @@ * providing it is not modified and that this notice remains in tact. */ #ifndef lint -static char sccsid[] = "@(#)sock.c 1.1 8/19/95 (C)1995 Darren Reed"; +static char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed"; #endif #include <stdio.h> #include <unistd.h> @@ -77,7 +77,7 @@ struct proc *proc; int kmemcpy(buf, pos, n) char *buf; -off_t pos; +void *pos; int n; { static int kfd = -1; @@ -85,7 +85,7 @@ int n; if (kfd == -1) kfd = open(KMEM, O_RDONLY); - if (lseek(kfd, pos, SEEK_SET) == -1) + if (lseek(kfd, (off_t)(u_long)pos, SEEK_SET) == -1) { perror("lseek"); return -1; @@ -117,21 +117,21 @@ struct proc *getproc() fprintf(stderr, "nlist(%#x) == %d\n", names, n); return NULL; } - if (kmemcpy((char *)&nproc, (off_t)names[1].n_value, + if (kmemcpy((char *)&nproc, (void *)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, (off_t)names[0].n_value, sizeof(p)) == -1) + if (kmemcpy((char *)&p, (void *)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, (off_t)p, siz) == -1) + if (kmemcpy((char *)proc, (void *)p, siz) == -1) { fprintf(stderr, "read(%#x,%#x,%d) proc\n", p, proc, siz); @@ -165,14 +165,14 @@ struct tcpiphdr *ti; return NULL; up = (struct user *)malloc(sizeof(*up)); - if (kmemcpy((char *)up, (off_t)p->p_uarea, sizeof(*up)) == -1) + if (kmemcpy((char *)up, (void *)p->p_uarea, sizeof(*up)) == -1) { fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea); return NULL; } o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1)); - if (kmemcpy((char *)o, (off_t)up->u_ofile, + if (kmemcpy((char *)o, (void *)up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n", @@ -180,7 +180,7 @@ struct tcpiphdr *ti; return NULL; } f = (struct file *)calloc(1, sizeof(*f)); - if (kmemcpy((char *)f, (off_t)o[fd], sizeof(*f)) == -1) + if (kmemcpy((char *)f, (void *)o[fd], sizeof(*f)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n", up->u_ofile_arr[fd], f, sizeof(*f)); @@ -188,7 +188,7 @@ struct tcpiphdr *ti; } s = (struct socket *)calloc(1, sizeof(*s)); - if (kmemcpy((char *)s, (off_t)f->f_data, sizeof(*s)) == -1) + if (kmemcpy((char *)s, (void *)f->f_data, sizeof(*s)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n", o[fd], s, sizeof(*s)); @@ -196,7 +196,7 @@ struct tcpiphdr *ti; } i = (struct inpcb *)calloc(1, sizeof(*i)); - if (kmemcpy((char *)i, (off_t)s->so_pcb, sizeof(*i)) == -1) + if (kmemcpy((char *)i, (void *)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 +204,7 @@ struct tcpiphdr *ti; } t = (struct tcpcb *)calloc(1, sizeof(*t)); - if (kmemcpy((char *)t, (off_t)i->inp_ppcb, sizeof(*t)) == -1) + if (kmemcpy((char *)t, (void *)i->inp_ppcb, sizeof(*t)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n", i->inp_ppcb, t, sizeof(*t)); @@ -249,14 +249,14 @@ struct tcpiphdr *ti; return NULL; fd = (struct filedesc *)malloc(sizeof(*fd)); - if (kmemcpy((char *)fd, (off_t)p->kp_proc.p_fd, sizeof(*fd)) == -1) + if (kmemcpy((char *)fd, (void *)p->kp_proc.p_fd, sizeof(*fd)) == -1) { fprintf(stderr, "read(%#x,%#x) failed\n", p, p->kp_proc.p_fd); return NULL; } o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1)); - if (kmemcpy((char *)o, (off_t)fd->fd_ofiles, + if (kmemcpy((char *)o, (void *)fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n", @@ -264,7 +264,7 @@ struct tcpiphdr *ti; return NULL; } f = (struct file *)calloc(1, sizeof(*f)); - if (kmemcpy((char *)f, (off_t)o[tfd], sizeof(*f)) == -1) + if (kmemcpy((char *)f, (void *)o[tfd], sizeof(*f)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - o[tfd] - failed\n", o[tfd], f, sizeof(*f)); @@ -272,7 +272,7 @@ struct tcpiphdr *ti; } s = (struct socket *)calloc(1, sizeof(*s)); - if (kmemcpy((char *)s, (off_t)f->f_data, sizeof(*s)) == -1) + if (kmemcpy((char *)s, (void *)f->f_data, sizeof(*s)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n", f->f_data, s, sizeof(*s)); @@ -280,7 +280,7 @@ struct tcpiphdr *ti; } i = (struct inpcb *)calloc(1, sizeof(*i)); - if (kmemcpy((char *)i, (off_t)s->so_pcb, sizeof(*i)) == -1) + if (kmemcpy((char *)i, (void *)s->so_pcb, sizeof(*i)) == -1) { fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n", s->so_pcb, i, sizeof(*i)); @@ -288,7 +288,7 @@ struct tcpiphdr *ti; } t = (struct tcpcb *)calloc(1, sizeof(*t)); - if (kmemcpy((char *)t, (off_t)i->inp_ppcb, sizeof(*t)) == -1) + if (kmemcpy((char *)t, (void *)i->inp_ppcb, sizeof(*t)) == -1) { fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n", i->inp_ppcb, t, sizeof(*t)); @@ -353,7 +353,7 @@ int flags; perror("connect"); return -1; } - kmemcpy((char*)&tcb, (off_t)t, sizeof(tcb)); + kmemcpy((char*)&tcb, (void *)t, sizeof(tcb)); ti->ti_win = tcb.rcv_adv; ti->ti_seq = tcb.snd_nxt - 1; ti->ti_ack = tcb.rcv_nxt; diff --git a/usr.sbin/ipsend/tcpip.h b/usr.sbin/ipsend/common/tcpip.h index 78f274f0066..78f274f0066 100644 --- a/usr.sbin/ipsend/tcpip.h +++ b/usr.sbin/ipsend/common/tcpip.h diff --git a/usr.sbin/ipsend/ipresend/Makefile b/usr.sbin/ipsend/ipresend/Makefile new file mode 100644 index 00000000000..da0f8a37855 --- /dev/null +++ b/usr.sbin/ipsend/ipresend/Makefile @@ -0,0 +1,12 @@ +# $Id: Makefile,v 1.1 1996/05/10 21:40:57 dm Exp $ + +PROG= ipresend +BINDIR= /usr/sbin +NOMAN= +SRCS= ipresend.c resend.c ip.c sbpf.c sock.c 44arp.c ipft_sn.c ipft_pc.c +CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest \ + -I${.CURDIR}/../../../sbin/ipf \ + -I${.CURDIR}/../../../sys/netinet +.PATH: ${.CURDIR}/../common ${.CURDIR}/../../ipftest + +.include <bsd.prog.mk> diff --git a/usr.sbin/ipsend/ipresend/ipresend.c b/usr.sbin/ipsend/ipresend/ipresend.c new file mode 100644 index 00000000000..482811a4b53 --- /dev/null +++ b/usr.sbin/ipsend/ipresend/ipresend.c @@ -0,0 +1,140 @@ +/* + * ipsend.c (C) 1995 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. + */ +#ifndef lint +static char sccsid[] = "@(#)ipresend.c 1.1 1/11/96 (C)1995 Darren Reed"; +#endif +#include <stdio.h> +#include <netdb.h> +#include <string.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 <netinet/tcp.h> +#include <netinet/udp.h> +#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" + + +extern char *optarg; +extern int optind; +extern struct ipread snoop, pcap; + +#ifdef linux +char default_device[] = "eth0"; +#else +# ifdef sun +char default_device[] = "le0"; +# else +# ifdef ultrix +char default_device[] = "ln0"; +# else +# ifdef __bsdi__ +char default_device[] = "ef0"; +# else +char default_device[] = "lan0"; +# endif +# endif +# endif +#endif + + +void usage(prog) +char *prog; +{ + fprintf(stderr, "Usage: %s [options] <-r filename|-R filename>\n\ +\t\t-r filename\tsnoop data file to resend\n\ +\t\t-R filename\tlibpcap data file to resend\n\ +\toptions:\n\ +\t\t-d device\tSend out on this device\n\ +\t\t-g gateway\tIP gateway to use if non-local dest.\n\ +\t\t-m mtu\t\tfake MTU to use when sending out\n\ +", prog); + exit(1); +} + + +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; + + while ((c = getopt(argc, argv, "R:d:g:m:r:")) != -1) + switch (c) + { + case 'R' : + resend = optarg; + ipr = &pcap; + break; + case 'd' : + dev = optarg; + break; + case 'g' : + gateway = optarg; + break; + case 'm' : + mtu = atoi(optarg); + if (mtu < 28) + { + fprintf(stderr, "mtu must be > 28\n"); + exit(1); + } + case 'r' : + resend = optarg; + ipr = &snoop; + break; + break; + default : + fprintf(stderr, "Unknown option \"%c\"\n", c); + usage(name); + } + + if (!ipr || !resend) + usage(name); + + gwip.s_addr = 0; + if (gateway && resolve(gateway, (char *)&gwip) == -1) + { + fprintf(stderr,"Cant resolve %s\n", gateway); + exit(2); + } + + if (!dev) + dev = default_device; + + printf("Device: %s\n", dev); + printf("Gateway: %s\n", inet_ntoa(gwip)); + printf("mtu: %d\n", mtu); + + return ip_resend(dev, mtu, ipr, gwip, resend); +} diff --git a/usr.sbin/ipsend/resend.c b/usr.sbin/ipsend/ipresend/resend.c index c89db44ac84..8d9d75574d2 100644 --- a/usr.sbin/ipsend/resend.c +++ b/usr.sbin/ipsend/ipresend/resend.c @@ -8,7 +8,7 @@ * */ #ifndef lint -static char sccsid[] = "@(#)resend.c 1.2 8/25/95 (C)1995 Darren Reed"; +static char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed"; #endif #include <stdio.h> #include <netdb.h> @@ -91,7 +91,7 @@ char *datain; eh = (ether_header_t *)malloc(sizeof(*eh)); bzero(&eh->ether_shost, sizeof(eh->ether_shost)); - if (arp((char *)&gwip, dhost) == -1) + if (gwip.s_addr && (arp((char *)&gwip, dhost) == -1)) { perror("arp"); return -2; @@ -102,7 +102,14 @@ char *datain; len = ntohs(ip->ip_len); eh = (ether_header_t *)realloc((char *)eh, sizeof(*eh) + len); eh->ether_type = htons((u_short)ETHERTYPE_IP); - bcopy(dhost, (char *)&eh->ether_dhost, sizeof(dhost)); + 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); diff --git a/usr.sbin/ipsend/ipsend/Makefile b/usr.sbin/ipsend/ipsend/Makefile new file mode 100644 index 00000000000..4b2770b47ac --- /dev/null +++ b/usr.sbin/ipsend/ipsend/Makefile @@ -0,0 +1,10 @@ +# $Id: Makefile,v 1.1 1996/05/10 21:40:58 dm 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 +.PATH: ${.CURDIR}/../common + +.include <bsd.prog.mk> diff --git a/usr.sbin/ipsend/ipsend.c b/usr.sbin/ipsend/ipsend/ipsend.c index 0ffaa0915c8..13e89676965 100644 --- a/usr.sbin/ipsend/ipsend.c +++ b/usr.sbin/ipsend/ipsend/ipsend.c @@ -15,7 +15,7 @@ * This was written and tested (successfully) on SunOS 4.1.x. */ #ifndef lint -static char sccsid[] = "%W% %G% (C)1995 Darren Reed"; +static char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed"; #endif #include <stdio.h> #include <netdb.h> @@ -40,16 +40,10 @@ static char sccsid[] = "%W% %G% (C)1995 Darren Reed"; #endif #include "ipt.h" -#if defined (__OpenBSD__) || defined (__NetBSD__) -/* XXX - ipftest already has a pcap.h file, so just declare this here */ -char *pcap_lookupdev (char *); -#endif extern char *optarg; extern int optind; -extern struct ipread snoop, pcap; -struct ipread *readers[] = { &snoop, &pcap, NULL }; char options[68]; #ifdef linux char default_device[] = "eth0"; @@ -63,7 +57,7 @@ char default_device[] = "ln0"; # ifdef __bsdi__ char default_device[] = "ef0"; # else -char default_device[] = "le0"; +char default_device[] = "lan0"; # endif # endif # endif @@ -86,22 +80,6 @@ char *prog; \t\t-t port\t\tdestination port\n\ \t\t-U\t\tSet UDP protocol\n\ ", prog); - fprintf(stderr, "Usage: %s [options] -g gateway\n\ -\toptions:\n\ -\t\t-r filename\tsnoop data file to resend\n\ -\t\t-R filename\tlibpcap data file to resend\n\ -", prog); - fprintf(stderr, "Usage: %s [options] destination\n\ -\toptions:\n\ -\t\t-d device\tSend out on this device\n\ -\t\t-m mtu\t\tfake MTU to use when sending out\n\ -\t\t-s src\t\tsource address for IP packet\n\ -\t\t-1 \t\tPerform test 1 (IP header)\n\ -\t\t-2 \t\tPerform test 2 (IP options)\n\ -\t\t-3 \t\tPerform test 3 (ICMP)\n\ -\t\t-4 \t\tPerform test 4 (UDP)\n\ -\t\t-5 \t\tPerform test 5 (TCP)\n\ -", prog); exit(1); } @@ -180,12 +158,11 @@ char **argv; { struct tcpiphdr *ti; struct in_addr gwip; - struct ipread *ipr = NULL; tcphdr_t *tcp; ip_t *ip; char *name = argv[0], host[64], *gateway = NULL, *dev = NULL; - char *src = NULL, *dst, c, *s, *resend = NULL; - int mtu = 1500, olen = 0, tests = 0, pointtest = 0; + char *src = NULL, *dst, c, *s; + int mtu = 1500, olen = 0; /* * 65535 is maximum packet size...you never know... @@ -196,16 +173,9 @@ char **argv; ip->ip_len = sizeof(*ip); ip->ip_hl = sizeof(*ip) >> 2; - while ((c = getopt(argc, argv, "12345IP:R:TUd:f:g:m:o:p:r:s:t:")) != -1) + while ((c = getopt(argc, argv, "IP:TUd:f:g:m:o:s:t:")) != -1) switch (c) { - case '1' : - case '2' : - case '3' : - case '4' : - case '5' : - tests = c - '0'; - break; case 'I' : if (ip->ip_p) { @@ -232,10 +202,6 @@ char **argv; optarg); break; } - case 'R' : - resend = optarg; - ipr = &pcap; - break; case 'T' : if (ip->ip_p) { @@ -276,13 +242,6 @@ char **argv; case 'o' : olen = optname(optarg, options); break; - case 'p' : - pointtest = atoi(optarg); - break; - case 'r' : - resend = optarg; - ipr = &pcap; - break; case 's' : src = optarg; break; @@ -301,18 +260,9 @@ char **argv; usage(name); } - if (ipr) - { - if (!gateway) - usage(name); - dst = gateway; - } - else - { - if (argc - optind < 2 && !tests) - usage(name); - dst = argv[optind++]; - } + if (argc - optind < 2) + usage(name); + dst = argv[optind++]; if (!src) { @@ -336,11 +286,11 @@ char **argv; gwip = ip->ip_dst; else if (resolve(gateway, (char *)&gwip) == -1) { - fprintf(stderr,"Cant resolve %s\n", src); + fprintf(stderr,"Cant resolve %s\n", gateway); exit(2); } - if (!ipr && ip->ip_p == IPPROTO_TCP) + if (ip->ip_p == IPPROTO_TCP) for (s = argv[optind]; c = *s; s++) switch(c) { @@ -364,17 +314,8 @@ char **argv; break; } - if (!dev) { -#if defined (__OpenBSD__) || defined (__NetBSD__) - char errbuf[160]; - if (! (dev = pcap_lookupdev(errbuf))) { - fprintf (stderr, "%s", errbuf); - dev = default_device; - } -#else + if (!dev) dev = default_device; -#endif - } printf("Device: %s\n", dev); printf("Source: %s\n", inet_ntoa(ip->ip_src)); printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); @@ -396,25 +337,6 @@ char **argv; ip->ip_len += olen; } - switch (tests) - { - case 1 : - return ip_test1(dev, mtu, ti, gwip, pointtest); - case 2 : - return ip_test2(dev, mtu, ti, gwip, pointtest); - case 3 : - return ip_test3(dev, mtu, ti, gwip, pointtest); - case 4 : - return ip_test4(dev, mtu, ti, gwip, pointtest); - case 5 : - return ip_test5(dev, mtu, ti, gwip, pointtest); - default : - break; - } - - if (ipr) - return ip_resend(dev, mtu, ipr, gwip, resend); - #ifdef DOSOCKET if (tcp->th_dport) return do_socket(dev, mtu, ti, gwip); diff --git a/usr.sbin/ipsend/ipsopt.c b/usr.sbin/ipsend/ipsend/ipsopt.c index 8088bed3819..13d9e49d002 100644 --- a/usr.sbin/ipsend/ipsopt.c +++ b/usr.sbin/ipsend/ipsend/ipsopt.c @@ -6,7 +6,7 @@ * for the use of this software. I hate legaleese, don't you ? */ #ifndef lint -static char sccsid[] = "@(#)opt.c 1.1 8/19/95 (C)1995 Darren Reed"; +static char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; #endif #include <stdio.h> #include <string.h> @@ -34,7 +34,7 @@ struct ipopt_names ionames[] = { { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */ { IPOPT_SATID, 0x20, 4, "satid" }, { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */ - { 0, NULL } /* must be last */ + { 0, 0, 0, NULL } /* must be last */ }; struct ipopt_names secnames[] = { diff --git a/usr.sbin/ipsend/iptest/Makefile b/usr.sbin/ipsend/iptest/Makefile new file mode 100644 index 00000000000..17cdef66a36 --- /dev/null +++ b/usr.sbin/ipsend/iptest/Makefile @@ -0,0 +1,10 @@ +# $Id: Makefile,v 1.1 1996/05/10 21:40:59 dm Exp $ + +PROG= iptest +BINDIR= /usr/sbin +NOMAN= +SRCS= iptest.c iptests.c ip.c sbpf.c sock.c 44arp.c +CFLAGS+= -DDOSOCKET -I${.CURDIR}/../common -I${.CURDIR}/../../ipftest +.PATH: ${.CURDIR}/../common + +.include <bsd.prog.mk> diff --git a/usr.sbin/ipsend/iptest/iptest.c b/usr.sbin/ipsend/iptest/iptest.c new file mode 100644 index 00000000000..bc875881b29 --- /dev/null +++ b/usr.sbin/ipsend/iptest/iptest.c @@ -0,0 +1,204 @@ +/* + * ipsend.c (C) 1995 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. + */ +#ifndef lint +static char sccsid[] = "%W% %G% (C)1995 Darren Reed"; +#endif +#include <stdio.h> +#include <netdb.h> +#include <string.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 <netinet/tcp.h> +#include <netinet/udp.h> +#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" + + +extern char *optarg; +extern int optind; + +char options[68]; +#ifdef linux +char default_device[] = "eth0"; +#else +# ifdef sun +char default_device[] = "le0"; +# else +# ifdef ultrix +char default_device[] = "ln0"; +# else +# ifdef __bsdi__ +char default_device[] = "ef0"; +# else +char default_device[] = "lan0"; +# endif +# endif +# endif +#endif + + +void usage(prog) +char *prog; +{ + fprintf(stderr, "Usage: %s [options] dest\n\ +\toptions:\n\ +\t\t-d device\tSend out on this device\n\ +\t\t-g gateway\tIP gateway to use if non-local dest.\n\ +\t\t-m mtu\t\tfake MTU to use when sending out\n\ +\t\t-p pointtest\t\n\ +\t\t-s src\t\tsource address for IP packet\n\ +\t\t-1 \t\tPerform test 1 (IP header)\n\ +\t\t-2 \t\tPerform test 2 (IP options)\n\ +\t\t-3 \t\tPerform test 3 (ICMP)\n\ +\t\t-4 \t\tPerform test 4 (UDP)\n\ +\t\t-5 \t\tPerform test 5 (TCP)\n\ +\t\t-6 \t\tPerform test 6 (overlapping fragments)\n\ +\t\t-7 \t\tPerform test 7 (random packets)\n\ +", prog); + exit(1); +} + + +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, c, *s; + int mtu = 1500, tests = 0, pointtest = 0; + + /* + * 65535 is maximum packet size...you never know... + */ + ip = (ip_t *)calloc(1, 65536); + ti = (struct tcpiphdr *)ip; + 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) + switch (c) + { + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + tests = c - '0'; + break; + case 'd' : + dev = optarg; + break; + case 'g' : + gateway = optarg; + break; + case 'm' : + mtu = atoi(optarg); + if (mtu < 28) + { + fprintf(stderr, "mtu must be > 28\n"); + exit(1); + } + break; + case 'p' : + pointtest = atoi(optarg); + break; + case 's' : + src = optarg; + break; + default : + fprintf(stderr, "Unknown option \"%c\"\n", c); + usage(name); + } + + if (argc - optind < 2 && !tests) + usage(name); + dst = argv[optind++]; + + if (!src) + { + gethostname(host, sizeof(host)); + src = host; + } + + if (resolve(dst, (char *)&ip->ip_dst) == -1) + { + fprintf(stderr,"Cant resolve %s\n", dst); + exit(2); + } + + if (resolve(src, (char *)&ip->ip_src) == -1) + { + fprintf(stderr,"Cant resolve %s\n", src); + exit(2); + } + + if (!gateway) + gwip = ip->ip_dst; + else if (resolve(gateway, (char *)&gwip) == -1) + { + fprintf(stderr,"Cant resolve %s\n", gateway); + exit(2); + } + + + if (!dev) + dev = default_device; + printf("Device: %s\n", dev); + printf("Source: %s\n", inet_ntoa(ip->ip_src)); + printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); + printf("Gateway: %s\n", inet_ntoa(gwip)); + printf("mtu: %d\n", mtu); + + switch (tests) + { + case 1 : + return ip_test1(dev, mtu, ti, gwip, pointtest); + case 2 : + return ip_test2(dev, mtu, ti, gwip, pointtest); + case 3 : + return ip_test3(dev, mtu, ti, gwip, pointtest); + case 4 : + return ip_test4(dev, mtu, ti, gwip, pointtest); + case 5 : + return ip_test5(dev, mtu, ti, gwip, pointtest); + case 6 : + return ip_test6(dev, mtu, ti, gwip, pointtest); + case 7 : + return ip_test7(dev, mtu, ti, gwip, pointtest); + default : + break; + } + return 0; +} diff --git a/usr.sbin/ipsend/iptests.c b/usr.sbin/ipsend/iptest/iptests.c index 57752b306d8..9c74804963a 100644 --- a/usr.sbin/ipsend/iptests.c +++ b/usr.sbin/ipsend/iptest/iptests.c @@ -12,9 +12,32 @@ static char sccsid[] = "%W% %G% (C)1995 Darren Reed"; #include <sys/types.h> #include <sys/time.h> #include <sys/param.h> +#if !defined(solaris) +# define _KERNEL +# define KERNEL +# include <sys/file.h> +# undef _KERNEL +# undef KERNEL +# include <nlist.h> +# include <sys/user.h> +# include <sys/proc.h> +#endif +#include <kvm.h> +#include <sys/socket.h> +#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> +#endif #include <netinet/in_systm.h> #include <sys/socket.h> #include <net/if.h> +#include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> @@ -22,13 +45,14 @@ static char sccsid[] = "%W% %G% (C)1995 Darren Reed"; #include <netinet/ip_icmp.h> #include <netinet/if_ether.h> #include <netinet/ip_var.h> -#include <netinet/tcpip.h> +#include <netinet/in_pcb.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> #include "ip_compat.h" -#ifndef sun -#if !defined (__OpenBSD__) && !defined (__NetBSD__) +#ifdef linux #include "tcpip.h" -#endif #else +#include <netinet/tcpip.h> # if defined(__SVR4) || defined(__svr4__) #include <sys/sysmacros.h> # endif @@ -75,7 +99,7 @@ int ptest; printf("1.1. sending packets with ip_hl < ip_len\n"); for (i = 0; i < ((sizeof(*ip) + u->uh_ulen) >> 2); i++) { ip->ip_hl = i >> 2; - (void) send_ip(nfd, 1500, ip, gwip); + (void) send_ip(nfd, 1500, ip, gwip, 1); printf("%d\r", i); fflush(stdout); PAUSE(); @@ -91,7 +115,7 @@ int ptest; printf("1.2. sending packets with ip_hl > ip_len\n"); for (; i < ((sizeof(*ip) * 2 + u->uh_ulen) >> 2); i++) { ip->ip_hl = i >> 2; - (void) send_ip(nfd, 1500, ip, gwip); + (void) send_ip(nfd, 1500, ip, gwip, 1); printf("%d\r", i); fflush(stdout); PAUSE(); @@ -108,7 +132,7 @@ int ptest; ip->ip_hl = sizeof(*ip) >> 2; for (i = 0; i < 4; i++) { ip->ip_v = i; - (void) send_ip(nfd, 1500, ip, gwip); + (void) send_ip(nfd, 1500, ip, gwip, 1); printf("%d\r", i); fflush(stdout); PAUSE(); @@ -124,7 +148,7 @@ int ptest; printf("1.4. ip_v > 4\n"); for (i = 5; i < 16; i++) { ip->ip_v = i; - (void) send_ip(nfd, 1500, ip, gwip); + (void) send_ip(nfd, 1500, ip, gwip, 1); printf("%d\r", i); fflush(stdout); PAUSE(); @@ -205,7 +229,7 @@ int ptest; ip->ip_id = 0; ip->ip_len = sizeof(*ip); ip->ip_off = htons(IP_MF); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); @@ -213,7 +237,7 @@ int ptest; ip->ip_id = 0; ip->ip_len = sizeof(*ip); ip->ip_off = htons(IP_MF); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); @@ -221,7 +245,7 @@ int ptest; ip->ip_id = 0; ip->ip_len = sizeof(*ip); ip->ip_off = htons(0xa000); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); @@ -229,7 +253,7 @@ int ptest; ip->ip_id = 0; ip->ip_len = sizeof(*ip); ip->ip_off = htons(0x0100); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); } @@ -248,7 +272,7 @@ int ptest; printf("1.8. 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); + (void) send_ip(nfd, mtu, ip, gwip, 1); printf("%d\r", i); } else printf("skip 0\n"); @@ -258,7 +282,7 @@ int ptest; for (; i < (63 * 1024 + 768); i += 768) { ip->ip_off = IP_MF | (i >> 3); if ((rand() & 0x1f) != 0) { - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); printf("%d\r", i); } else printf("skip %d\n", i); @@ -268,7 +292,7 @@ int ptest; ip->ip_len = 896 + 20; ip->ip_off = IP_MF | (i >> 3); if ((rand() & 0x1f) != 0) { - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); printf("%d\r", i); } else printf("skip\n"); @@ -285,7 +309,7 @@ int ptest; ip->ip_id = 0; ip->ip_off = 0x8000; printf("1.9. ip_off & 0x8000 == 0x8000\n"); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); } @@ -299,19 +323,19 @@ int ptest; ip->ip_id = 0; ip->ip_ttl = 255; printf("1.10.0 ip_ttl = 255\n"); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); ip->ip_ttl = 128; printf("1.10.1 ip_ttl = 128\n"); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); ip->ip_ttl = 0; printf("1.10.2 ip_ttl = 0\n"); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); } @@ -349,7 +373,7 @@ int ptest; s[IPOPT_OFFSET] = IPOPT_MINOFF; ip->ip_p = IPPROTO_IP; printf("2.1 option length > packet length\n"); - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); } @@ -363,42 +387,42 @@ int ptest; printf("2.2.1 option length = 0, RR\n"); s[IPOPT_OPTVAL] = IPOPT_RR; s[IPOPT_OLEN] = 0; - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); printf("2.2.2 option length = 0, TS\n"); s[IPOPT_OPTVAL] = IPOPT_TS; s[IPOPT_OLEN] = 0; - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); printf("2.2.3 option length = 0, SECURITY\n"); s[IPOPT_OPTVAL] = IPOPT_SECURITY; s[IPOPT_OLEN] = 0; - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); printf("2.2.4 option length = 0, LSRR\n"); s[IPOPT_OPTVAL] = IPOPT_LSRR; s[IPOPT_OLEN] = 0; - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); printf("2.2.5 option length = 0, SATID\n"); s[IPOPT_OPTVAL] = IPOPT_SATID; s[IPOPT_OLEN] = 0; - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); printf("2.2.6 option length = 0, SSRR\n"); s[IPOPT_OPTVAL] = IPOPT_SSRR; s[IPOPT_OLEN] = 0; - (void) send_ip(nfd, mtu, ip, gwip); + (void) send_ip(nfd, mtu, ip, gwip, 1); fflush(stdout); PAUSE(); } @@ -913,20 +937,85 @@ int ptest; PAUSE(); } +#if !defined(linux) && !defined(__SVR4) && !defined(__svr4__) + { + struct tcpcb *t, tcb; + struct tcpiphdr ti; + struct sockaddr_in sin; + int fd, slen; + + bzero((char *)&sin, sizeof(sin)); + + for (i = 1; i < 63; i++) { + fd = socket(AF_INET, SOCK_STREAM, 0); + sin.sin_addr.s_addr = ip->ip_dst.s_addr; + sin.sin_port = htons(i); + if (!connect(fd, (struct sockaddr *)&sin, sizeof(sin))) + break; + } + + if (i == 63) { + printf("Couldn't open a TCP socket between ports 1 and 63\n"); + printf("to host %s for test 5 and 6 - skipping.\n", + inet_ntoa(ip->ip_dst)); + goto skip_five_and_six; + } + + bcopy((char *)ip, (char *)&ti, sizeof(*ip)); + ti.ti_dport = 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))) { + printf("Can't find PCB\n"); + goto skip_five_and_six; + } + kmemcpy((char*)&tcb, (void *)t, sizeof(tcb)); + ti.ti_win = tcb.rcv_adv; + ti.ti_seq = tcb.snd_nxt - 1; + ti.ti_ack = tcb.rcv_nxt; + if (!ptest || (ptest == 5)) { - t->th_win = 4096; /* - * Test 5: urp, urp = 0, urp > packetlen, urp < header + * Test 5: urp */ + printf("5.1 TCP Urgent pointer\n"); + ti.ti_urp = 1; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + ti.ti_urp = 0x7fff; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + ti.ti_urp = 0x8000; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); + ti.ti_urp = 0xffff; + (void) send_tcp(nfd, mtu, ip, gwip); + PAUSE(); } 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++) { + ti.ti_off = ntohs(i); + (void) send_tcp(nfd, mtu, ip, gwip); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); } + (void) close(fd); + } +skip_five_and_six: +#endif + t->th_seq = 1; + t->th_ack = 1; + if (!ptest || (ptest == 7)) { t->th_off = 0; t->th_flags = TH_SYN; @@ -1002,3 +1091,131 @@ int ptest; PAUSE(); } } + + +/* Perform test 6 (exhaust mbuf test) */ + +void ip_test6(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + struct timeval tv; + udphdr_t *u; + int nfd, i, j, k, len, id = getpid(); + + ip->ip_v = IPVERSION; + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_ttl = 60; + ip->ip_p = IPPROTO_UDP; + ip->ip_sum = 0; + u = (udphdr_t *)(ip + 1); + u->uh_sport = 1; + u->uh_dport = 9; + u->uh_sum = 0; + + nfd = initdevice(dev, u->uh_sport, 1); + u->uh_sport = htons(u->uh_sport); + u->uh_dport = htons(u->uh_dport); + u->uh_ulen = 7168; + + for (i = 0; i < 65536; i++) { + /* + * First send the entire packet in 768 byte chunks. + */ + ip->ip_len = sizeof(*ip) + 768 + sizeof(*u); + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_off = IP_MF; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, 0); + fflush(stdout); + PAUSE(); + /* + * And again using 128 byte chunks. + */ + ip->ip_len = sizeof(*ip) + 128 + sizeof(*u); + ip->ip_off = IP_MF; + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, 0); + fflush(stdout); + PAUSE(); + + for (j = 768; j < 3584; j += 768) { + ip->ip_len = sizeof(*ip) + 768; + ip->ip_off = IP_MF|(j>>3); + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, j); + fflush(stdout); + PAUSE(); + + ip->ip_len = sizeof(*ip) + 128; + for (k = j - 768; k < j; k += 128) { + ip->ip_off = IP_MF|(k>>3); + (void) send_ip(nfd, 1500, ip, gwip, 1); + printf("%d %d\r", i, k); + fflush(stdout); + PAUSE(); + } + } + } + putchar('\n'); +} + + +/* Perform test 7 (random packets) */ + +static u_long tbuf[64]; + +void ip_test7(dev, mtu, ip, gwip, ptest) +char *dev; +int mtu; +ip_t *ip; +struct in_addr gwip; +int ptest; +{ + ip_t *pip; + struct timeval tv; + int nfd, i, j; + u_char *s; + + nfd = initdevice(dev, 0, 1); + pip = (ip_t *)tbuf; + + srand(time(NULL) ^ (getpid() * getppid())); + + printf("7. send 1024 random IP packets.\n"); + + for (i = 0; i < 512; i++) { + for (s = (u_char *)pip, j = 0; j < sizeof(tbuf); j++, s++) + *s = (rand() >> 13) & 0xff; + pip->ip_v = IPVERSION; + bcopy((char *)&ip->ip_dst, (char *)&pip->ip_dst, + sizeof(struct in_addr)); + pip->ip_sum = 0; + pip->ip_len &= 0xff; + (void) send_ip(nfd, mtu, pip, gwip, 0); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); + + for (i = 0; i < 512; i++) { + for (s = (u_char *)pip, j = 0; j < sizeof(tbuf); j++, s++) + *s = (rand() >> 13) & 0xff; + pip->ip_v = IPVERSION; + pip->ip_off &= 0xc000; + bcopy((char *)&ip->ip_dst, (char *)&pip->ip_dst, + sizeof(struct in_addr)); + pip->ip_sum = 0; + pip->ip_len &= 0xff; + (void) send_ip(nfd, mtu, pip, gwip, 0); + printf("%d\r", i); + fflush(stdout); + PAUSE(); + } + putchar('\n'); +} |