| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- Index: iptables-1.3.8/extensions/.layer7-test
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ iptables-1.3.8/extensions/.layer7-test 2007-07-31 15:27:56.000000000 -0500
- @@ -0,0 +1,2 @@
- +#! /bin/sh
- +[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_layer7.h ] && echo layer7
- Index: iptables-1.3.8/extensions/ipt_layer7.h
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ iptables-1.3.8/extensions/ipt_layer7.h 2007-07-31 15:27:56.000000000 -0500
- @@ -0,0 +1,27 @@
- +/*
- + By Matthew Strait <[email protected]>, Dec 2003.
- + http://l7-filter.sf.net
- +
- + This program is free software; you can redistribute it and/or
- + modify it under the terms of the GNU General Public License
- + as published by the Free Software Foundation; either version
- + 2 of the License, or (at your option) any later version.
- + http://www.gnu.org/licenses/gpl.txt
- +*/
- +
- +#ifndef _IPT_LAYER7_H
- +#define _IPT_LAYER7_H
- +
- +#define MAX_PATTERN_LEN 8192
- +#define MAX_PROTOCOL_LEN 256
- +
- +typedef char *(*proc_ipt_search) (char *, char, char *);
- +
- +struct ipt_layer7_info {
- + char protocol[MAX_PROTOCOL_LEN];
- + char invert:1;
- + char pattern[MAX_PATTERN_LEN];
- + char pkt;
- +};
- +
- +#endif /* _IPT_LAYER7_H */
- Index: iptables-1.3.8/extensions/libipt_layer7.c
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ iptables-1.3.8/extensions/libipt_layer7.c 2007-07-31 15:27:56.000000000 -0500
- @@ -0,0 +1,358 @@
- +/*
- + Shared library add-on to iptables to add layer 7 matching support.
- +
- + By Matthew Strait <[email protected]>, Oct 2003.
- +
- + http://l7-filter.sf.net
- +
- + This program is free software; you can redistribute it and/or
- + modify it under the terms of the GNU General Public License
- + as published by the Free Software Foundation; either version
- + 2 of the License, or (at your option) any later version.
- + http://www.gnu.org/licenses/gpl.txt
- +
- + Based on libipt_string.c (C) 2000 Emmanuel Roger <[email protected]>
- +*/
- +
- +#define _GNU_SOURCE
- +#include <stdio.h>
- +#include <netdb.h>
- +#include <string.h>
- +#include <stdlib.h>
- +#include <getopt.h>
- +#include <ctype.h>
- +#include <dirent.h>
- +
- +#include <iptables.h>
- +#include "ipt_layer7.h"
- +
- +#define MAX_FN_LEN 256
- +
- +static char l7dir[MAX_FN_LEN] = "\0";
- +
- +/* Function which prints out usage message. */
- +static void help(void)
- +{
- + printf(
- + "LAYER7 match v%s options:\n"
- + "--l7dir <directory> : Look for patterns here instead of /etc/l7-protocols/\n"
- + " (--l7dir must be specified before --l7proto if used!)\n"
- + "--l7proto [!] <name> : Match the protocol defined in /etc/l7-protocols/name.pat\n"
- + "--l7pkt : Skip connection tracking and match individual packets\n",
- + IPTABLES_VERSION);
- + fputc('\n', stdout);
- +}
- +
- +static struct option opts[] = {
- + { .name = "l7proto", .has_arg = 1, .flag = 0, .val = '1' },
- + { .name = "l7dir", .has_arg = 1, .flag = 0, .val = '2' },
- + { .name = "l7pkt", .has_arg = 0, .flag = 0, .val = '3' },
- + { .name = 0 }
- +};
- +
- +/* reads filename, puts protocol info into layer7_protocol_info, number of protocols to numprotos */
- +int parse_protocol_file(char * filename, const unsigned char * protoname, struct ipt_layer7_info *info)
- +{
- + FILE * f;
- + char * line = NULL;
- + size_t len = 0;
- +
- + enum { protocol, pattern, done } datatype = protocol;
- +
- + f = fopen(filename, "r");
- +
- + if(!f)
- + return 0;
- +
- + while(getline(&line, &len, f) != -1)
- + {
- + if(strlen(line) < 2 || line[0] == '#')
- + continue;
- +
- + /* strip the pesky newline... */
- + if(line[strlen(line) - 1] == '\n')
- + line[strlen(line) - 1] = '\0';
- +
- + if(datatype == protocol)
- + {
- + if(strcmp(line, protoname))
- + exit_error(OTHER_PROBLEM,
- + "Protocol name (%s) doesn't match file name (%s). Bailing out\n",
- + protoname, filename);
- +
- + if(strlen(line) >= MAX_PROTOCOL_LEN)
- + exit_error(PARAMETER_PROBLEM,
- + "Protocol name in %s too long!", filename);
- + strncpy(info->protocol, line, MAX_PROTOCOL_LEN);
- +
- + datatype = pattern;
- + }
- + else if(datatype == pattern)
- + {
- + if(strlen(line) >= MAX_PATTERN_LEN)
- + exit_error(PARAMETER_PROBLEM, "Pattern in %s too long!", filename);
- + strncpy(info->pattern, line, MAX_PATTERN_LEN);
- +
- + datatype = done;
- + break;
- + }
- + else
- + exit_error(OTHER_PROBLEM, "Internal error");
- + }
- +
- + if(datatype != done)
- + exit_error(OTHER_PROBLEM, "Failed to get all needed data from %s", filename);
- +
- + if(line) free(line);
- + fclose(f);
- +
- + return 1;
- +
- +/*
- + fprintf(stderr, "protocol: %s\npattern: %s\n\n",
- + info->protocol,
- + info->pattern);
- +*/
- +}
- +
- +static int hex2dec(char c)
- +{
- + switch (c)
- + {
- + case '0' ... '9':
- + return c - '0';
- + case 'a' ... 'f':
- + return c - 'a' + 10;
- + case 'A' ... 'F':
- + return c - 'A' + 10;
- + default:
- + exit_error(OTHER_PROBLEM, "hex2dec: bad value!\n");
- + return 0;
- + }
- +}
- +
- +/* takes a string with \xHH escapes and returns one with the characters
- +they stand for */
- +static char * pre_process(char * s)
- +{
- + char * result = malloc(strlen(s) + 1);
- + int sindex = 0, rindex = 0;
- + while( sindex < strlen(s) )
- + {
- + if( sindex + 3 < strlen(s) &&
- + s[sindex] == '\\' && s[sindex+1] == 'x' &&
- + isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) )
- + {
- + /* carefully remember to call tolower here... */
- + result[rindex] = tolower( hex2dec(s[sindex + 2])*16 +
- + hex2dec(s[sindex + 3] ) );
- + sindex += 3; /* 4 total */
- + }
- + else
- + result[rindex] = tolower(s[sindex]);
- +
- + sindex++;
- + rindex++;
- + }
- + result[rindex] = '\0';
- +
- + return result;
- +}
- +
- +#define MAX_SUBDIRS 128
- +char ** readl7dir(char * dirname)
- +{
- + DIR * scratchdir;
- + struct dirent ** namelist;
- + char ** subdirs = malloc(MAX_SUBDIRS * sizeof(char *));
- +
- + int n, d = 1;
- + subdirs[0] = "";
- +
- + n = scandir(dirname, &namelist, 0, alphasort);
- +
- + if (n < 0)
- + {
- + perror("scandir");
- + exit_error(OTHER_PROBLEM, "Couldn't open %s\n", dirname);
- + }
- + else
- + {
- + while(n--)
- + {
- + char fulldirname[MAX_FN_LEN];
- +
- + snprintf(fulldirname, MAX_FN_LEN, "%s/%s", dirname, namelist[n]->d_name);
- +
- + if((scratchdir = opendir(fulldirname)) != NULL)
- + {
- + closedir(scratchdir);
- +
- + if(!strcmp(namelist[n]->d_name, ".") ||
- + !strcmp(namelist[n]->d_name, ".."))
- + /* do nothing */ ;
- + else
- + {
- + subdirs[d] = malloc(strlen(namelist[n]->d_name) + 1);
- + strcpy(subdirs[d], namelist[n]->d_name);
- + d++;
- + if(d >= MAX_SUBDIRS - 1)
- + {
- + fprintf(stderr,
- + "Too many subdirectories, skipping the rest!\n");
- + break;
- + }
- + }
- + }
- + free(namelist[n]);
- + }
- + free(namelist);
- + }
- +
- + subdirs[d] = NULL;
- +
- + return subdirs;
- +}
- +
- +static void
- +parse_layer7_protocol(const unsigned char *s, struct ipt_layer7_info *info)
- +{
- + char filename[MAX_FN_LEN];
- + char * dir = NULL;
- + char ** subdirs;
- + int n = 0, done = 0;
- +
- + if(strlen(l7dir) > 0)
- + dir = l7dir;
- + else
- + dir = "/etc/l7-protocols";
- +
- + subdirs = readl7dir(dir);
- +
- + while(subdirs[n] != NULL)
- + {
- + int c = snprintf(filename, MAX_FN_LEN, "%s/%s/%s.pat", dir, subdirs[n], s);
- +
- + //fprintf(stderr, "Trying to find pattern in %s ... ", filename);
- +
- + if(c > MAX_FN_LEN)
- + {
- + exit_error(OTHER_PROBLEM,
- + "Filename beginning with %s is too long!\n", filename);
- + }
- +
- + /* read in the pattern from the file */
- + if(parse_protocol_file(filename, s, info))
- + {
- + //fprintf(stderr, "found\n");
- + done = 1;
- + break;
- + }
- +
- + //fprintf(stderr, "not found\n");
- +
- + n++;
- + }
- +
- + if(!done)
- + exit_error(OTHER_PROBLEM,
- + "Couldn't find a pattern definition file for %s.\n", s);
- +
- + /* process \xHH escapes and tolower everything. (our regex lib has no
- + case insensitivity option.) */
- + strncpy(info->pattern, pre_process(info->pattern), MAX_PATTERN_LEN);
- +}
- +
- +/* Function which parses command options; returns true if it ate an option */
- +static int parse(int c, char **argv, int invert, unsigned int *flags,
- + const struct ipt_entry *entry, unsigned int *nfcache,
- + struct ipt_entry_match **match)
- +{
- + struct ipt_layer7_info *layer7info =
- + (struct ipt_layer7_info *)(*match)->data;
- +
- + switch (c) {
- + case '1':
- + check_inverse(optarg, &invert, &optind, 0);
- + parse_layer7_protocol(argv[optind-1], layer7info);
- + if (invert)
- + layer7info->invert = 1;
- + *flags = 1;
- + break;
- +
- + case '2':
- + /* not going to use this, but maybe we need to strip a ! anyway (?) */
- + check_inverse(optarg, &invert, &optind, 0);
- +
- + if(strlen(argv[optind-1]) >= MAX_FN_LEN)
- + exit_error(PARAMETER_PROBLEM, "directory name too long\n");
- +
- + strncpy(l7dir, argv[optind-1], MAX_FN_LEN);
- +
- + *flags = 1;
- + break;
- + case '3':
- + layer7info->pkt = 1;
- + break;
- +
- + default:
- + return 0;
- + }
- +
- + return 1;
- +}
- +
- +/* Final check; must have specified --pattern. */
- +static void final_check(unsigned int flags)
- +{
- + if (!flags)
- + exit_error(PARAMETER_PROBLEM,
- + "LAYER7 match: You must specify `--pattern'");
- +}
- +
- +static void print_protocol(char s[], int invert, int numeric)
- +{
- + fputs("l7proto ", stdout);
- + if (invert) fputc('!', stdout);
- + printf("%s ", s);
- +}
- +
- +/* Prints out the matchinfo. */
- +static void print(const struct ipt_ip *ip,
- + const struct ipt_entry_match *match,
- + int numeric)
- +{
- + printf("LAYER7 ");
- +
- + print_protocol(((struct ipt_layer7_info *)match->data)->protocol,
- + ((struct ipt_layer7_info *)match->data)->invert, numeric);
- +
- + if (((struct ipt_layer7_info *)match->data)->pkt)
- + printf("l7pkt ");
- +}
- +/* Saves the union ipt_matchinfo in parsable form to stdout. */
- +static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
- +{
- + const struct ipt_layer7_info *info =
- + (const struct ipt_layer7_info*) match->data;
- +
- + printf("--l7proto %s%s ", (info->invert) ? "! ": "", info->protocol);
- +}
- +
- +static struct iptables_match layer7 = {
- + .name = "layer7",
- + .version = IPTABLES_VERSION,
- + .size = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
- + .userspacesize = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
- + .help = &help,
- + .parse = &parse,
- + .final_check = &final_check,
- + .print = &print,
- + .save = &save,
- + .extra_opts = opts
- +};
- +
- +void _init(void)
- +{
- + register_match(&layer7);
- +}
- Index: iptables-1.3.8/extensions/libipt_layer7.man
- ===================================================================
- --- /dev/null 1970-01-01 00:00:00.000000000 +0000
- +++ iptables-1.3.8/extensions/libipt_layer7.man 2007-07-31 15:27:56.000000000 -0500
- @@ -0,0 +1,13 @@
- +This module matches packets based on the application layer data of
- +their connections. It uses regular expression matching to compare
- +the application layer data to regular expressions found it the layer7
- +configuration files. This is an experimental module which can be found at
- +http://l7-filter.sf.net. It takes two options.
- +.TP
- +.BI "--l7proto " "\fIprotocol\fP"
- +Match the specified protocol. The protocol name must match a file
- +name in /etc/l7-protocols/
- +.TP
- +.BI "--l7dir " "\fIdirectory\fP"
- +Use \fIdirectory\fP instead of /etc/l7-protocols/
- +
|