编译时出错 - 初始化程序中指定的未知字段
我发现了一个用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
听起来你的 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 ?
我不熟悉 ROPE,但从文档来看,它看起来应该是构建为内核模块,因此构建它可能比直接的
gcc
调用更多。要安装它以在用户空间(不是内核的一部分)中使用,请查看文档中的此部分: http: //www.lowth.com/rope/UserLand
另外,ROPE 的最后一个可用版本似乎是针对 2.4 内核开发的,因此 @sylvainulg 提到当前内核标头可能存在一些不兼容问题。
更新
看起来 ROPE 在内核 2.6 上运行良好,但不适用于最新的 iptables。网站指出:
针对 多个版本的 iptables 进行编译表明,再次编译时该错误是可重现的较晚 (1.4.10),但
1.3.0
不会发生。update2
这是让它发挥作用的最后一次尝试。尝试将以下内容添加到源代码的顶部:
从 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:
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:
As of iptables 1.4.0,
iptables_match
seems to be defined asxtables_match
(seeincludes/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).您使用哪些编译器选项来编译该代码?
看来您正在尝试使用 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?