编译时出错 - 初始化程序中指定的未知字段

发布于 2024-10-22 00:20:03 字数 16026 浏览 0 评论 0原文

我发现了一个用 C 语言编写的旧脚本,当我尝试编译它时,我收到以下消息

 # gcc libipt_rope.c -o libipt_rope.so
libipt_rope.c:349: error: variable ‘rope’ has initializer but incomplete type
libipt_rope.c:350: error: unknown field ‘next’ specified in initializer
libipt_rope.c:350: warning: excess elements in struct initializer
libipt_rope.c:350: warning: (near initialization for ‘rope’)
libipt_rope.c:351: error: unknown field ‘name’ specified in initializer
libipt_rope.c:351: warning: excess elements in struct initializer
libipt_rope.c:351: warning: (near initialization for ‘rope’)
libipt_rope.c:352: error: unknown field ‘version’ specified in initializer
libipt_rope.c:352: warning: excess elements in struct initializer
libipt_rope.c:352: warning: (near initialization for ‘rope’)
libipt_rope.c:353: error: unknown field ‘size’ specified in initializer
libipt_rope.c:353: warning: excess elements in struct initializer
libipt_rope.c:353: warning: (near initialization for ‘rope’)
libipt_rope.c:354: error: unknown field ‘userspacesize’ specified in initializer
libipt_rope.c:354: warning: excess elements in struct initializer
libipt_rope.c:354: warning: (near initialization for ‘rope’)
libipt_rope.c:355: error: unknown field ‘help’ specified in initializer
libipt_rope.c:355: warning: excess elements in struct initializer
libipt_rope.c:355: warning: (near initialization for ‘rope’)
libipt_rope.c:356: error: unknown field ‘init’ specified in initializer
libipt_rope.c:356: warning: excess elements in struct initializer
libipt_rope.c:356: warning: (near initialization for ‘rope’)
libipt_rope.c:357: error: unknown field ‘parse’ specified in initializer
libipt_rope.c:357: warning: excess elements in struct initializer
libipt_rope.c:357: warning: (near initialization for ‘rope’)
libipt_rope.c:358: error: unknown field ‘final_check’ specified in initializer
libipt_rope.c:358: warning: excess elements in struct initializer
libipt_rope.c:358: warning: (near initialization for ‘rope’)
libipt_rope.c:359: error: unknown field ‘print’ specified in initializer
libipt_rope.c:359: warning: excess elements in struct initializer
libipt_rope.c:359: warning: (near initialization for ‘rope’)
libipt_rope.c:360: error: unknown field ‘save’ specified in initializer
libipt_rope.c:360: warning: excess elements in struct initializer
libipt_rope.c:360: warning: (near initialization for ‘rope’)
libipt_rope.c:361: error: unknown field ‘extra_opts’ specified in initializer
libipt_rope.c:362: warning: excess elements in struct initializer
libipt_rope.c:362: warning: (near initialization for ‘rope’

,我正在询问 C 专家,因为我对 C 语言非常熟悉,但不是那么熟悉。

这是代码

/

/* For detailed documentation about ROPE, visit http://www.lowth.com/rope */

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

#include "iptables.h"

#define _USERLAND_ 1
#define _ROPE_IPTABLES_ 1
#include "rope.h"
#include "rope-enum.h"

#define WANT_ROPE_LOAD_SCRIPT
#include "rope-util.h"

#define IPT_ROPE_SCRIPT     0x0001
#define IPT_ROPE_PUSH_INT   0x0002
#define IPT_ROPE_PUSH_STR   0x0004
#define IPT_ROPE_PUSH_IP    0x0008

#define OPT_SCRIPT   "rope-script"
#define OPT_PUSH_INT "rope-push-int"
#define OPT_PUSH_STR "rope-push-str"
#define OPT_PUSH_IP  "rope-push-ip"

/* Function which prints out usage message. */
static void help(void)
{
    printf(
"ROPE (version " ROPE_VERSION ") match v%s options:\n"
"[!] --" OPT_SCRIPT "    scriptfile    Name of packet-matching ROPE script\n"
"    --" OPT_PUSH_INT "  integer       Push integer onto stack\n"
"    --" OPT_PUSH_STR "  string        Push string onto stack\n"
"    --" OPT_PUSH_IP "   ip-address    Push IPv4 address onto stack\n",
IPTABLES_VERSION);

    fputc('\n', stdout);
}

static struct option opts[] = {
    { "script",     1, 0, '1' },    // for backwards compatibility
    { OPT_SCRIPT,   1, 0, '1' },
    { OPT_PUSH_INT, 1, 0, '2' },
    { OPT_PUSH_STR, 1, 0, '3' },
    { OPT_PUSH_IP,  1, 0, '4' },
    {0}
};

/* Initialize the match. */
static void init(struct ipt_entry_match *m, unsigned int *nfcache)
{
    struct ipt_rope_info *ropeinfo = (struct ipt_rope_info *)(m)->data;
    *nfcache |= NFC_UNKNOWN;
    memset(ropeinfo, 0, sizeof(*ropeinfo));
    ropeinfo->version = ROPE_SCRIPT_VERSION;
    ropeinfo->info_size = (u_int16_t)sizeof(struct ipt_rope_info);
}

static void read_scriptfile(struct ipt_rope_info *info, char *filename)
{
    int i;
    int len = strlen(filename);
    char *scriptdir = "/etc/rope.d/scripts";
    char path[ROPE_MAX_FILENAME + strlen(scriptdir)+8];
    struct stat stat_info;
    int ok, script_offset, script_len, ipsets_offset, ipsets_len, used_buff;

    if (len < 1) exit_error(PARAMETER_PROBLEM, "Script file name cannot be empty" );
    if (len >= ROPE_MAX_FILENAME) exit_error(PARAMETER_PROBLEM, "Script file name too long" );
    for (i=0; i<len; i++) {
        char c = filename[i];
        if ( !isalnum(c) && c != '-' && c != '_' )
            exit_error(
                PARAMETER_PROBLEM,
                "Script file name can only contain letters, digits or hyphens"
            );
    }
    strcpy(path, scriptdir);
    strcat(path, "/");
    strcat(path, filename);
    strcat(path, ".rp");

    /* Verify that it is safe to load scripts from the directory */
    if (lstat(scriptdir, &stat_info) != 0)
        exit_error( PARAMETER_PROBLEM, "Cant stat '%s'", scriptdir );
    if (!S_ISDIR(stat_info.st_mode))
        exit_error( PARAMETER_PROBLEM, "'%s' is not a directory (it should be)", scriptdir);
    if (stat_info.st_uid != 0)
        exit_error( PARAMETER_PROBLEM, "Directory '%s' is not owned by 'root' (it should be)", scriptdir);
    if (stat_info.st_mode & (S_IWGRP | S_IWOTH))
        exit_error( PARAMETER_PROBLEM, "Directory '%s' may be writeable by non-root users (it should not be)", scriptdir);

    /* Verify that only root can modify it */
    if (lstat(path, &stat_info) != 0)
        exit_error( PARAMETER_PROBLEM, "Cant stat '%s'", path);
    if (!S_ISREG(stat_info.st_mode))
        exit_error( PARAMETER_PROBLEM, "'%s' is not a regular file (it should be)", path);
    if (stat_info.st_uid != 0)
        exit_error( PARAMETER_PROBLEM, "File '%s' is not owned by 'root' (it should be)", path);
    if (stat_info.st_mode & (S_IWGRP | S_IWOTH))
        exit_error( PARAMETER_PROBLEM, "File '%s' may be writeable by non-root users (it should not be)", path);

    strcpy(info->scriptfile, filename);

    ok = rope_load_script(
        path,
        info->scriptbuff+info->arguments_len, ROPE_MAX_COMPILED_SIZE - info->arguments_len, &used_buff,
        &script_offset, &script_len,
        &ipsets_offset, &ipsets_len
    );

    if ( !ok )
        exit_error( PARAMETER_PROBLEM, "Cant load file '%s'", path );

    info->script_offset = 0;
    info->script_len = info->arguments_len + script_len;
    info->ipsets_offset = ipsets_offset + info->arguments_len;
    info->ipsets_len = ipsets_len;
    info->scriptbuff_len = used_buff;
}

/* 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_rope_info *ropeinfo = (struct ipt_rope_info *)(*match)->data;
    int n, len, i;
    struct hostent *he;
    char push_buff[ROPE_MAX_COMPILED_SIZE];
    int push_len = 0;

    switch (c)
    {
        case '1':   // --rope-script
            ropeinfo->invert = invert;
            if (*flags & IPT_ROPE_SCRIPT)
                exit_error( PARAMETER_PROBLEM, "--"OPT_SCRIPT": cant specify more than one script");
            read_scriptfile( ropeinfo, optarg );
            *flags |= IPT_ROPE_SCRIPT;
            break;

        case '2':   // --rope-push-int
            if (invert)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_INT": cant specify '!'");
            n = atoi(optarg);
            if (n >= 0 && n <= 127) {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_INTEGER8;
                push_buff[push_len++] = n;
            } else if (n >= 0 && n <= 32767) {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_INTEGER16;
                push_buff[push_len++] = ((unsigned int)n & 0xff00) >> 8;
                push_buff[push_len++] = ((unsigned int)n & 0x00ff);
            } else {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_INTEGER;
                push_buff[push_len++] = ((unsigned int)n & 0xff000000) >> 24;
                push_buff[push_len++] = ((unsigned int)n & 0x00ff0000) >> 16;
                push_buff[push_len++] = ((unsigned int)n & 0x0000ff00) >> 8;
                push_buff[push_len++] = ((unsigned int)n & 0x000000ff);
            }
            *flags |= IPT_ROPE_PUSH_INT;
            break;

        case '3':   // --rope-push-str
            if (invert)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": cant specify '!'");
            len = strlen(optarg);
            if ((len + 3) > sizeof(push_buff))
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": string too long" );
            if (len < 128) {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_STRING8;
                push_buff[push_len++] = len;
            } else {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_STRING;
                push_buff[push_len++] = (len & 0xff00) >> 8;
                push_buff[push_len++] = (len & 0x00ff);
            }

            /*
             * We have to check that the string we provide will work with iptables-save and
             * iptables-restore - which are rather crude in their parsing of the config
             * file they use. Non printable characters, control characters and quotes will
             * all cause us problems.
             */

            for (i=0; i<len; i++) {
                if (iscntrl(optarg[i]) || !isprint(optarg[i]))
                    exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": string includes non-printable character(s)");
                if (optarg[i] == '"')
                    exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": string includes double-quote character(s)");
            }

            memcpy(push_buff+push_len, optarg, len);
            push_len += len;
            *flags |= IPT_ROPE_PUSH_STR;
            break;

        case '4':   // --rope-push-ip
            if (invert)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": cant specify '!'");
            he = gethostbyname( optarg );
            if (he == NULL)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": cant resolve host name");
            if (he->h_length != 4)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": IPv4 address expected");
            if ( he->h_addr_list == NULL || he->h_addr_list[0] == NULL || he->h_addr_list[1] != NULL)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": name resolved to multiple IPv4 addresses");
            push_buff[push_len++] = ROPE_ELEMENT_TYPE_DOTTED_STRING8;
            push_buff[push_len++] = 4;
            memcpy(push_buff + push_len, he->h_addr_list[0], 4);
            push_len += 4;
            *flags |= IPT_ROPE_PUSH_IP;
            break;

        default:
            return 0;
    }

    memmove(
        ropeinfo->scriptbuff + ropeinfo->arguments_len + push_len,
        ropeinfo->scriptbuff + ropeinfo->arguments_len,
        ropeinfo->scriptbuff_len - ropeinfo->arguments_len
    );
    memcpy(ropeinfo->scriptbuff + ropeinfo->arguments_len, push_buff, push_len);
    ropeinfo->script_len += push_len;
    ropeinfo->ipsets_offset += push_len;
    ropeinfo->arguments_len += push_len;
    ropeinfo->scriptbuff_len += push_len;
    return 1;
}

/* Final check; must have specified --string. */
static void final_check(unsigned int flags)
{
    if (! (flags & IPT_ROPE_SCRIPT) )
        exit_error(
            PARAMETER_PROBLEM,
            "ROPE match: You must specify `--" OPT_SCRIPT "'"
        );
}

static void print_string(int len, unsigned char *str)
{
    putchar( '\"' );
    while (len) {
        putchar(*str);
        /*if (ch == '\n') printf( "\\n" );
        else if (ch == '\r') printf( "\\r" );
        else if (ch == '\t') printf( "\\t" );
        else if (ch == '"') printf( "\\\"" );
        else if (ch == '\\') printf( "\\\\" );
        else if (isprint( ch )) printf( "%c", ch );
        else printf( "\\%03o", ch );*/
        str ++;
        len --;
    }
    putchar( '\"' );
}

static void print_pushes(struct ipt_rope_info *info, char *prefix, char *delim)
{
    int opcode, len;
    unsigned char *buff = info->scriptbuff;
    unsigned char *end = info->scriptbuff + info->arguments_len;

    while (buff < end) {
        opcode = (*buff++);
        if (opcode == ROPE_ELEMENT_TYPE_INTEGER8) {
            printf( "%spush-int%s%d", prefix, delim, (*buff++) );
        } else if (opcode == ROPE_ELEMENT_TYPE_INTEGER16) {
            printf( "%spush-int%s%d", prefix, delim, buff[0] << 8 | buff[1]);
            buff += 2;
        } else if (opcode == ROPE_ELEMENT_TYPE_INTEGER) {
            printf( "%spush-int%s%d", prefix, delim, buff[0] << 24 | buff[1] << 16 | buff[2] << 8 | buff[3]);
            buff += 4;
        } else if (opcode == ROPE_ELEMENT_TYPE_DOTTED_STRING8 && *buff == 4) {
            printf( "%spush-ip%s%d.%d.%d.%d", prefix, delim, buff[1], buff[2], buff[3], buff[4] );
            buff += 5;
        } else if (opcode == ROPE_ELEMENT_TYPE_STRING8) {
            len = buff[0];
            printf( "%spush-str%s", prefix, delim );
            print_string(len, buff+1);
            buff += len + 1;
        } else if (opcode == ROPE_ELEMENT_TYPE_STRING) {
            len = buff[0] << 8 | buff[1];
            printf( "%spush-str%s", prefix, delim );
            print_string(len, buff+2);
            buff += len + 2;
        } else {
            return;
        }
        printf( " " );
    }
}

/* Prints out the matchinfo. */
static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
{
    printf( "ROPE script: %s%s ",
        ((struct ipt_rope_info *)match->data)->invert ? "!" : "",
        ((struct ipt_rope_info *)match->data)->scriptfile
    );
    print_pushes((struct ipt_rope_info *)match->data, "", ":");
}

/* Saves the union ipt_matchinfo in parsable form to stdout. */
static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
{
    printf( "%s--" OPT_SCRIPT " %s ",
        ((struct ipt_rope_info *)match->data)->invert ? "! " : "",
        ((struct ipt_rope_info *)match->data)->scriptfile
    );
    print_pushes((struct ipt_rope_info *)match->data, "--rope-", " ");
}

static struct iptables_match rope = {
        .next           = NULL,
        .name           = "rope",
        .version        = IPTABLES_VERSION,
        .size           = IPT_ALIGN(sizeof(struct ipt_rope_info)),
        .userspacesize  = IPT_ALIGN(sizeof(struct ipt_rope_info)),
        .help           = &help,
        .init           = &init,
        .parse          = &parse,
        .final_check    = &final_check,
        .print          = &print,
        .save           = &save,
        .extra_opts     = opts
};

void _init(void)
{
    register_match(&rope);
}

感谢您的阅读:)

I have found an old script written in C and when I try to compile it I get the following message

 # gcc libipt_rope.c -o libipt_rope.so
libipt_rope.c:349: error: variable ‘rope’ has initializer but incomplete type
libipt_rope.c:350: error: unknown field ‘next’ specified in initializer
libipt_rope.c:350: warning: excess elements in struct initializer
libipt_rope.c:350: warning: (near initialization for ‘rope’)
libipt_rope.c:351: error: unknown field ‘name’ specified in initializer
libipt_rope.c:351: warning: excess elements in struct initializer
libipt_rope.c:351: warning: (near initialization for ‘rope’)
libipt_rope.c:352: error: unknown field ‘version’ specified in initializer
libipt_rope.c:352: warning: excess elements in struct initializer
libipt_rope.c:352: warning: (near initialization for ‘rope’)
libipt_rope.c:353: error: unknown field ‘size’ specified in initializer
libipt_rope.c:353: warning: excess elements in struct initializer
libipt_rope.c:353: warning: (near initialization for ‘rope’)
libipt_rope.c:354: error: unknown field ‘userspacesize’ specified in initializer
libipt_rope.c:354: warning: excess elements in struct initializer
libipt_rope.c:354: warning: (near initialization for ‘rope’)
libipt_rope.c:355: error: unknown field ‘help’ specified in initializer
libipt_rope.c:355: warning: excess elements in struct initializer
libipt_rope.c:355: warning: (near initialization for ‘rope’)
libipt_rope.c:356: error: unknown field ‘init’ specified in initializer
libipt_rope.c:356: warning: excess elements in struct initializer
libipt_rope.c:356: warning: (near initialization for ‘rope’)
libipt_rope.c:357: error: unknown field ‘parse’ specified in initializer
libipt_rope.c:357: warning: excess elements in struct initializer
libipt_rope.c:357: warning: (near initialization for ‘rope’)
libipt_rope.c:358: error: unknown field ‘final_check’ specified in initializer
libipt_rope.c:358: warning: excess elements in struct initializer
libipt_rope.c:358: warning: (near initialization for ‘rope’)
libipt_rope.c:359: error: unknown field ‘print’ specified in initializer
libipt_rope.c:359: warning: excess elements in struct initializer
libipt_rope.c:359: warning: (near initialization for ‘rope’)
libipt_rope.c:360: error: unknown field ‘save’ specified in initializer
libipt_rope.c:360: warning: excess elements in struct initializer
libipt_rope.c:360: warning: (near initialization for ‘rope’)
libipt_rope.c:361: error: unknown field ‘extra_opts’ specified in initializer
libipt_rope.c:362: warning: excess elements in struct initializer
libipt_rope.c:362: warning: (near initialization for ‘rope’

I'm asking the C gurus, since i'm quite familiar with C, but not that much.

And here's the code

/

/* For detailed documentation about ROPE, visit http://www.lowth.com/rope */

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

#include "iptables.h"

#define _USERLAND_ 1
#define _ROPE_IPTABLES_ 1
#include "rope.h"
#include "rope-enum.h"

#define WANT_ROPE_LOAD_SCRIPT
#include "rope-util.h"

#define IPT_ROPE_SCRIPT     0x0001
#define IPT_ROPE_PUSH_INT   0x0002
#define IPT_ROPE_PUSH_STR   0x0004
#define IPT_ROPE_PUSH_IP    0x0008

#define OPT_SCRIPT   "rope-script"
#define OPT_PUSH_INT "rope-push-int"
#define OPT_PUSH_STR "rope-push-str"
#define OPT_PUSH_IP  "rope-push-ip"

/* Function which prints out usage message. */
static void help(void)
{
    printf(
"ROPE (version " ROPE_VERSION ") match v%s options:\n"
"[!] --" OPT_SCRIPT "    scriptfile    Name of packet-matching ROPE script\n"
"    --" OPT_PUSH_INT "  integer       Push integer onto stack\n"
"    --" OPT_PUSH_STR "  string        Push string onto stack\n"
"    --" OPT_PUSH_IP "   ip-address    Push IPv4 address onto stack\n",
IPTABLES_VERSION);

    fputc('\n', stdout);
}

static struct option opts[] = {
    { "script",     1, 0, '1' },    // for backwards compatibility
    { OPT_SCRIPT,   1, 0, '1' },
    { OPT_PUSH_INT, 1, 0, '2' },
    { OPT_PUSH_STR, 1, 0, '3' },
    { OPT_PUSH_IP,  1, 0, '4' },
    {0}
};

/* Initialize the match. */
static void init(struct ipt_entry_match *m, unsigned int *nfcache)
{
    struct ipt_rope_info *ropeinfo = (struct ipt_rope_info *)(m)->data;
    *nfcache |= NFC_UNKNOWN;
    memset(ropeinfo, 0, sizeof(*ropeinfo));
    ropeinfo->version = ROPE_SCRIPT_VERSION;
    ropeinfo->info_size = (u_int16_t)sizeof(struct ipt_rope_info);
}

static void read_scriptfile(struct ipt_rope_info *info, char *filename)
{
    int i;
    int len = strlen(filename);
    char *scriptdir = "/etc/rope.d/scripts";
    char path[ROPE_MAX_FILENAME + strlen(scriptdir)+8];
    struct stat stat_info;
    int ok, script_offset, script_len, ipsets_offset, ipsets_len, used_buff;

    if (len < 1) exit_error(PARAMETER_PROBLEM, "Script file name cannot be empty" );
    if (len >= ROPE_MAX_FILENAME) exit_error(PARAMETER_PROBLEM, "Script file name too long" );
    for (i=0; i<len; i++) {
        char c = filename[i];
        if ( !isalnum(c) && c != '-' && c != '_' )
            exit_error(
                PARAMETER_PROBLEM,
                "Script file name can only contain letters, digits or hyphens"
            );
    }
    strcpy(path, scriptdir);
    strcat(path, "/");
    strcat(path, filename);
    strcat(path, ".rp");

    /* Verify that it is safe to load scripts from the directory */
    if (lstat(scriptdir, &stat_info) != 0)
        exit_error( PARAMETER_PROBLEM, "Cant stat '%s'", scriptdir );
    if (!S_ISDIR(stat_info.st_mode))
        exit_error( PARAMETER_PROBLEM, "'%s' is not a directory (it should be)", scriptdir);
    if (stat_info.st_uid != 0)
        exit_error( PARAMETER_PROBLEM, "Directory '%s' is not owned by 'root' (it should be)", scriptdir);
    if (stat_info.st_mode & (S_IWGRP | S_IWOTH))
        exit_error( PARAMETER_PROBLEM, "Directory '%s' may be writeable by non-root users (it should not be)", scriptdir);

    /* Verify that only root can modify it */
    if (lstat(path, &stat_info) != 0)
        exit_error( PARAMETER_PROBLEM, "Cant stat '%s'", path);
    if (!S_ISREG(stat_info.st_mode))
        exit_error( PARAMETER_PROBLEM, "'%s' is not a regular file (it should be)", path);
    if (stat_info.st_uid != 0)
        exit_error( PARAMETER_PROBLEM, "File '%s' is not owned by 'root' (it should be)", path);
    if (stat_info.st_mode & (S_IWGRP | S_IWOTH))
        exit_error( PARAMETER_PROBLEM, "File '%s' may be writeable by non-root users (it should not be)", path);

    strcpy(info->scriptfile, filename);

    ok = rope_load_script(
        path,
        info->scriptbuff+info->arguments_len, ROPE_MAX_COMPILED_SIZE - info->arguments_len, &used_buff,
        &script_offset, &script_len,
        &ipsets_offset, &ipsets_len
    );

    if ( !ok )
        exit_error( PARAMETER_PROBLEM, "Cant load file '%s'", path );

    info->script_offset = 0;
    info->script_len = info->arguments_len + script_len;
    info->ipsets_offset = ipsets_offset + info->arguments_len;
    info->ipsets_len = ipsets_len;
    info->scriptbuff_len = used_buff;
}

/* 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_rope_info *ropeinfo = (struct ipt_rope_info *)(*match)->data;
    int n, len, i;
    struct hostent *he;
    char push_buff[ROPE_MAX_COMPILED_SIZE];
    int push_len = 0;

    switch (c)
    {
        case '1':   // --rope-script
            ropeinfo->invert = invert;
            if (*flags & IPT_ROPE_SCRIPT)
                exit_error( PARAMETER_PROBLEM, "--"OPT_SCRIPT": cant specify more than one script");
            read_scriptfile( ropeinfo, optarg );
            *flags |= IPT_ROPE_SCRIPT;
            break;

        case '2':   // --rope-push-int
            if (invert)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_INT": cant specify '!'");
            n = atoi(optarg);
            if (n >= 0 && n <= 127) {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_INTEGER8;
                push_buff[push_len++] = n;
            } else if (n >= 0 && n <= 32767) {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_INTEGER16;
                push_buff[push_len++] = ((unsigned int)n & 0xff00) >> 8;
                push_buff[push_len++] = ((unsigned int)n & 0x00ff);
            } else {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_INTEGER;
                push_buff[push_len++] = ((unsigned int)n & 0xff000000) >> 24;
                push_buff[push_len++] = ((unsigned int)n & 0x00ff0000) >> 16;
                push_buff[push_len++] = ((unsigned int)n & 0x0000ff00) >> 8;
                push_buff[push_len++] = ((unsigned int)n & 0x000000ff);
            }
            *flags |= IPT_ROPE_PUSH_INT;
            break;

        case '3':   // --rope-push-str
            if (invert)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": cant specify '!'");
            len = strlen(optarg);
            if ((len + 3) > sizeof(push_buff))
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": string too long" );
            if (len < 128) {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_STRING8;
                push_buff[push_len++] = len;
            } else {
                push_buff[push_len++] = ROPE_ELEMENT_TYPE_STRING;
                push_buff[push_len++] = (len & 0xff00) >> 8;
                push_buff[push_len++] = (len & 0x00ff);
            }

            /*
             * We have to check that the string we provide will work with iptables-save and
             * iptables-restore - which are rather crude in their parsing of the config
             * file they use. Non printable characters, control characters and quotes will
             * all cause us problems.
             */

            for (i=0; i<len; i++) {
                if (iscntrl(optarg[i]) || !isprint(optarg[i]))
                    exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": string includes non-printable character(s)");
                if (optarg[i] == '"')
                    exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_STR": string includes double-quote character(s)");
            }

            memcpy(push_buff+push_len, optarg, len);
            push_len += len;
            *flags |= IPT_ROPE_PUSH_STR;
            break;

        case '4':   // --rope-push-ip
            if (invert)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": cant specify '!'");
            he = gethostbyname( optarg );
            if (he == NULL)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": cant resolve host name");
            if (he->h_length != 4)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": IPv4 address expected");
            if ( he->h_addr_list == NULL || he->h_addr_list[0] == NULL || he->h_addr_list[1] != NULL)
                exit_error( PARAMETER_PROBLEM, "--"OPT_PUSH_IP": name resolved to multiple IPv4 addresses");
            push_buff[push_len++] = ROPE_ELEMENT_TYPE_DOTTED_STRING8;
            push_buff[push_len++] = 4;
            memcpy(push_buff + push_len, he->h_addr_list[0], 4);
            push_len += 4;
            *flags |= IPT_ROPE_PUSH_IP;
            break;

        default:
            return 0;
    }

    memmove(
        ropeinfo->scriptbuff + ropeinfo->arguments_len + push_len,
        ropeinfo->scriptbuff + ropeinfo->arguments_len,
        ropeinfo->scriptbuff_len - ropeinfo->arguments_len
    );
    memcpy(ropeinfo->scriptbuff + ropeinfo->arguments_len, push_buff, push_len);
    ropeinfo->script_len += push_len;
    ropeinfo->ipsets_offset += push_len;
    ropeinfo->arguments_len += push_len;
    ropeinfo->scriptbuff_len += push_len;
    return 1;
}

/* Final check; must have specified --string. */
static void final_check(unsigned int flags)
{
    if (! (flags & IPT_ROPE_SCRIPT) )
        exit_error(
            PARAMETER_PROBLEM,
            "ROPE match: You must specify `--" OPT_SCRIPT "'"
        );
}

static void print_string(int len, unsigned char *str)
{
    putchar( '\"' );
    while (len) {
        putchar(*str);
        /*if (ch == '\n') printf( "\\n" );
        else if (ch == '\r') printf( "\\r" );
        else if (ch == '\t') printf( "\\t" );
        else if (ch == '"') printf( "\\\"" );
        else if (ch == '\\') printf( "\\\\" );
        else if (isprint( ch )) printf( "%c", ch );
        else printf( "\\%03o", ch );*/
        str ++;
        len --;
    }
    putchar( '\"' );
}

static void print_pushes(struct ipt_rope_info *info, char *prefix, char *delim)
{
    int opcode, len;
    unsigned char *buff = info->scriptbuff;
    unsigned char *end = info->scriptbuff + info->arguments_len;

    while (buff < end) {
        opcode = (*buff++);
        if (opcode == ROPE_ELEMENT_TYPE_INTEGER8) {
            printf( "%spush-int%s%d", prefix, delim, (*buff++) );
        } else if (opcode == ROPE_ELEMENT_TYPE_INTEGER16) {
            printf( "%spush-int%s%d", prefix, delim, buff[0] << 8 | buff[1]);
            buff += 2;
        } else if (opcode == ROPE_ELEMENT_TYPE_INTEGER) {
            printf( "%spush-int%s%d", prefix, delim, buff[0] << 24 | buff[1] << 16 | buff[2] << 8 | buff[3]);
            buff += 4;
        } else if (opcode == ROPE_ELEMENT_TYPE_DOTTED_STRING8 && *buff == 4) {
            printf( "%spush-ip%s%d.%d.%d.%d", prefix, delim, buff[1], buff[2], buff[3], buff[4] );
            buff += 5;
        } else if (opcode == ROPE_ELEMENT_TYPE_STRING8) {
            len = buff[0];
            printf( "%spush-str%s", prefix, delim );
            print_string(len, buff+1);
            buff += len + 1;
        } else if (opcode == ROPE_ELEMENT_TYPE_STRING) {
            len = buff[0] << 8 | buff[1];
            printf( "%spush-str%s", prefix, delim );
            print_string(len, buff+2);
            buff += len + 2;
        } else {
            return;
        }
        printf( " " );
    }
}

/* Prints out the matchinfo. */
static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
{
    printf( "ROPE script: %s%s ",
        ((struct ipt_rope_info *)match->data)->invert ? "!" : "",
        ((struct ipt_rope_info *)match->data)->scriptfile
    );
    print_pushes((struct ipt_rope_info *)match->data, "", ":");
}

/* Saves the union ipt_matchinfo in parsable form to stdout. */
static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
{
    printf( "%s--" OPT_SCRIPT " %s ",
        ((struct ipt_rope_info *)match->data)->invert ? "! " : "",
        ((struct ipt_rope_info *)match->data)->scriptfile
    );
    print_pushes((struct ipt_rope_info *)match->data, "--rope-", " ");
}

static struct iptables_match rope = {
        .next           = NULL,
        .name           = "rope",
        .version        = IPTABLES_VERSION,
        .size           = IPT_ALIGN(sizeof(struct ipt_rope_info)),
        .userspacesize  = IPT_ALIGN(sizeof(struct ipt_rope_info)),
        .help           = &help,
        .init           = &init,
        .parse          = &parse,
        .final_check    = &final_check,
        .print          = &print,
        .save           = &save,
        .extra_opts     = opts
};

void _init(void)
{
    register_match(&rope);
}

Thanks for reading :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

俯瞰星空 2024-10-29 00:20:03

听起来你的 iptables_match 结构没有预期的帮助、打印、保存...字段给我。由于它是一个旧程序(我们不使用 C 的“脚本”),依赖于可能已经发展的内核头(iptables),您检查过 iptables_match 的新结构吗?

that sounds like your iptables_match structure doesn't have the expected help, print, save ... fields to me. Since it's an old program (we don't use 'script' for C) that relies on a kernel header (iptables) that is likely to have evolved, have you checked the new structure of iptables_match ?

靖瑶 2024-10-29 00:20:03

我不熟悉 ROPE,但从文档来看,它看起来应该是构建为内核模块,因此构建它可能比直接的 gcc 调用更多。

要安装它以在用户空间(不是内核的一部分)中使用,请查看文档中的此部分: http: //www.lowth.com/rope/UserLand

另外,ROPE 的最后一个可用版本似乎是针对 2.4 内核开发的,因此 @sylvainulg 提到当前内核标头可能存在一些不兼容问题。

更新

看起来 ROPE 在内核 2.6 上运行良好,但不适用于最新的 iptables。网站指出:

到目前为止,ROPE已经开发出来并
针对 2.4.x 和 2.6.x 进行了测试
linux 内核(适用于单 Intel CPU
平台)和 IpTables 从 1.2.x 到 1.3.x

针对 多个版本的 iptables 进行编译表明,再次编译时该错误是可重现的较晚 (1.4.10),但 1.3.0 不会发生。

update2

这是让它发挥作用的最后一次尝试。尝试将以下内容添加到源代码的顶部:

#ifdef _XTABLES_H
    #define iptables_rule_match        xtables_rule_match
    #define iptables_match             xtables_match
    #define iptables_target            xtables_target
    #define ipt_tryload                xt_tryload

    #if (!defined(IPTABLES_VERSION) && defined(XTABLES_VERSION))
        #define IPTABLES_VERSION   XTABLES_VERSION
    #endif

#endif

从 iptables 1.4.0 开始,iptables_match 似乎被定义为xtables_match(请参阅includes/xtables.h< /代码>)。假设没有任何其他更改更新会破坏 ROPE,则应该可以编译(不能保证它会按照所述想法工作。请彻底测试它)。

I'm not familiar with ROPE, but from the docs it looks like it is meant to be build as a kernel module so there may be more to building it than a straighforward gcc call.

To install it for use in userland (not part of kernel), look at this section in the docs: http://www.lowth.com/rope/UserLand

Also, it looks like the last available version of ROPE was developed against the 2.4 kernel so as the @sylvainulg mentioned there might be some incompatibility issues with current kernels headers.

updates

Looks like ROPE works fine on kernel 2.6 but not with the latest iptables. Website states:

So far, ROPE has been developed and
tested against the 2.4.x and 2.6.x
linux kernels (for single Intel CPU
platforms) and IpTables from 1.2.x to 1.3.x.

Compiling it against several version of iptables shows that the error is reproducable when compiled agains the lates (1.4.10) but does not occur for 1.3.0.

update2

Here's a last ditch attempt at trying to make it work. Try adding the following to the top of your source:

#ifdef _XTABLES_H
    #define iptables_rule_match        xtables_rule_match
    #define iptables_match             xtables_match
    #define iptables_target            xtables_target
    #define ipt_tryload                xt_tryload

    #if (!defined(IPTABLES_VERSION) && defined(XTABLES_VERSION))
        #define IPTABLES_VERSION   XTABLES_VERSION
    #endif

#endif

As of iptables 1.4.0, iptables_match seems to be defined as xtables_match (see includes/xtables.h). Assuming none of the other changes updates break ROPE, that should compile (no guarantees that it will work as stated thought. Do test it out thoroughly).

沫尐诺 2024-10-29 00:20:03

您使用哪些编译器选项来编译该代码?

看来您正在尝试使用 std=c99 进行编译,并且您的源代码使用了一些匿名结构,这些结构首先在 c11 中引入。所以你可能应该使用该选项进行编译。

如果是这种情况,您可以在此处阅读有关此主题的更多信息:
结构体中的匿名联合不在 c99 中?

Which compiler options do you use to compile that code?

It seems that you're trying to compile with std=c99 and your source code uses some anonymous structs, which are first introduced in c11. So probably you should compile with that option.

If that's the case, you can read more about this topic here:
Anonymous union within struct not in c99?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文