Я нашел старый скрипт, написанный на 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’
Я спрашиваю гуру Си, так как я довольно хорошо знаком с Си, но не так много.
А вот и код
/
/* 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);
}
Спасибо за чтение:)