Usage libiptc to add new rule, error with function iptc_commit():Invalid argument

Discussion in 'Linux Networking' started by Олег Ðплекаев, Oct 12, 2014.

  1. I am trying to write some code to add this iptables rule:

    iptables -t nat -A PREROUTING -s 192.168.213.2 -d 186.23.1.128 -i eth1 -p tcp --sport 34533 --dport 443 -j REDIRECT --to-ports 8443

    When I call iptc_commit() procedure in this code, I get the error invalid argument. I think the problem lies in completing the structure of ipt_entry_target.

    Does anyone know what could be wrong with my sample code here?

    #include "linux/netfilter/xt_limit.h"
    #include "linux/netfilter/xt_physdev.h"
    #include "linux/netfilter_ipv4/ip_tables.h"

    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
    #define __must_be_array(a) \
    BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
    #define LIST_POISON2 ((void *) 0x00200200 )
    #include <linux/netfilter_ipv4/nf_nat.h>
    #define ip_nat_multi_range nf_nat_multi_range
    #define ip_nat_range nf_nat_range
    #define IPTC_HANDLE struct iptc_handle *

    #ifndef IPT_ALIGN
    #define IPT_ALIGN XT_ALIGN
    #endif

    #define IP_PARTS_NATIVE(n) \
    (unsigned int)((n)>>24)&0xFF, \
    (unsigned int)((n)>>16)&0xFF, \
    (unsigned int)((n)>>8)&0xFF, \
    (unsigned int)((n)&0xFF)

    #define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))

    struct pprot {
    char *name;
    u_int8_t num;
    };

    static const struct pprot chain_protos[] = {
    { "tcp", IPPROTO_TCP },
    { "udp", IPPROTO_UDP },
    { "icmp", IPPROTO_ICMP },
    { "esp", IPPROTO_ESP },
    { "ah", IPPROTO_AH },
    };

    int main(int argc, char *argv[])
    {
    int ret = 0;
    struct ipt_entry *entry = NULL;
    struct ipt_entry_match *match = NULL;
    struct ipt_entry_target *target = NULL;
    IPTC_HANDLE iptcHandle_ = iptc_init(nat);
    if (!IPTC_HANDLE)
    exit(1);
    entry = static_cast<struct ipt_entry *>(calloc(1, sizeof (struct ipt_entry)));
    if (entry == NULL)
    exit(1);
    entry->ip.proto = IPPROTO_TCP;
    match = getTcpMatch(443, 34533);
    entry->nfcache = NFC_IP_DST_PT;
    target = getRedirectTarget(_redirectPort);
    entry->nfcache |= NFC_UNKNOWN;
    entry = static_cast<struct ipt_entry *>(realloc(entry, sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size));
    memcpy(entry->elems, match, match->u.match_size);
    memcpy(entry->elems + match->u.match_size, target, target->u.target_size);
    entry->target_offset = sizeof(struct ipt_entry)
    + match->u.match_size;
    entry->next_offset = sizeof(struct ipt_entry)
    + match->u.match_size
    + target->u.target_size;
    entry->ip.src.s_addr = inet_addr('192.168.213.2');
    entry->ip.smsk.s_addr = 0xFFFFFFFF;
    strcpy(entry->ip.iniface, 'eth1');
    entry->ip.dst.s_addr = inet_addr('189.222.1.128');
    entry->ip.dmsk.s_addr = 0xFFFFFFFF;
    if(!iptc_append_entry("PREROUTING", entry, iptcHandle_))
    exit(1);
    if(!iptc_commit(iptcHandle_))
    exit(1);
    } //int main(int argc, char *argv[])

    struct ipt_entry_match *getTcpMatch(unsigned short _dport, unsigned short _sport)
    {
    struct ipt_entry_match *match;
    struct ipt_tcp * tcpinfo;
    size_t size;
    size = IPT_ALIGN(sizeof(struct ipt_entry_match))
    + IPT_ALIGN(sizeof(struct ipt_tcp));
    match = static_cast<ipt_entry_match *>(calloc(1, size));
    match->u.match_size = size;
    strncpy(match->u.user.name, "tcp", sizeof(match->u.user.name));
    tcpinfo = (struct ipt_tcp *)match->data;
    if (_sport == 0)
    {
    tcpinfo->spts[0] = 0; /* all source ports */
    tcpinfo->spts[1] = 0xFFFF;
    } //if (sport == 0)
    else
    {
    tcpinfo->spts[0] = _sport; /* specified source port */
    tcpinfo->spts[1] = _sport;
    } //else /if (sport == 0)
    if (_dport == 0)
    {
    tcpinfo->dpts[0] = 0; /* all destination ports */
    tcpinfo->dpts[1] = 0xFFFF;
    } //if (dport == 0)
    else
    {
    tcpinfo->dpts[0] = _dport; /* specified destination port */
    tcpinfo->dpts[1] = _dport;
    } //else /if (dport == 0)
    return match;
    } //struct ipt_entry_match *getTcpMatch(unsigned short _dport, unsigned short _sport)

    struct ipt_entry_target *getRedirectTarget(unsigned short _redirectPort)
    {
    struct ipt_entry_target * target;
    //!!! I doubt the use of this structure
    struct ip_nat_range * range;
    size_t size;

    size = IPT_ALIGN(sizeof(struct ipt_entry_target))
    + IPT_ALIGN(sizeof(struct ip_nat_range));
    target = static_cast<ipt_entry_target *>(calloc(1, size));
    target->u.target_size = size;
    strncpy(target->u.user.name, "REDIRECT", sizeof(target->u.user.name));
    /* one ip_nat_range already included in ip_nat_multi_range */
    range = (struct ip_nat_range *)&target->data[0];
    //range->min_ip = range->max_ip = inet_addr(daddr);
    //range->flags |= IP_NAT_RANGE_MAP_IPS;
    range->min.all = range->max.all = htons(_redirectPort);
    range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
    return target;
    } //static struct ipt_entry_target *getRedirectTarget(unsigned short _redirectPort)
     
    Олег Ðплекаев, Oct 12, 2014
    #1
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.