From aeb497128e2171f13e610fdc1ec1053a241f5ffc Mon Sep 17 00:00:00 2001 From: Darren Reed Date: Sat, 15 Feb 2003 06:25:25 +0000 Subject: [PATCH] Commit import changed from vendor branch of ipfilter to -current head --- sys/contrib/ipfilter/netinet/ip_auth.c | 6 - sys/contrib/ipfilter/netinet/ip_fil.c | 6 - sys/contrib/ipfilter/netinet/ip_fil.h | 16 +- sys/contrib/ipfilter/netinet/ip_frag.c | 2 +- sys/contrib/ipfilter/netinet/ip_ftp_pxy.c | 284 ++++++++++++++++----- sys/contrib/ipfilter/netinet/ip_log.c | 27 +- sys/contrib/ipfilter/netinet/ip_nat.c | 86 ++++++- sys/contrib/ipfilter/netinet/ip_nat.h | 2 + sys/contrib/ipfilter/netinet/ip_proxy.c | 22 +- sys/contrib/ipfilter/netinet/ip_proxy.h | 1 + sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c | 3 +- sys/contrib/ipfilter/netinet/ip_state.c | 47 ++-- sys/contrib/ipfilter/netinet/ipl.h | 2 +- 13 files changed, 383 insertions(+), 121 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index a439a688cb7c..b7e66ffcdacb 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -298,15 +298,9 @@ ip_t *ip; cv_signal(&ipfauthwait); #else # if defined(BSD) && !defined(sparc) && (BSD >= 199306) -<<<<<<< ip_auth.c - if (!fin->fin_out) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); -======= if (fin->fin_out == 0) { ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); ->>>>>>> 1.1.1.11 } # endif fr_authpkts[i] = m; diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c index c2961cc4d268..ec4f041dc290 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.c +++ b/sys/contrib/ipfilter/netinet/ip_fil.c @@ -504,15 +504,9 @@ int ipl_disable() int ipldetach() # endif { -<<<<<<< ip_fil.c - int s, i = FR_INQUE|FR_OUTQUE; -#if defined(NETBSD_PF) && \ - ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) -======= int s, i; #if defined(NETBSD_PF) && \ ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) ->>>>>>> 1.1.1.17 int error = 0; # if __NetBSD_Version__ >= 105150000 struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index ae5025c5c580..bf407c27af61 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -64,6 +64,7 @@ # define SIOCSTGET _IOWR('r', 81, struct ipstate_save *) # define SIOCSTGSZ _IOWR('r', 82, struct natget) # define SIOCGFRST _IOWR('r', 83, struct ipfrstat *) +# define SIOCIPFL6 _IOWR('r', 84, int) #else # define SIOCADAFR _IOW(r, 60, struct frentry *) # define SIOCRMAFR _IOW(r, 61, struct frentry *) @@ -89,6 +90,7 @@ # define SIOCSTGET _IOWR(r, 81, struct ipstate_save *) # define SIOCSTGSZ _IOWR(r, 82, struct natget) # define SIOCGFRST _IOWR(r, 83, struct ipfrstat *) +# define SIOCIPFL6 _IOWR(r, 84, int) #endif #define SIOCADDFR SIOCADAFR #define SIOCDELFR SIOCRMAFR @@ -413,14 +415,16 @@ typedef struct frgroup { * structure which is then followed by any packet data. */ typedef struct iplog { - u_32_t ipl_magic; - u_int ipl_count; - u_long ipl_sec; - u_long ipl_usec; - size_t ipl_dsize; + u_32_t ipl_magic; + u_int ipl_count; + struct timeval ipl_tv; + size_t ipl_dsize; struct iplog *ipl_next; } iplog_t; +#define ipl_sec ipl_tv.tv_sec +#define ipl_usec ipl_tv.tv_usec + #define IPL_MAGIC 0x49504c4d /* 'IPLM' */ #define IPLOG_SIZE sizeof(iplog_t) @@ -614,7 +618,7 @@ extern int ipflog __P((u_int, ip_t *, fr_info_t *, mb_t *)); extern int ipllog __P((int, fr_info_t *, void **, size_t *, int *, int)); extern int ipflog_read __P((minor_t, struct uio *)); -extern int frflush __P((minor_t, int)); +extern int frflush __P((minor_t, int, int)); extern void frsync __P((void)); extern frgroup_t *fr_addgroup __P((u_32_t, frentry_t *, minor_t, int)); extern void fr_delgroup __P((u_32_t, u_32_t, minor_t, int)); diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index e789860e0e09..855087a783f0 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -7,7 +7,7 @@ # define _KERNEL #endif -#ifdef __sgi +#if defined(__sgi) && (IRIX > 602) # include #endif #include diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index b6644b92199e..56973da684f8 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -39,24 +39,30 @@ extern kmutex_t ipf_rw; #define FTPXY_PASS_2 14 #define FTPXY_PAOK_2 15 +/* + * Values for FTP commands. Numerics cover 0-999 + */ +#define FTPXY_C_PASV 1000 + int ippr_ftp_client __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); int ippr_ftp_complete __P((char *, size_t)); int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); int ippr_ftp_init __P((void)); int ippr_ftp_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_ftp_pasv __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); +int ippr_ftp_pasv __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); int ippr_ftp_port __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); int ippr_ftp_process __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_valid __P((int, char *, size_t)); -int ippr_ftp_server_valid __P((char *, size_t)); -int ippr_ftp_client_valid __P((char *, size_t)); +int ippr_ftp_valid __P((ftpinfo_t *, int, char *, size_t)); +int ippr_ftp_server_valid __P((ftpside_t *, char *, size_t)); +int ippr_ftp_client_valid __P((ftpside_t *, char *, size_t)); u_short ippr_ftp_atoi __P((char **)); static frentry_t ftppxyfr; int ippr_ftp_pasvonly = 0; int ippr_ftp_insecure = 0; +int ippr_ftp_forcepasv = 0; /* @@ -123,8 +129,13 @@ int dlen; /* * Check for client sending out PORT message. */ - if (dlen < IPF_MINPORTLEN) + if (dlen < IPF_MINPORTLEN) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", dlen); +#endif return 0; + } off = fin->fin_hlen + (tcp->th_off << 2); /* * Skip the PORT command + space @@ -134,23 +145,39 @@ int dlen; * Pick out the address components, two at a time. */ a1 = ippr_ftp_atoi(&s); - if (!s) + if (s == NULL) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_port:ippr_ftp_atoi(1) failed\n"); +#endif return 0; + } a2 = ippr_ftp_atoi(&s); - if (!s) + if (s == NULL) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_port:ippr_ftp_atoi(2) failed\n"); +#endif return 0; + } /* * check that IP address in the PORT/PASV reply is the same as the * sender of the command - prevents using PORT for port scanning. */ a1 <<= 16; a1 |= a2; - if (a1 != ntohl(nat->nat_inip.s_addr)) + if (a1 != ntohl(nat->nat_inip.s_addr)) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_port:a1 != nat->nat_inip\n"); +#endif return 0; + } a5 = ippr_ftp_atoi(&s); - if (!s) + if (s == NULL) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_port:ippr_ftp_atoi(3) failed\n"); +#endif return 0; + } if (*s == ')') s++; @@ -162,8 +189,12 @@ int dlen; if ((*s == '\r') && (*(s + 1) == '\n')) { s += 2; a6 = a5 & 0xff; - } else + } else { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_port:missing cr-lf\n"); +#endif return 0; + } a5 >>= 8; a5 &= 0xff; /* @@ -181,8 +212,13 @@ int dlen; nlen = strlen(newbuf); inc = nlen - olen; - if ((inc + ip->ip_len) > 65535) + if ((inc + ip->ip_len) > 65535) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n", inc); +#endif return 0; + } #if !defined(_KERNEL) m = *((mb_t **)fin->fin_mp); @@ -253,8 +289,13 @@ int dlen; * Don't allow the PORT command to specify a port < 1024 due to * security crap. */ - if (sp < 1024) + if (sp < 1024) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_port:sp(%d) < 1024\n", sp); +#endif return 0; + } + /* * The server may not make the connection back from port 20, but * it is the most likely so use it here to check for a conflicting @@ -369,11 +410,11 @@ int dlen; } -int ippr_ftp_pasv(fin, ip, nat, f, dlen) +int ippr_ftp_pasv(fin, ip, nat, ftp, dlen) fr_info_t *fin; ip_t *ip; nat_t *nat; -ftpside_t *f; +ftpinfo_t *ftp; int dlen; { tcphdr_t *tcp, tcph, *tcp2 = &tcph; @@ -381,23 +422,45 @@ int dlen; u_int a1, a2, a3, a4; u_short a5, a6, dp; fr_info_t fi; + ftpside_t *f; nat_t *ipn; int inc; char *s; + if (ippr_ftp_forcepasv != 0 && + ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n", + ftp->ftp_side[0].ftps_cmds); +#endif + return 0; + } + + f = &ftp->ftp_side[1]; + #define PASV_REPLEN 24 /* * Check for PASV reply message. */ - if (dlen < IPF_MIN227LEN) + if (dlen < IPF_MIN227LEN) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", dlen); +#endif return 0; - else if (strncmp(f->ftps_rptr, "227 Entering Passive Mod", PASV_REPLEN)) + } else if (strncmp(f->ftps_rptr, + "227 Entering Passive Mod", PASV_REPLEN)) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_pasv:227 reply wrong\n"); +#endif return 0; + } tcp = (tcphdr_t *)fin->fin_dp; /* - * Skip the PORT command + space + * Skip the PASV reply + space */ s = f->ftps_rptr + PASV_REPLEN; while (*s && !isdigit(*s)) @@ -406,11 +469,19 @@ int dlen; * Pick out the address components, two at a time. */ a1 = ippr_ftp_atoi(&s); - if (!s) + if (s == NULL) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_pasv:ippr_ftp_atoi(1) failed\n"); +#endif return 0; + } a2 = ippr_ftp_atoi(&s); - if (!s) + if (s == NULL) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_pasv:ippr_ftp_atoi(2) failed\n"); +#endif return 0; + } /* * check that IP address in the PORT/PASV reply is the same as the @@ -418,12 +489,20 @@ int dlen; */ a1 <<= 16; a1 |= a2; - if (a1 != ntohl(nat->nat_oip.s_addr)) + if (a1 != ntohl(nat->nat_oip.s_addr)) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_pasv:a1 != nat->nat_oip\n"); +#endif return 0; + } a5 = ippr_ftp_atoi(&s); - if (!s) + if (s == NULL) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_pasv:ippr_ftp_atoi(3) failed\n"); +#endif return 0; + } if (*s == ')') s++; @@ -437,8 +516,12 @@ int dlen; if ((*s == '\r') && (*(s + 1) == '\n')) { s += 2; a6 = a5 & 0xff; - } else + } else { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_pasv:missing cr-lf\n"); +#endif return 0; + } a5 >>= 8; /* * Calculate new address parts for 227 reply @@ -580,9 +663,9 @@ int dlen; return 0; if (ftp->ftp_passok == FTPXY_GO) { if (!strncmp(rptr, "227 ", 4)) - inc = ippr_ftp_pasv(fin, ip, nat, f, dlen); + inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen); } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) { - inc = ippr_ftp_pasv(fin, ip, nat, f, dlen); + inc = ippr_ftp_pasv(fin, ip, nat, ftp, dlen); } else if (*rptr == '5' || *rptr == '4') ftp->ftp_passok = FTPXY_INIT; else if (ftp->ftp_incok) { @@ -608,6 +691,7 @@ int dlen; } } ftp->ftp_incok = 0; + while ((*rptr++ != '\n') && (rptr < wptr)) ; f->ftps_rptr = rptr; @@ -619,100 +703,150 @@ int dlen; * Look to see if the buffer starts with something which we recognise as * being the correct syntax for the FTP protocol. */ -int ippr_ftp_client_valid(buf, len) +int ippr_ftp_client_valid(ftps, buf, len) +ftpside_t *ftps; char *buf; size_t len; { register char *s, c; register size_t i = len; + char cmd[5]; - if (i < 5) + if (i < 5) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_client_valid:i(%d) < 5\n", i); +#endif return 2; + } s = buf; c = *s++; i--; if (isalpha(c)) { + cmd[0] = toupper(c); c = *s++; i--; if (isalpha(c)) { + cmd[1] = toupper(c); c = *s++; i--; if (isalpha(c)) { + cmd[2] = toupper(c); c = *s++; i--; if (isalpha(c)) { + cmd[3] = toupper(c); c = *s++; i--; if ((c != ' ') && (c != '\r')) - return 1; + goto bad_client_command; } else if ((c != ' ') && (c != '\r')) - return 1; + goto bad_client_command; } else - return 1; + goto bad_client_command; } else - return 1; - } else + goto bad_client_command; + } else { +bad_client_command: +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_client_valid:bad cmd:len %d i %d c 0x%x\n", + i, len, c); +#endif return 1; + } + for (; i; i--) { c = *s++; - if (c == '\n') + if (c == '\n') { + cmd[4] = '\0'; + if (!strcmp(cmd, "PASV")) + ftps->ftps_cmds = FTPXY_C_PASV; + else + ftps->ftps_cmds = 0; return 0; + } } +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_client_valid:junk after cmd[%s]\n", buf); +#endif return 2; } -int ippr_ftp_server_valid(buf, len) +int ippr_ftp_server_valid(ftps, buf, len) +ftpside_t *ftps; char *buf; size_t len; { register char *s, c; register size_t i = len; + int cmd; if (i < 5) return 2; s = buf; c = *s++; + cmd = 0; i--; if (isdigit(c)) { + cmd = (c - '0') * 100; c = *s++; i--; if (isdigit(c)) { + cmd += (c - '0') * 10; c = *s++; i--; if (isdigit(c)) { + cmd += (c - '0'); c = *s++; i--; if ((c != '-') && (c != ' ')) - return 1; + goto bad_server_command; } else - return 1; + goto bad_server_command; } else - return 1; - } else + goto bad_server_command; + } else { +bad_server_command: +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_server_valid:bad cmd:len %d i %d c 0x%x\n", + i, len, c); +#endif return 1; + } + for (; i; i--) { c = *s++; - if (c == '\n') + if (c == '\n') { + ftps->ftps_cmds = cmd; return 0; + } } +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, "ippr_ftp_server_valid:junk after cmd[%s]\n", buf); +#endif return 2; } -int ippr_ftp_valid(side, buf, len) +int ippr_ftp_valid(ftp, side, buf, len) +ftpinfo_t *ftp; int side; char *buf; size_t len; { + ftpside_t *ftps; int ret; + ftps = &ftp->ftp_side[side]; + if (side == 0) - ret = ippr_ftp_client_valid(buf, len); + ret = ippr_ftp_client_valid(ftps, buf, len); else - ret = ippr_ftp_server_valid(buf, len); + ret = ippr_ftp_server_valid(ftps, buf, len); return ret; } @@ -814,9 +948,10 @@ int rv; #endif ok = 0; - if (t->ftps_seq[0] == 0) - t->ftps_seq[0] = thack, ok = 1; - else { + if (t->ftps_seq[0] == 0) { + t->ftps_seq[0] = thack; + ok = 1; + } else { if (ackoff == 0) { if (t->ftps_seq[0] == thack) ok = 1; @@ -845,20 +980,24 @@ int rv; #endif if (!mlen) { - if (t->ftps_seq[0] + ackoff != thack) + if (t->ftps_seq[0] + ackoff != thack) { +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_process:seq[0](%x) + ackoff(%x) != thack(%x)\n", + t->ftps_seq[0], ackoff, thack); +#endif return APR_ERR(1); + } #if PROXY_DEBUG printf("f:seq[0] %x seq[1] %x\n", f->ftps_seq[0], f->ftps_seq[1]); #endif if (tcp->th_flags & TH_FIN) { - if (thseq + seqoff == f->ftps_seq[0] + 1 || - f->ftps_seq[0] + seqoff + 1 == thseq || - thseq + seqoff == f->ftps_seq[0] || - thseq == f->ftps_seq[0] + seqoff) - ; - else { -#if PROXY_DEBUG + if (thseq == f->ftps_seq[1]) { + f->ftps_seq[0] = f->ftps_seq[1] - seqoff; + f->ftps_seq[1] = thseq + 1 - seqoff; + } else { +#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL)) printf("FIN: thseq %x seqoff %d ftps_seq %x\n", thseq, seqoff, f->ftps_seq[0]); #endif @@ -870,17 +1009,19 @@ int rv; } ok = 0; - if (thseq == f->ftps_seq[0] || thseq == f->ftps_seq[1]) + if ((thseq == f->ftps_seq[0]) || (thseq == f->ftps_seq[1])) { ok = 1; /* * Retransmitted data packet. */ - else if (thseq + mlen == f->ftps_seq[0] || - thseq + mlen == f->ftps_seq[1]) + } else if ((thseq + mlen == f->ftps_seq[0]) || + (thseq + mlen == f->ftps_seq[1])) { ok = 1; + } + if (ok == 0) { inc = thseq - f->ftps_seq[0]; -#if PROXY_DEBUG +#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL)) printf("inc %d sel %d rv %d\n", inc, sel, rv); printf("th_seq %x ftps_seq %x/%x\n", thseq, f->ftps_seq[0], f->ftps_seq[1]); @@ -917,10 +1058,12 @@ int rv; wptr += len; f->ftps_wptr = wptr; if (f->ftps_junk == 2) - f->ftps_junk = ippr_ftp_valid(rv, rptr, wptr - rptr); + f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, + wptr - rptr); while ((f->ftps_junk == 0) && (wptr > rptr)) { - f->ftps_junk = ippr_ftp_valid(rv, rptr, wptr - rptr); + f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, + wptr - rptr); if (f->ftps_junk == 0) { f->ftps_cmds++; len = wptr - rptr; @@ -942,6 +1085,10 @@ int rv; */ if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) { /* f->ftps_seq[1] += inc; */ +#if !defined(_KERNEL) && !defined(KERNEL) + fprintf(stdout, + "ippr_ftp_process:cmds == 0 junk == 1\n"); +#endif return APR_ERR(2); } @@ -985,18 +1132,17 @@ int rv; /* f->ftps_seq[1] += inc; */ if (tcp->th_flags & TH_FIN) f->ftps_seq[1]++; -#ifndef _KERNEL - mlen = mbuflen(m); -#else -# if SOLARIS - mlen = msgdsize(m); -# else - mlen = mbufchainlen(m); -# endif -#endif - off = fin->fin_hlen + (tcp->th_off << 2); - mlen -= off; #if PROXY_DEBUG +# ifndef _KERNEL + mlen = mbuflen(m); +# else +# if SOLARIS + mlen = msgdsize(m); +# else + mlen = mbufchainlen(m); +# endif +# endif + mlen -= off; printf("ftps_seq[1] = %x inc %d len %d\n", f->ftps_seq[1], inc, mlen); #endif diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index 4e8488bbc575..7edba023627a 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -105,6 +105,9 @@ # include # include # include +# ifdef USE_INET6 +# include +# endif # include # ifndef _KERNEL # include @@ -217,6 +220,26 @@ mb_t *m; break; } } +#ifdef USE_INET6 + else if (p == IPPROTO_ICMPV6) { + struct icmp6_hdr *icmp; + + icmp = (struct icmp6_hdr *)fin->fin_dp; + + /* + * For ICMPV6, if the packet is an error packet, also + * include the information about the packet which + * caused the error. + */ + if (icmp->icmp6_type < 128) { + hlen += MIN(sizeof(struct icmp6_hdr) + 8, + fin->fin_dlen); + } else { + hlen += MIN(sizeof(struct icmp6_hdr), + fin->fin_dlen); + } + } +#endif } /* * Get the interface number and name to which this packet is @@ -340,10 +363,10 @@ int *types, cnt; ipl->ipl_dsize = len; # ifdef _KERNEL # if SOLARIS || defined(sun) - uniqtime((struct timeval *)&ipl->ipl_sec); + uniqtime(&ipl->ipl_tv); # else # if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) - microtime((struct timeval *)&ipl->ipl_sec); + microtime(&ipl->ipl_tv); # endif # endif # else diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index ef109b1b8608..90fd20da611c 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -10,7 +10,7 @@ #define _KERNEL #endif -#ifdef __sgi +#if defined(__sgi) && (IRIX > 602) # include #endif #include @@ -150,6 +150,7 @@ static int nat_match __P((fr_info_t *, ipnat_t *, ip_t *)); static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr, struct in_addr)); static void nat_hostmapdel __P((struct hostmap *)); +static void nat_mssclamp __P((tcphdr_t *, u_32_t, fr_info_t *, u_short *)); int nat_init() @@ -458,8 +459,9 @@ int mode; /* * For add/delete, look to see if the NAT entry is already present */ - if (getlock == 1) + if (getlock == 1) { WRITE_ENTER(&ipf_nat); + } if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) { nat = &natd; nat->in_flags &= IPN_USERFLAGS; @@ -728,8 +730,9 @@ int mode; error = EINVAL; break; } - if (getlock == 1) + if (getlock == 1) { RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ + } done: if (nt) KFREE(nt); @@ -1467,6 +1470,7 @@ int direction; nat->nat_p = fin->fin_p; nat->nat_bytes = 0; nat->nat_pkts = 0; + nat->nat_mssclamp = np->in_mssclamp; nat->nat_fr = fin->fin_fr; if (nat->nat_fr != NULL) { ATOMIC_INC32(nat->nat_fr->fr_ref); @@ -2519,6 +2523,16 @@ fr_info_t *fin; */ if (nat->nat_age == fr_tcpclosed) nat->nat_age = fr_tcplastack; + + /* + * Do a MSS CLAMPING on a SYN packet, + * only deal IPv4 for now. + */ + if (nat->nat_mssclamp && + (tcp->th_flags & TH_SYN) != 0) + nat_mssclamp(tcp, nat->nat_mssclamp, + fin, csump); + MUTEX_EXIT(&nat->nat_lock); } else if (fin->fin_p == IPPROTO_UDP) { udphdr_t *udp = (udphdr_t *)tcp; @@ -2730,6 +2744,15 @@ fr_info_t *fin; */ if (nat->nat_age == fr_tcpclosed) nat->nat_age = fr_tcplastack; + /* + * Do a MSS CLAMPING on a SYN packet, + * only deal IPv4 for now. + */ + if (nat->nat_mssclamp && + (tcp->th_flags & TH_SYN) != 0) + nat_mssclamp(tcp, nat->nat_mssclamp, + fin, csump); + MUTEX_EXIT(&nat->nat_lock); } else if (fin->fin_p == IPPROTO_UDP) { udphdr_t *udp = (udphdr_t *)tcp; @@ -2929,3 +2952,60 @@ void *ifp; return; } #endif + + +/* + * Check for MSS option and clamp it if necessary. + */ +static void nat_mssclamp(tcp, maxmss, fin, csump) +tcphdr_t *tcp; +u_32_t maxmss; +fr_info_t *fin; +u_short *csump; +{ + u_char *cp, *ep, opt; + int hlen, advance; + u_32_t mss, sumd; + u_short v; + + hlen = tcp->th_off << 2; + if (hlen > sizeof(*tcp)) { + cp = (u_char *)tcp + sizeof(*tcp); + ep = (u_char *)tcp + hlen; + + while (cp < ep) { + opt = cp[0]; + if (opt == TCPOPT_EOL) + break; + else if (opt == TCPOPT_NOP) { + cp++; + continue; + } + + if (&cp[1] >= ep) + break; + advance = cp[1]; + if (&cp[advance] >= ep) + break; + switch (opt) { + case TCPOPT_MAXSEG: + if (advance != 4) + break; + bcopy(&cp[2], &v, sizeof(v)); + mss = ntohs(v); + if (mss > maxmss) { + v = htons(maxmss); + bcopy(&v, &cp[2], sizeof(v)); + CALC_SUMD(mss, maxmss, sumd); + fix_outcksum(fin, csump, sumd); + } + break; + default: + /* ignore unknown options */ + break; + } + + cp += advance; + } + } +} diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index 2462e61f096e..6b3fe6623b98 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -85,6 +85,7 @@ typedef struct nat { u_short nat_use; u_char nat_tcpstate[2]; u_char nat_p; /* protocol for NAT */ + u_32_t nat_mssclamp; /* if != zero clamp MSS to this */ struct ipnat *nat_ptr; /* pointer back to the rule */ struct hostmap *nat_hm; struct nat *nat_next; @@ -114,6 +115,7 @@ typedef struct ipnat { u_short in_pnext; u_short in_ippip; /* IP #'s per IP# */ u_32_t in_flags; /* From here to in_dport must be reflected */ + u_32_t in_mssclamp; /* if != zero clamp MSS to this */ u_short in_spare; u_short in_ppip; /* ports per IP */ u_short in_port[2]; /* correctly in IPN_CMPSIZ */ diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index d612adf32115..da90a9d607d9 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -8,7 +8,7 @@ # define _KERNEL #endif -#ifdef __sgi +#if defined(__sgi) && (IRIX > 602) # include #endif #include @@ -312,7 +312,7 @@ nat_t *nat; sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, tcp); #endif if (sum != tcp->th_sum) { -#if PROXY_DEBUG +#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL)) printf("proxy tcp checksum failure\n"); #endif frstats[fin->fin_out].fr_tcpbad++; @@ -320,8 +320,8 @@ nat_t *nat; } /* - * Don't both the proxy with these...or in fact, should - * we free up proxy stuff when seen? + * Don't bother the proxy with these...or in fact, + * should we free up proxy stuff when seen? */ if ((tcp->th_flags & TH_RST) != 0) return 0; @@ -339,13 +339,13 @@ nat_t *nat; rv = APR_EXIT(err); if (rv == 1) { -#if PROXY_DEBUG +#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL)) printf("proxy says bad packet received\n"); #endif return -1; } if (rv == 2) { -#if PROXY_DEBUG +#if PROXY_DEBUG || (!defined(_KERNEL) && !defined(KERNEL)) printf("proxy says free app proxy data\n"); #endif appr_free(apr); @@ -421,7 +421,7 @@ ap_session_t *aps; apr = aps->aps_apr; if ((apr != NULL) && (apr->apr_del != NULL)) (*apr->apr_del)(aps); - + if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) KFREES(aps->aps_data, aps->aps_psiz); KFREE(aps); @@ -465,7 +465,7 @@ int inc; sel, !sel, seq1, aps->aps_seqmin[!sel]); #endif sel = aps->aps_sel[out] = !sel; -} + } if (aps->aps_seqoff[sel]) { seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel]; @@ -500,7 +500,7 @@ int inc; sel, !sel, seq1, aps->aps_ackmin[!sel]); #endif sel = aps->aps_sel[1 - out] = !sel; -} + } if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) { seq2 = aps->aps_ackoff[sel]; @@ -519,7 +519,7 @@ int inc; sel, !sel, seq1, aps->aps_ackmin[!sel]); #endif sel = aps->aps_sel[out] = !sel; -} + } if (aps->aps_ackoff[sel]) { seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel]; @@ -554,7 +554,7 @@ int inc; sel, !sel, seq1, aps->aps_seqmin[!sel]); #endif sel = aps->aps_sel[1 - out] = !sel; -} + } if (aps->aps_seqoff[sel] != 0) { #if PROXY_DEBUG diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.h b/sys/contrib/ipfilter/netinet/ip_proxy.h index d293f17f7693..8488188936ff 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.h +++ b/sys/contrib/ipfilter/netinet/ip_proxy.h @@ -100,6 +100,7 @@ typedef struct ftpside { u_32_t ftps_len; int ftps_junk; int ftps_cmds; + int ftps_cmd; char ftps_buf[FTP_BUFSZ]; } ftpside_t; diff --git a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c index 1d6bc71893d6..6715b07e6d53 100644 --- a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c @@ -1,5 +1,5 @@ /* - * $Id: ip_rcmd_pxy.c,v 1.4.2.5 2001/10/30 16:38:14 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.4.2.6 2002/10/01 15:24:59 darrenr Exp $ */ /* * Simple RCMD transparent proxy for in-kernel use. For use with the NAT @@ -144,6 +144,7 @@ nat_t *nat; tcp2->th_sport = htons(sp); tcp2->th_dport = 0; /* XXX - don't specify remote port */ tcp2->th_off = 5; + tcp2->th_flags = TH_SYN; fi.fin_data[1] = 0; fi.fin_dp = (char *)tcp2; fi.fin_dlen = sizeof(*tcp2); diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index b649058fc9b1..ef4d361adc02 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. */ -#ifdef __sgi +#if defined(__sgi) && (IRIX > 602) # include #endif #include @@ -119,8 +119,8 @@ static frentry_t *fr_checkicmp6matchingstate __P((ip6_t *, fr_info_t *)); static int fr_matchsrcdst __P((ipstate_t *, union i6addr, union i6addr, fr_info_t *, tcphdr_t *)); static frentry_t *fr_checkicmpmatchingstate __P((ip_t *, fr_info_t *)); -static int fr_matchicmpqueryreply __P((int, ipstate_t *, icmphdr_t *)); -static int fr_state_flush __P((int)); +static int fr_matchicmpqueryreply __P((int, ipstate_t *, icmphdr_t *, int)); +static int fr_state_flush __P((int, int)); static ips_stat_t *fr_statetstats __P((void)); static void fr_delstate __P((ipstate_t *)); static int fr_state_remove __P((caddr_t)); @@ -205,8 +205,8 @@ static ips_stat_t *fr_statetstats() * starting at > 4 days idle and working back in successive half- * days to at most 12 hours old. */ -static int fr_state_flush(which) -int which; +static int fr_state_flush(which, proto) +int which, proto; { ipstate_t *is, **isp; #if defined(_KERNEL) && !SOLARIS @@ -218,6 +218,9 @@ int which; for (isp = &ips_list; (is = *isp); ) { delete = 0; + if ((proto != 0) && (is->is_v != proto)) + continue; + switch (which) { case 0 : @@ -339,12 +342,26 @@ int mode; break; if (arg == 0 || arg == 1) { WRITE_ENTER(&ipf_state); - ret = fr_state_flush(arg); + ret = fr_state_flush(arg, 4); RWLOCK_EXIT(&ipf_state); error = IWCOPY((caddr_t)&ret, data, sizeof(ret)); } else error = EINVAL; break; +#ifdef USE_INET6 + case SIOCIPFL6 : + error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); + if (error) + break; + if (arg == 0 || arg == 1) { + WRITE_ENTER(&ipf_state); + ret = fr_state_flush(arg, 6); + RWLOCK_EXIT(&ipf_state); + error = IWCOPY((caddr_t)&ret, data, sizeof(ret)); + } else + error = EINVAL; + break; +#endif #ifdef IPFILTER_LOG case SIOCIPFFB : if (!(mode & FWRITE)) @@ -1120,7 +1137,7 @@ tcphdr_t *tcp; return 1; } -static int fr_matchicmpqueryreply(v, is, icmp) +static int fr_matchicmpqueryreply(v, is, icmp, rev) int v; ipstate_t *is; icmphdr_t *icmp; @@ -1130,8 +1147,8 @@ icmphdr_t *icmp; * If we matched its type on the way in, then when going out * it will still be the same type. */ - if (((icmp->icmp_type == is->is_type) || - (icmpreplytype4[is->is_type] == icmp->icmp_type))) { + if ((!rev && (icmp->icmp_type == is->is_type)) || + (rev && (icmpreplytype4[is->is_type] == icmp->icmp_type))) { if (icmp->icmp_type != ICMP_ECHOREPLY) return 1; if ((icmp->icmp_id == is->is_icmp.ics_id) && @@ -1141,8 +1158,8 @@ icmphdr_t *icmp; } #ifdef USE_INET6 else if (is->is_v == 6) { - if (((icmp->icmp_type == is->is_type) || - (icmpreplytype6[is->is_type] == icmp->icmp_type))) { + if ((!rev && (icmp->icmp_type == is->is_type)) || + (rev && (icmpreplytype6[is->is_type] == icmp->icmp_type))) { if (icmp->icmp_type != ICMP6_ECHO_REPLY) return 1; if ((icmp->icmp_id == is->is_icmp.ics_id) && @@ -1280,7 +1297,7 @@ fr_info_t *fin; for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) if ((is->is_p == pr) && (is->is_v == 4) && fr_matchsrcdst(is, src, dst, &ofin, NULL) && - fr_matchicmpqueryreply(is->is_v, is, icmp)) { + fr_matchicmpqueryreply(is->is_v, is, icmp, fin->fin_rev)) { ips_stats.iss_hits++; is->is_pkts++; is->is_bytes += ip->ip_len; @@ -1462,7 +1479,7 @@ fr_info_t *fin; for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext) if ((is->is_p == pr) && (is->is_v == v) && fr_matchsrcdst(is, src, dst, fin, NULL) && - fr_matchicmpqueryreply(v, is, ic)) { + fr_matchicmpqueryreply(v, is, ic, fin->fin_rev)) { rev = fin->fin_rev; if (is->is_frage[rev] != 0) is->is_age = is->is_frage[rev]; @@ -1517,7 +1534,7 @@ fr_info_t *fin; for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext) if ((is->is_p == pr) && (is->is_v == v) && fr_matchsrcdst(is, src, dst, fin, NULL) && - fr_matchicmpqueryreply(v, is, ic)) { + fr_matchicmpqueryreply(v, is, ic, fin->fin_rev)) { rev = fin->fin_rev; if (is->is_frage[rev] != 0) is->is_age = is->is_frage[rev]; @@ -1752,7 +1769,7 @@ void fr_timeoutstate() } else isp = &is->is_next; if (fr_state_doflush) { - (void) fr_state_flush(2); + (void) fr_state_flush(2, 0); fr_state_doflush = 0; } RWLOCK_EXIT(&ipf_state); diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index d1d69a5ee26f..d61898614b58 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -10,6 +10,6 @@ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.29" +#define IPL_VERSION "IP Filter: v3.4.31" #endif