source: freewrt/package/iptables/patches/02-layer7-1.5nbd.patch@ 475ad56

freewrt_1_0 freewrt_2_0
Last change on this file since 475ad56 was 475ad56, checked in by Waldemar Brodkorb <wbx@…>, 19 years ago

add OpenWrt trunk revision 3830.

git-svn-id: svn://www.freewrt.org/trunk/freewrt@1 afb5a338-a214-0410-bd46-81f09a774fd1

  • Property mode set to 100644
File size: 11.5 KB
  • extensions/.layer7-test

    diff -urN iptables.old/extensions/.layer7-test iptables.dev/extensions/.layer7-test
    old new  
     1#! /bin/sh
     2[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_layer7.h ] && echo layer7
  • extensions/ipt_layer7.h

    diff -urN iptables.old/extensions/ipt_layer7.h iptables.dev/extensions/ipt_layer7.h
    old new  
     1/*
     2  By Matthew Strait <quadong@users.sf.net>, Dec 2003.
     3  http://l7-filter.sf.net
     4
     5  This program is free software; you can redistribute it and/or
     6  modify it under the terms of the GNU General Public License
     7  as published by the Free Software Foundation; either version
     8  2 of the License, or (at your option) any later version.
     9  http://www.gnu.org/licenses/gpl.txt
     10*/
     11
     12#ifndef _IPT_LAYER7_H
     13#define _IPT_LAYER7_H
     14
     15#define MAX_PATTERN_LEN 8192
     16#define MAX_PROTOCOL_LEN 256
     17
     18typedef char *(*proc_ipt_search) (char *, char, char *);
     19
     20struct ipt_layer7_info {
     21    char protocol[MAX_PROTOCOL_LEN];
     22    char invert:1;
     23    char pattern[MAX_PATTERN_LEN];
     24        char pkt;
     25};
     26
     27#endif /* _IPT_LAYER7_H */
  • extensions/libipt_layer7.c

    diff -urN iptables.old/extensions/libipt_layer7.c iptables.dev/extensions/libipt_layer7.c
    old new  
     1/*
     2   Shared library add-on to iptables to add layer 7 matching support.
     3 
     4   By Matthew Strait <quadong@users.sf.net>, Oct 2003.
     5
     6   http://l7-filter.sf.net
     7
     8   This program is free software; you can redistribute it and/or
     9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version
     11   2 of the License, or (at your option) any later version.
     12   http://www.gnu.org/licenses/gpl.txt
     13
     14   Based on libipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>
     15*/
     16
     17#define _GNU_SOURCE
     18#include <stdio.h>
     19#include <netdb.h>
     20#include <string.h>
     21#include <stdlib.h>
     22#include <getopt.h>
     23#include <ctype.h>
     24#include <dirent.h>
     25
     26#include <iptables.h>
     27#include "ipt_layer7.h"
     28
     29#define MAX_FN_LEN 256
     30
     31static char l7dir[MAX_FN_LEN] = "\0";
     32
     33/* Function which prints out usage message. */
     34static void help(void)
     35{
     36        printf(
     37        "LAYER7 match v%s options:\n"
     38        "--l7dir <directory>  : Look for patterns here instead of /etc/l7-protocols/\n"
     39        "                       (--l7dir must be specified before --l7proto if used!)\n"
     40        "--l7proto [!] <name> : Match the protocol defined in /etc/l7-protocols/name.pat\n"
     41        "--l7pkt              : Skip connection tracking and match individual packets\n",
     42        IPTABLES_VERSION);
     43        fputc('\n', stdout);
     44}
     45
     46static struct option opts[] = {
     47        { .name = "l7proto", .has_arg = 1, .flag = 0, .val = '1' },
     48        { .name = "l7dir",   .has_arg = 1, .flag = 0, .val = '2' },
     49        { .name = "l7pkt",   .has_arg = 0, .flag = 0, .val = '3' },
     50        { .name = 0 }
     51};
     52
     53/* reads filename, puts protocol info into layer7_protocol_info, number of protocols to numprotos */
     54int parse_protocol_file(char * filename, const unsigned char * protoname, struct ipt_layer7_info *info)
     55{
     56        FILE * f;
     57        char * line = NULL;
     58        size_t len = 0;
     59
     60        enum { protocol, pattern, done } datatype = protocol;
     61
     62        f = fopen(filename, "r");
     63
     64        if(!f)
     65                return 0;
     66
     67        while(getline(&line, &len, f) != -1)
     68        {
     69                if(strlen(line) < 2 || line[0] == '#')
     70                        continue;
     71
     72                /* strip the pesky newline... */
     73                if(line[strlen(line) - 1] == '\n')
     74                        line[strlen(line) - 1] = '\0';
     75
     76                if(datatype == protocol)
     77                {
     78                        if(strcmp(line, protoname))
     79                                exit_error(OTHER_PROBLEM,
     80                                        "Protocol name (%s) doesn't match file name (%s).  Bailing out\n",
     81                                        protoname, filename);
     82
     83                        if(strlen(line) >= MAX_PROTOCOL_LEN)
     84                                 exit_error(PARAMETER_PROBLEM,
     85                                        "Protocol name in %s too long!", filename);
     86                        strncpy(info->protocol, line, MAX_PROTOCOL_LEN);
     87
     88                        datatype = pattern;
     89                }
     90                else if(datatype == pattern)
     91                {
     92                        if(strlen(line) >= MAX_PATTERN_LEN)
     93                                 exit_error(PARAMETER_PROBLEM, "Pattern in %s too long!", filename);
     94                        strncpy(info->pattern, line, MAX_PATTERN_LEN);
     95                       
     96                        datatype = done;                       
     97                        break;
     98                }
     99                else
     100                        exit_error(OTHER_PROBLEM, "Internal error");
     101        }
     102
     103        if(datatype != done)
     104                exit_error(OTHER_PROBLEM, "Failed to get all needed data from %s", filename);
     105
     106        if(line) free(line);
     107        fclose(f);
     108
     109        return 1;
     110
     111/*
     112        fprintf(stderr, "protocol: %s\npattern: %s\n\n",
     113                        info->protocol,
     114                        info->pattern);
     115*/
     116}
     117
     118static int hex2dec(char c)
     119{
     120        switch (c)
     121        {
     122                case '0' ... '9':
     123                        return c - '0';
     124                case 'a' ... 'f':
     125                        return c - 'a' + 10;
     126                case 'A' ... 'F':
     127                        return c - 'A' + 10;
     128                default:
     129                        exit_error(OTHER_PROBLEM, "hex2dec: bad value!\n");
     130                        return 0;
     131        }
     132}
     133
     134/* takes a string with \xHH escapes and returns one with the characters
     135they stand for */
     136static char * pre_process(char * s)
     137{
     138        char * result = malloc(strlen(s) + 1);
     139        int sindex = 0, rindex = 0;
     140        while( sindex < strlen(s) )
     141        {
     142            if( sindex + 3 < strlen(s) &&
     143                s[sindex] == '\\' && s[sindex+1] == 'x' &&
     144                isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) )
     145                {
     146                        /* carefully remember to call tolower here... */
     147                        result[rindex] = tolower( hex2dec(s[sindex + 2])*16 +
     148                                                  hex2dec(s[sindex + 3] ) );
     149                        sindex += 3; /* 4 total */
     150                }
     151                else
     152                        result[rindex] = tolower(s[sindex]);
     153
     154                sindex++;
     155                rindex++;
     156        }
     157        result[rindex] = '\0';
     158
     159        return result;
     160}
     161
     162#define MAX_SUBDIRS 128
     163char ** readl7dir(char * dirname)
     164{
     165        DIR             * scratchdir;
     166        struct dirent   ** namelist;
     167        char ** subdirs = malloc(MAX_SUBDIRS * sizeof(char *));
     168
     169        int n, d = 1;
     170        subdirs[0] = "";
     171
     172        n = scandir(dirname, &namelist, 0, alphasort);
     173
     174        if (n < 0)
     175        {
     176            perror("scandir");
     177            exit_error(OTHER_PROBLEM, "Couldn't open %s\n", dirname);
     178        }
     179        else
     180        {
     181                while(n--)
     182                {
     183                        char fulldirname[MAX_FN_LEN];
     184
     185                        snprintf(fulldirname, MAX_FN_LEN, "%s/%s", dirname, namelist[n]->d_name);
     186
     187                        if((scratchdir = opendir(fulldirname)) != NULL)
     188                        {
     189                                closedir(scratchdir);
     190
     191                                if(!strcmp(namelist[n]->d_name, ".") ||
     192                                   !strcmp(namelist[n]->d_name, ".."))
     193                                        /* do nothing */ ;
     194                                else
     195                                {
     196                                        subdirs[d] = malloc(strlen(namelist[n]->d_name) + 1);
     197                                        strcpy(subdirs[d], namelist[n]->d_name);
     198                                        d++;
     199                                        if(d >= MAX_SUBDIRS - 1)
     200                                        {
     201                                                fprintf(stderr,
     202                                                  "Too many subdirectories, skipping the rest!\n");
     203                                                break;
     204                                        }
     205                                }
     206                        }
     207                        free(namelist[n]);
     208                }
     209                free(namelist);
     210        }
     211       
     212        subdirs[d] = NULL;
     213
     214        return subdirs;
     215}
     216
     217static void
     218parse_layer7_protocol(const unsigned char *s, struct ipt_layer7_info *info)
     219{
     220        char filename[MAX_FN_LEN];
     221        char * dir = NULL;
     222        char ** subdirs;
     223        int n = 0, done = 0;
     224
     225        if(strlen(l7dir) > 0)
     226                dir = l7dir;
     227        else
     228                dir = "/etc/l7-protocols";
     229
     230        subdirs = readl7dir(dir);
     231
     232        while(subdirs[n] != NULL)
     233        {
     234                int c = snprintf(filename, MAX_FN_LEN, "%s/%s/%s.pat", dir, subdirs[n], s);
     235
     236                //fprintf(stderr, "Trying to find pattern in %s ... ", filename);
     237
     238                if(c > MAX_FN_LEN)
     239                {
     240                        exit_error(OTHER_PROBLEM,
     241                                "Filename beginning with %s is too long!\n", filename);
     242                }
     243
     244                /* read in the pattern from the file */
     245                if(parse_protocol_file(filename, s, info))
     246                {
     247                        //fprintf(stderr, "found\n");
     248                        done = 1;
     249                        break;
     250                }
     251               
     252                //fprintf(stderr, "not found\n");
     253
     254                n++;
     255        }
     256
     257        if(!done)
     258                exit_error(OTHER_PROBLEM,
     259                        "Couldn't find a pattern definition file for %s.\n", s);
     260
     261        /* process \xHH escapes and tolower everything. (our regex lib has no
     262        case insensitivity option.) */
     263        strncpy(info->pattern, pre_process(info->pattern), MAX_PATTERN_LEN);
     264}
     265
     266/* Function which parses command options; returns true if it ate an option */
     267static int parse(int c, char **argv, int invert, unsigned int *flags,
     268      const struct ipt_entry *entry, unsigned int *nfcache,
     269      struct ipt_entry_match **match)
     270{
     271        struct ipt_layer7_info *layer7info =
     272                (struct ipt_layer7_info *)(*match)->data;
     273
     274        switch (c) {
     275        case '1':
     276                check_inverse(optarg, &invert, &optind, 0);
     277                parse_layer7_protocol(argv[optind-1], layer7info);
     278                if (invert)
     279                        layer7info->invert = 1;
     280                *flags = 1;
     281                break;
     282
     283        case '2':
     284                /* not going to use this, but maybe we need to strip a ! anyway (?) */
     285                check_inverse(optarg, &invert, &optind, 0);
     286
     287                if(strlen(argv[optind-1]) >= MAX_FN_LEN)
     288                        exit_error(PARAMETER_PROBLEM, "directory name too long\n");
     289
     290                strncpy(l7dir, argv[optind-1], MAX_FN_LEN);
     291
     292                *flags = 1;
     293                break;
     294        case '3':
     295                layer7info->pkt = 1;
     296                break;
     297
     298        default:
     299                return 0;
     300        }
     301
     302        return 1;
     303}
     304
     305/* Final check; must have specified --pattern. */
     306static void final_check(unsigned int flags)
     307{
     308        if (!flags)
     309                exit_error(PARAMETER_PROBLEM,
     310                           "LAYER7 match: You must specify `--pattern'");
     311}
     312
     313static void print_protocol(char s[], int invert, int numeric)
     314{
     315        fputs("l7proto ", stdout);
     316        if (invert) fputc('!', stdout);
     317        printf("%s ", s);
     318}
     319
     320/* Prints out the matchinfo. */
     321static void print(const struct ipt_ip *ip,
     322      const struct ipt_entry_match *match,
     323      int numeric)
     324{
     325        printf("LAYER7 ");
     326
     327        print_protocol(((struct ipt_layer7_info *)match->data)->protocol,
     328                  ((struct ipt_layer7_info *)match->data)->invert, numeric);
     329
     330        if (((struct ipt_layer7_info *)match->data)->pkt)
     331                printf("l7pkt ");
     332}
     333/* Saves the union ipt_matchinfo in parsable form to stdout. */
     334static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
     335{
     336        const struct ipt_layer7_info *info =
     337            (const struct ipt_layer7_info*) match->data;
     338
     339        printf("--l7proto %s%s ", (info->invert)   ? "! ": "", info->protocol);
     340}
     341
     342static struct iptables_match layer7 = {
     343    .name          = "layer7",
     344    .version       = IPTABLES_VERSION,
     345    .size          = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
     346    .userspacesize = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
     347    .help          = &help,
     348    .parse         = &parse,
     349    .final_check   = &final_check,
     350    .print         = &print,
     351    .save          = &save,
     352    .extra_opts    = opts
     353};
     354
     355void _init(void)
     356{
     357        register_match(&layer7);
     358}
  • extensions/libipt_layer7.man

    diff -urN iptables.old/extensions/libipt_layer7.man iptables.dev/extensions/libipt_layer7.man
    old new  
     1This module matches packets based on the application layer data of
     2their connections.  It uses regular expression matching to compare
     3the application layer data to regular expressions found it the layer7
     4configuration files.  This is an experimental module which can be found at
     5http://l7-filter.sf.net.  It takes two options.
     6.TP
     7.BI "--l7proto " "\fIprotocol\fP"
     8Match the specified protocol.  The protocol name must match a file
     9name in /etc/l7-protocols/
     10.TP
     11.BI "--l7dir " "\fIdirectory\fP"
     12Use \fIdirectory\fP instead of /etc/l7-protocols/
     13
Note: See TracBrowser for help on using the repository browser.