iptablesinvalid-argumentiptc

Adding a custom chain to OUTPUT using libiptc


I'm trying to achieve the following iptable command using libiptc, but cannot find any examples of how to do this.

iptables -A OUTPUT -j my_outbound_rules

I've tried using the following code:

int addChainToBuiltin(const char *_pChain, const char *_pTarget)
{
    /*iptables -A OUTPUT  -j <chain>*/
    const char *pTable    = "filter";

    struct xtc_handle      *pHandle;
    struct ipt_entry       *pEntry;
    struct xt_entry_target *pTarget;

    size_t entrySize  = XT_ALIGN(sizeof(struct ipt_entry));
    size_t targetSize = XT_ALIGN(sizeof(struct xt_entry_target));

    pHandle = iptc_init(pTable);
    if (! pHandle)
        return errno;

    pEntry  = calloc(1, entrySize + targetSize);
    pTarget = (struct xt_entry_target *)((char*)pEntry + entrySize);

    strncpy(pTarget->u.user.name, _pTarget, sizeof(pTarget->u.user.name));
    pTarget->u.target_size      = targetSize;
    pTarget->u.user.target_size = targetSize;
    pTarget->u.user.revision    = 1;

    pEntry->target_offset = entrySize;
    pEntry->next_offset   = entrySize + targetSize;

    pEntry->ip.src.s_addr  = INADDR_ANY;
    pEntry->ip.smsk.s_addr = 0;
    pEntry->ip.dst.s_addr  = INADDR_ANY;
    pEntry->ip.dmsk.s_addr = 0;

    pEntry->ip.proto    = 0; // any
    pEntry->ip.flags    = 0;
    pEntry->ip.invflags = 0;
    pEntry->nfcache     = NFC_UNKNOWN;

    int res = applyRule(Append, _pChain, pEntry, pHandle);
    if (res == 0)
        res = commitAndFree(pHandle);

    printf("Result: %d %s\n", res, iptc_strerror(res));

    free(pEntry);

    return res;
}

But I get an error 'Invalid Argument' from iptc_strerror, but cannot see which argument is invalid.

Many thanks


Solution

  • Solved it with the following code:

    int addChainToBuiltin(const char *_pChain, const char *_pTarget)
    {
        /*iptables -A OUTPUT  -j <chain>*/
        const char *pTable    = "filter";
    
        struct xtc_handle         *pHandle;
        struct ipt_entry          *pEntry;
        struct xt_standard_target *pTarget;
    
        size_t entrySize  = XT_ALIGN(sizeof(struct ipt_entry));
        size_t targetSize = XT_ALIGN(sizeof(struct xt_standard_target));
    
        pHandle = iptc_init(pTable);
        if (! pHandle)
            return errno;
    
        pEntry  = calloc(1, entrySize + targetSize);
        pTarget = (struct xt_entry_target *)((char*)pEntry + entrySize);
    
        strncpy(pTarget->target.u.user.name, _pTarget, sizeof(pTarget->target.u.user.name));
        pTarget->target.u.target_size      = targetSize;
        pTarget->target.u.user.target_size = targetSize;
        pTarget->target.u.user.revision = 0;
    
        pEntry->target_offset = entrySize;
        pEntry->next_offset   = entrySize + targetSize;
    
        pEntry->ip.src.s_addr  = INADDR_ANY;
        pEntry->ip.smsk.s_addr = 0;
        pEntry->ip.dst.s_addr  = INADDR_ANY;
        pEntry->ip.dmsk.s_addr = 0;
    
        pEntry->ip.proto    = 0; // any
        pEntry->ip.flags    = 0;
        pEntry->ip.invflags = 0;
        pEntry->nfcache     = NFC_UNKNOWN;
    
        printf("Adding: %s to %s\n", pTarget->target.u.user.name, _pChain);
    
        int res = applyRule(Append, _pChain, pEntry, pHandle);
        if (res == 0)
            res = commitAndFree(pHandle);
    
        free(pEntry);
    
        return res;
    }