diff options
Diffstat (limited to 'contrib/ipfilter/ip_scan.c')
-rw-r--r-- | contrib/ipfilter/ip_scan.c | 594 |
1 files changed, 0 insertions, 594 deletions
diff --git a/contrib/ipfilter/ip_scan.c b/contrib/ipfilter/ip_scan.c deleted file mode 100644 index b36fccf..0000000 --- a/contrib/ipfilter/ip_scan.c +++ /dev/null @@ -1,594 +0,0 @@ -/* $FreeBSD$ */ - -/* - * Copyright (C) 1995-2001 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(KERNEL) || defined(_KERNEL) -# undef KERNEL -# undef _KERNEL -# define KERNEL 1 -# define _KERNEL 1 -#endif -#include <sys/param.h> -#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) -# include <sys/kern_svcs.h> -#endif -#include <sys/types.h> -#include <sys/time.h> -#include <sys/errno.h> -#if !defined(_KERNEL) -# include <stdlib.h> -# include <string.h> -# define _KERNEL -# ifdef __OpenBSD__ -struct file; -# endif -# include <sys/uio.h> -# undef _KERNEL -#else -# include <sys/systm.h> -# if !defined(__svr4__) && !defined(__SVR4) -# include <sys/mbuf.h> -# endif -#endif -#include <sys/socket.h> -#if !defined(__hpux) && !defined(__osf__) && !defined(linux) -# include <sys/ioccom.h> -#endif -#ifdef __FreeBSD__ -# include <sys/filio.h> -# include <sys/malloc.h> -#else -# include <sys/ioctl.h> -#endif - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> - -#include <net/if.h> - - -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_state.h" -#include "netinet/ip_scan.h" -/* END OF INCLUDES */ - -#if !defined(lint) -static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)Id: ip_scan.c,v 2.40.2.2 2005/01/18 10:13:16 darrenr Exp"; -#endif - -#ifdef IPFILTER_SCAN /* endif at bottom of file */ - - -ipscan_t *ipsc_list = NULL, - *ipsc_tail = NULL; -ipscanstat_t ipsc_stat; -# ifdef USE_MUTEXES -ipfrwlock_t ipsc_rwlock; -# endif - -# ifndef isalpha -# define isalpha(x) (((x) >= 'A' && 'Z' >= (x)) || \ - ((x) >= 'a' && 'z' >= (x))) -# endif - - -int ipsc_add __P((caddr_t)); -int ipsc_delete __P((caddr_t)); -struct ipscan *ipsc_lookup __P((char *)); -int ipsc_matchstr __P((sinfo_t *, char *, int)); -int ipsc_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *)); -int ipsc_match __P((ipstate_t *)); - - - -int ipsc_init() -{ - RWLOCK_INIT(&ipsc_rwlock, "ip scan rwlock"); - return 0; -} - - -void fr_scanunload() -{ - RW_DESTROY(&ipsc_rwlock); -} - - -int ipsc_add(data) -caddr_t data; -{ - ipscan_t *i, *isc; - int err; - - KMALLOC(isc, ipscan_t *); - if (!isc) - return ENOMEM; - - err = copyinptr(data, isc, sizeof(*isc)); - if (err) - return err; - - WRITE_ENTER(&ipsc_rwlock); - - i = ipsc_lookup(isc->ipsc_tag); - if (i) { - RWLOCK_EXIT(&ipsc_rwlock); - KFREE(isc); - return EEXIST; - } - - if (ipsc_tail) { - ipsc_tail->ipsc_next = isc; - isc->ipsc_pnext = &ipsc_tail->ipsc_next; - ipsc_tail = isc; - } else { - ipsc_list = isc; - ipsc_tail = isc; - isc->ipsc_pnext = &ipsc_list; - } - isc->ipsc_next = NULL; - - isc->ipsc_hits = 0; - isc->ipsc_fref = 0; - isc->ipsc_sref = 0; - isc->ipsc_active = 0; - - ipsc_stat.iscs_entries++; - RWLOCK_EXIT(&ipsc_rwlock); - return 0; -} - - -int ipsc_delete(data) -caddr_t data; -{ - ipscan_t isc, *i; - int err; - - err = copyinptr(data, &isc, sizeof(isc)); - if (err) - return err; - - WRITE_ENTER(&ipsc_rwlock); - - i = ipsc_lookup(isc.ipsc_tag); - if (i == NULL) - err = ENOENT; - else { - if (i->ipsc_fref) { - RWLOCK_EXIT(&ipsc_rwlock); - return EBUSY; - } - - *i->ipsc_pnext = i->ipsc_next; - if (i->ipsc_next) - i->ipsc_next->ipsc_pnext = i->ipsc_pnext; - else { - if (i->ipsc_pnext == &ipsc_list) - ipsc_tail = NULL; - else - ipsc_tail = *(*i->ipsc_pnext)->ipsc_pnext; - } - - ipsc_stat.iscs_entries--; - KFREE(i); - } - RWLOCK_EXIT(&ipsc_rwlock); - return err; -} - - -struct ipscan *ipsc_lookup(tag) -char *tag; -{ - ipscan_t *i; - - for (i = ipsc_list; i; i = i->ipsc_next) - if (!strcmp(i->ipsc_tag, tag)) - return i; - return NULL; -} - - -int ipsc_attachfr(fr) -struct frentry *fr; -{ - ipscan_t *i; - - if (fr->fr_isctag[0]) { - READ_ENTER(&ipsc_rwlock); - i = ipsc_lookup(fr->fr_isctag); - if (i != NULL) { - ATOMIC_INC32(i->ipsc_fref); - } - RWLOCK_EXIT(&ipsc_rwlock); - if (i == NULL) - return ENOENT; - fr->fr_isc = i; - } - return 0; -} - - -int ipsc_attachis(is) -struct ipstate *is; -{ - frentry_t *fr; - ipscan_t *i; - - READ_ENTER(&ipsc_rwlock); - fr = is->is_rule; - if (fr) { - i = fr->fr_isc; - if (!i || (i != (ipscan_t *)-1)) { - is->is_isc = i; - if (i) { - ATOMIC_INC32(i->ipsc_sref); - if (i->ipsc_clen) - is->is_flags |= IS_SC_CLIENT; - else - is->is_flags |= IS_SC_MATCHC; - if (i->ipsc_slen) - is->is_flags |= IS_SC_SERVER; - else - is->is_flags |= IS_SC_MATCHS; - } else - is->is_flags |= (IS_SC_CLIENT|IS_SC_SERVER); - } - } - RWLOCK_EXIT(&ipsc_rwlock); - return 0; -} - - -int ipsc_detachfr(fr) -struct frentry *fr; -{ - ipscan_t *i; - - i = fr->fr_isc; - if (i != NULL) { - ATOMIC_DEC32(i->ipsc_fref); - } - return 0; -} - - -int ipsc_detachis(is) -struct ipstate *is; -{ - ipscan_t *i; - - READ_ENTER(&ipsc_rwlock); - if ((i = is->is_isc) && (i != (ipscan_t *)-1)) { - ATOMIC_DEC32(i->ipsc_sref); - is->is_isc = NULL; - is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER); - } - RWLOCK_EXIT(&ipsc_rwlock); - return 0; -} - - -/* - * 'string' compare for scanning - */ -int ipsc_matchstr(sp, str, n) -sinfo_t *sp; -char *str; -int n; -{ - char *s, *t, *up; - int i = n; - - if (i > sp->s_len) - i = sp->s_len; - up = str; - - for (s = sp->s_txt, t = sp->s_msk; i; i--, s++, t++, up++) - switch ((int)*t) - { - case '.' : - if (*s != *up) - return 1; - break; - case '?' : - if (!ISALPHA(*up) || ((*s & 0x5f) != (*up & 0x5f))) - return 1; - break; - case '*' : - break; - } - return 0; -} - - -/* - * Returns 3 if both server and client match, 2 if just server, - * 1 if just client - */ -int ipsc_matchisc(isc, is, cl, sl, maxm) -ipscan_t *isc; -ipstate_t *is; -int cl, sl, maxm[2]; -{ - int i, j, k, n, ret = 0, flags; - - flags = is->is_flags; - - /* - * If we've already matched more than what is on offer, then - * assume we have a better match already and forget this one. - */ - if (maxm != NULL) { - if (isc->ipsc_clen < maxm[0]) - return 0; - if (isc->ipsc_slen < maxm[1]) - return 0; - j = maxm[0]; - k = maxm[1]; - } else { - j = 0; - k = 0; - } - - if (!isc->ipsc_clen) - ret = 1; - else if (((flags & (IS_SC_MATCHC|IS_SC_CLIENT)) == IS_SC_CLIENT) && - cl && isc->ipsc_clen) { - i = 0; - n = MIN(cl, isc->ipsc_clen); - if ((n > 0) && (!maxm || (n >= maxm[1]))) { - if (!ipsc_matchstr(&isc->ipsc_cl, is->is_sbuf[0], n)) { - i++; - ret |= 1; - if (n > j) - j = n; - } - } - } - - if (!isc->ipsc_slen) - ret |= 2; - else if (((flags & (IS_SC_MATCHS|IS_SC_SERVER)) == IS_SC_SERVER) && - sl && isc->ipsc_slen) { - i = 0; - n = MIN(cl, isc->ipsc_slen); - if ((n > 0) && (!maxm || (n >= maxm[1]))) { - if (!ipsc_matchstr(&isc->ipsc_sl, is->is_sbuf[1], n)) { - i++; - ret |= 2; - if (n > k) - k = n; - } - } - } - - if (maxm && (ret == 3)) { - maxm[0] = j; - maxm[1] = k; - } - return ret; -} - - -int ipsc_match(is) -ipstate_t *is; -{ - int i, j, k, n, cl, sl, maxm[2]; - ipscan_t *isc, *lm; - tcpdata_t *t; - - for (cl = 0, n = is->is_smsk[0]; n & 1; n >>= 1) - cl++; - for (sl = 0, n = is->is_smsk[1]; n & 1; n >>= 1) - sl++; - - j = 0; - isc = is->is_isc; - if (isc != NULL) { - /* - * Known object to scan for. - */ - i = ipsc_matchisc(isc, is, cl, sl, NULL); - if (i & 1) { - is->is_flags |= IS_SC_MATCHC; - is->is_flags &= ~IS_SC_CLIENT; - } else if (cl >= isc->ipsc_clen) - is->is_flags &= ~IS_SC_CLIENT; - if (i & 2) { - is->is_flags |= IS_SC_MATCHS; - is->is_flags &= ~IS_SC_SERVER; - } else if (sl >= isc->ipsc_slen) - is->is_flags &= ~IS_SC_SERVER; - } else { - i = 0; - lm = NULL; - maxm[0] = 0; - maxm[1] = 0; - for (k = 0, isc = ipsc_list; isc; isc = isc->ipsc_next) { - i = ipsc_matchisc(isc, is, cl, sl, maxm); - if (i) { - /* - * We only want to remember the best match - * and the number of times we get a best - * match. - */ - if ((j == 3) && (i < 3)) - continue; - if ((i == 3) && (j != 3)) - k = 1; - else - k++; - j = i; - lm = isc; - } - } - if (k == 1) - isc = lm; - - /* - * No matches or partial matches, so reset the respective - * search flag. - */ - if (!(j & 1)) - is->is_flags &= ~IS_SC_CLIENT; - - if (!(j & 2)) - is->is_flags &= ~IS_SC_SERVER; - - /* - * If we found the best match, then set flags appropriately. - */ - if ((j == 3) && (k == 1)) { - is->is_flags &= ~(IS_SC_SERVER|IS_SC_CLIENT); - is->is_flags |= (IS_SC_MATCHS|IS_SC_MATCHC); - } - } - - /* - * If the acknowledged side of a connection has moved past the data in - * which we are interested, then reset respective flag. - */ - t = &is->is_tcp.ts_data[0]; - if (t->td_end > is->is_s0[0] + 15) - is->is_flags &= ~IS_SC_CLIENT; - - t = &is->is_tcp.ts_data[1]; - if (t->td_end > is->is_s0[1] + 15) - is->is_flags &= ~IS_SC_SERVER; - - /* - * Matching complete ? - */ - j = ISC_A_NONE; - if ((is->is_flags & IS_SC_MATCHALL) == IS_SC_MATCHALL) { - j = isc->ipsc_action; - ipsc_stat.iscs_acted++; - } else if ((is->is_isc != NULL) && - ((is->is_flags & IS_SC_MATCHALL) != IS_SC_MATCHALL) && - !(is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER))) { - /* - * Matching failed... - */ - j = isc->ipsc_else; - ipsc_stat.iscs_else++; - } - - switch (j) - { - case ISC_A_CLOSE : - /* - * If as a result of a successful match we are to - * close a connection, change the "keep state" info. - * to block packets and generate TCP RST's. - */ - is->is_pass &= ~FR_RETICMP; - is->is_pass |= FR_RETRST; - break; - default : - break; - } - - return i; -} - - -/* - * check if a packet matches what we're scanning for - */ -int ipsc_packet(fin, is) -fr_info_t *fin; -ipstate_t *is; -{ - int i, j, rv, dlen, off, thoff; - u_32_t seq, s0; - tcphdr_t *tcp; - - rv = !IP6_EQ(&fin->fin_fi.fi_src, &is->is_src); - tcp = fin->fin_dp; - seq = ntohl(tcp->th_seq); - - if (!is->is_s0[rv]) - return 1; - - /* - * check if this packet has more data that falls within the first - * 16 bytes sent in either direction. - */ - s0 = is->is_s0[rv]; - off = seq - s0; - if ((off > 15) || (off < 0)) - return 1; - thoff = TCP_OFF(tcp) << 2; - dlen = fin->fin_dlen - thoff; - if (dlen <= 0) - return 1; - if (dlen > 16) - dlen = 16; - if (off + dlen > 16) - dlen = 16 - off; - - j = 0xffff >> (16 - dlen); - i = (0xffff & j) << off; -#ifdef _KERNEL - COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_hlen + thoff, dlen, - (caddr_t)is->is_sbuf[rv] + off); -#endif - is->is_smsk[rv] |= i; - for (j = 0, i = is->is_smsk[rv]; i & 1; i >>= 1) - j++; - if (j == 0) - return 1; - - (void) ipsc_match(is); -#if 0 - /* - * There is the potential here for plain text passwords to get - * buffered and stored for some time... - */ - if (!(is->is_flags & IS_SC_CLIENT)) - bzero(is->is_sbuf[0], sizeof(is->is_sbuf[0])); - if (!(is->is_flags & IS_SC_SERVER)) - bzero(is->is_sbuf[1], sizeof(is->is_sbuf[1])); -#endif - return 0; -} - - -int fr_scan_ioctl(data, cmd, mode) -caddr_t data; -ioctlcmd_t cmd; -int mode; -{ - ipscanstat_t ipscs; - int err = 0; - - switch (cmd) - { - case SIOCADSCA : - err = ipsc_add(data); - break; - case SIOCRMSCA : - err = ipsc_delete(data); - break; - case SIOCGSCST : - bcopy((char *)&ipsc_stat, (char *)&ipscs, sizeof(ipscs)); - ipscs.iscs_list = ipsc_list; - BCOPYOUT(&ipscs, data, sizeof(ipscs)); - break; - default : - err = EINVAL; - break; - } - - return err; -} -#endif /* IPFILTER_SCAN */ |