加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

libiptc 之数据包利器

(2012-06-27 14:08:27)
标签:

鼎鼎大名

开发包

数据包

源代码

环境

分类: Linux
libiptc是netfilter的一个开发包,鼎鼎大名的iptables就是在它的基础上做的开发。

以下我是在SUSE 64位环境下做的实验(Ubuntu环境下一直有问题):

源代码:
#include <stdio.h>
#include <libiptc/libiptc.h>

int main(void){
char *tab = "filter";
struct iptc_handle *handle;
const char *chain;

handle = iptc_init(tab); //初始化table

chain = iptc_first_chain(handle); //获取该table中的第一个chain

printf("chain : %s\n", chain);

return 1;
}

编译:
gcc -liptc test.c -o test

备注:
编译时候,是需要头文件libiptc.h和动态链接库libiptc.so

在SUSE 32位环境下,在调用iptc_first_chain时会出现段错误(Segmentation fault)。哪位大侠知道错误原因的话,还望多多指点,谢谢。

以下是我利用libiptc做的一个程序原代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libiptc/libiptc.h>
#include <iptables.h>
#include <lib_netfilter.h>
#include <net/netfilter/nf_nat.h>
#include <linux/netfilter/xt_time.h>

//#define X64 1
//#define SHELL 1
#define TABS 12
#define MIN_PORT 0
#define MAX_PORT 65535
#define ipt_time xt_time_info
#define D_NO -1
#define D_DEBUG 0
#define RULE ipt_entry
//#define DEBUG D_DEBUG
#define XT_TIME_ALL_MONTHDAYS    0XFFFFFFFE
#define XT_TIME_ALL_WEEKDAYS    0XFE
#define XT_TIME_MIN_DAYTIME    0
#define    XT_TIME_MAX_DAYTIME    24 * 60 * 60 - 1
#define XT_TIME_LOOCAL_TZ    1 << 0

static char tables[][TABS] = {"filter", "mangle", "nat"};

static enum
{
    F_TIME_START    = 1 << 2,
    F_TIME_STOP    = 1 << 3,
};

static enum
{
    MATCH_TCP    = 1 << 0,
    MATCH_UDP    = 1 << 1,
    MATCH_TIME    = 1 << 2,
    MATCH_LIMIT    = 1 << 3,
};

static unsigned int time_parse_minutes(const char *str)
{
    unsigned int hour, minute, secound = 0;
    char *e;
    char *s = str;

    hour = strtoul(s, &e, 10);
    if(*e != ':' || hour > 23)
    {
        goto error;
    }

    s = e + 1;
    minute = strtoul(s, &e, 10);
    if((*e != ':' && *e != '\0') || minute > 59)
    {
        goto error;
    }

    if(*e == '\0')
    {
        goto success;
    }

    s = e + 1;
    secound = strtoul(s, &e, 10);
    if(*e != '\0' || secound > 59)
    {
        goto error;
    }

success:
    return 60 * 60 * hour + 60 * minute + secound;

error:
    return 0;
}

static void r_time_parse_minutes(int time, char *t_str)
{
    int t = time;

    sprintf(t_str, "%d", t / 3600);

    t %= 3600;
    sprintf(t_str, "%s:%d", t_str, t / 60);

    t %= 60;
    if(t > 0)
    {
        sprintf(t_str, "%s:%d", t_str, t);
    }

    t_str[strlen(t_str)] = '\0';
}

static void fill_rule_match(JNIEnv *env, jobject j_match, struct ipt_entry_match *match)
{
    jclass match_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Match");
    jmethodID match_getType_id = (*env)->GetMethodID(env, match_cls, "getType", "()I");
    jmethodID match_setType_id = (*env)->GetMethodID(env, match_cls, "setType", "(I)V");
    jmethodID match_setSport_id = (*env)->GetMethodID(env, match_cls, "setSport", "(I)V");
    jmethodID match_setDport_id = (*env)->GetMethodID(env, match_cls, "setDport", "(I)V");
    jmethodID match_setTimeStart_id = (*env)->GetMethodID(env, match_cls, "setTimeStart", "(Ljava/lang/String;)V");
    jmethodID match_setTimeStop_id = (*env)->GetMethodID(env, match_cls, "setTimeStop", "(Ljava/lang/String;)V");
    jmethodID match_setMtu_id = (*env)->GetMethodID(env, match_cls, "setMtu", "(I)V");

    const char *match_name = match->u.user.name;

    if(strcmp(match_name, "tcp") == 0)
    {
        struct ipt_tcp *m_tcp = (struct ipt_tcp*)match->data;
       
        if(m_tcp->spts[0] == m_tcp->spts[1])
        {
            (*env)->CallObjectMethod(env, j_match, match_setSport_id, m_tcp->spts[0]);
        }

        if(m_tcp->dpts[0] == m_tcp->dpts[1])
        {
            (*env)->CallObjectMethod(env, j_match, match_setDport_id, m_tcp->dpts[0]);
        }

        int type = (*env)->CallObjectMethod(env, j_match, match_getType_id);
        type = type < 0 ? 0 : type;

        (*env)->CallObjectMethod(env, j_match, match_setType_id, type + MATCH_TCP);
    }
    else if(strcmp(match_name, "udp") == 0)
    {
        struct ipt_udp *m_udp = (struct ipt_tcp*)match->data;
       
        if(m_udp->spts[0] == m_udp->spts[1])
        {
            (*env)->CallObjectMethod(env, j_match, match_setSport_id, m_udp->spts[0]);
        }

        if(m_udp->dpts[0] == m_udp->dpts[1])
        {
            (*env)->CallObjectMethod(env, j_match, match_setDport_id, m_udp->dpts[0]);
        }

        int type = (*env)->CallObjectMethod(env, j_match, match_getType_id);
        type = type < 0 ? 0 : type;

        (*env)->CallObjectMethod(env, j_match, match_setType_id, type + MATCH_UDP);
    }
    else if(strcmp(match_name, "time") == 0)
    {
        struct ipt_time *m_time = (struct ipt_time*)(match->data);

        if(m_time->flags & F_TIME_START)
        {
            char time[40];
            r_time_parse_minutes(m_time->daytime_start, time);
            (*env)->CallObjectMethod(env, j_match, match_setTimeStart_id, (*env)->NewStringUTF(env, time));
        }

        if(m_time->flags & F_TIME_STOP)
        {
            char time[40];
            r_time_parse_minutes(m_time->daytime_stop, time);
            (*env)->CallObjectMethod(env, j_match, match_setTimeStop_id, (*env)->NewStringUTF(env, time));
        }

        int type = (*env)->CallObjectMethod(env, j_match, match_getType_id);
        type = type < 0 ? 0 : type;

        (*env)->CallObjectMethod(env, j_match, match_setType_id, type + MATCH_TIME);
    }
}

jobject fill_rule(JNIEnv *env, const struct ipt_entry *entry, struct iptc_handle *handle, char *table, const char *chain, int num)
{
    jclass rule_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Rule");   
    jclass addr_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Address");
    jclass match_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Match");
    jclass target_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Target");

    jmethodID rule_new_id = (*env)->GetMethodID(env, rule_cls, "<init>", "()V");
    jmethodID rule_getId_id = (*env)->GetMethodID(env, rule_cls, "getId", "()I");
    jmethodID rule_setTable_id = (*env)->GetMethodID(env, rule_cls, "setTable", "(Ljava/lang/String;)V");
    jmethodID rule_setChain_id = (*env)->GetMethodID(env, rule_cls, "setChain", "(Ljava/lang/String;)V");
    jmethodID rule_setNum_id = (*env)->GetMethodID(env, rule_cls, "setNum", "(I)V");
    jmethodID rule_setIn_id = (*env)->GetMethodID(env, rule_cls, "setInInterface", "(Ljava/lang/String;)V");
    jmethodID rule_setOut_id = (*env)->GetMethodID(env, rule_cls, "setOutInterface", "(Ljava/lang/String;)V");
    jmethodID rule_setProto_id = (*env)->GetMethodID(env, rule_cls, "setProto", "(I)V");
    jmethodID rule_setSrc_id = (*env)->GetMethodID(env, rule_cls, "setSourceAddr", "(Lorg/linux/lib/netfilter/Address;)V");
    jmethodID rule_setDst_id = (*env)->GetMethodID(env, rule_cls, "setDestAddr", "(Lorg/linux/lib/netfilter/Address;)V");
    jmethodID rule_setMatch_id = (*env)->GetMethodID(env, rule_cls, "setMatch", "(Lorg/linux/lib/netfilter/Match;)V");
    jmethodID rule_setTarget_id = (*env)->GetMethodID(env, rule_cls, "setTarget", "(Lorg/linux/lib/netfilter/Target;)V");
    jmethodID addr_new_id = (*env)->GetMethodID(env, addr_cls, "<init>", "()V");
    jmethodID addr_setPort_id = (*env)->GetMethodID(env, addr_cls, "setPort", "(I)V");
    jmethodID addr_setIp_id = (*env)->GetMethodID(env, addr_cls, "setIp", "(Ljava/lang/String;)V");
    jmethodID match_new_id = (*env)->GetMethodID(env, match_cls, "<init>", "()V");
    jmethodID match_setType_id = (*env)->GetMethodID(env, match_cls, "setType", "(I)V");
    jmethodID target_new_id = (*env)->GetMethodID(env, target_cls, "<init>", "()V");
    jmethodID target_setName_id = (*env)->GetMethodID(env, target_cls, "setName", "(Ljava/lang/String;)V");
    jmethodID target_setAddr_id = (*env)->GetMethodID(env, target_cls, "setAddr", "(Lorg/linux/lib/netfilter/Address;)V");

    jobject rule = (*env)->NewObject(env, rule_cls, rule_new_id);

    //fill rule basic info
    (*env)->CallObjectMethod(env, rule, rule_setTable_id, (*env)->NewStringUTF(env, table));
    (*env)->CallObjectMethod(env, rule, rule_setChain_id, (*env)->NewStringUTF(env, chain));
    (*env)->CallObjectMethod(env, rule, rule_setNum_id, num);
    (*env)->CallObjectMethod(env, rule, rule_setIn_id, (*env)->NewStringUTF(env, entry->ip.iniface));
    (*env)->CallObjectMethod(env, rule, rule_setOut_id, (*env)->NewStringUTF(env, entry->ip.outiface));
    (*env)->CallObjectMethod(env, rule, rule_setProto_id, entry->ip.proto);

    //fill rule.src and rule.dst
    jobject addr_src = NULL;
    jobject addr_dst = NULL;

    const struct in_addr *src = (struct in_addr*)&entry->ip.src;
    const struct in_addr *dst = (struct in_addr*)&entry->ip.dst;

    char src_ip[16];
    char dst_ip[16];
    inet_ntop(AF_INET, src, src_ip, sizeof(src_ip));
    inet_ntop(AF_INET, dst, dst_ip, sizeof(dst_ip));

    if(strcmp("0.0.0.0", src_ip) != 0)
    {
        addr_src = (*env)->NewObject(env, addr_cls, addr_new_id);
        (*env)->CallObjectMethod(env, addr_src, addr_setIp_id, (*env)->NewStringUTF(env, src_ip));
    }

    if(strcmp("0.0.0.0", dst_ip) != 0)
    {
        addr_dst = (*env)->NewObject(env, addr_cls, addr_new_id);
        (*env)->CallObjectMethod(env, addr_dst, addr_setIp_id, (*env)->NewStringUTF(env, dst_ip));
    }

    (*env)->CallObjectMethod(env, rule, rule_setSrc_id, addr_src);
    (*env)->CallObjectMethod(env, rule, rule_setDst_id, addr_dst);

    //fill rule.match
    size_t match_size = entry->target_offset - sizeof(struct ipt_entry);

    #ifdef DEBUG
    if(DEBUG == D_DEBUG)
    {
        printf("match_size:%d\n", match_size);
    }
    #endif

    jobject j_match = NULL;
    if(match_size > 0)
    {
        j_match = (*env)->NewObject(env, match_cls, match_new_id);

        struct ipt_entry_match *match;
        int next = 0;
        match = (struct ipt_entry_match*)entry->elems;

        while(match)
        {
            #ifdef DEBUG
            if(DEBUG == D_DEBUG)
            {
                printf("match size :%d, name : %s\n", match->u.user.match_size, match->u.user.name);
            }
            #endif

            fill_rule_match(env, j_match, match);
            if((next = match_size - match->u.user.match_size) > 0)
            {
                match = (struct ipt_entry_match*)(entry->elems + match->u.user.match_size);
            }
            else
            {
                match = NULL;
            }
        }
    }
    (*env)->CallObjectMethod(env, rule, rule_setMatch_id, j_match);

    //fill rule.target
    jobject j_target = (*env)->NewObject(env, target_cls, target_new_id);

    const char *target_name = iptc_get_target(entry, handle);
    (*env)->CallObjectMethod(env, j_target, target_setName_id, (*env)->NewStringUTF(env, target_name));

    if(strcmp(target_name, "SNAT") == 0 || strcmp(target_name, "DNAT") == 0)
    {
        jobject target_addr = (*env)->NewObject(env, addr_cls, addr_new_id);
        struct ipt_entry_target *target = (struct ipt_entry_target*)(entry->elems + match_size);
        struct nf_nat_multi_range *mr = (struct nf_nat_multi_range*)target->data;

        if(mr->range[0].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
        {
            (*env)->CallObjectMethod(env, target_addr, addr_setPort_id, ntohs(mr->range[0].max.tcp.port));
        }
        else
        {
            (*env)->CallObjectMethod(env, target_addr, addr_setPort_id, -1);
        }

        if(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
        {
            struct in_addr addr_in;

            memset(&addr_in, 0, sizeof(addr_in));

            addr_in.s_addr = mr->range[0].max_ip;

            char addr[16];
            inet_ntop(AF_INET, &addr_in, addr, 16);

            if(addr != NULL && strcmp(addr, "") != 0)
            {
                (*env)->CallObjectMethod(env, target_addr, addr_setIp_id, (*env)->NewStringUTF(env, addr));
            }
        }

        (*env)->CallObjectMethod(env, j_target, target_setAddr_id, target_addr);
    }

    (*env)->CallObjectMethod(env, rule, rule_setTarget_id, j_target);

    return rule;
}

JNIEXPORT jobject JNICALL Java_org_linux_lib_netfilter_Filter_getRules(JNIEnv *env, jobject obj)
{
    struct iptc_handle *handle;
    const struct ipt_entry *entry;
    const char *chain;
    int i;
    int j;
    int len = sizeof(tables) / sizeof(tables[0]);

    jclass list_cls = (*env)->FindClass(env, "java/util/ArrayList");
    jmethodID list_new_id = (*env)->GetMethodID(env, list_cls, "<init>", "()V");
    jmethodID list_add_id = (*env)->GetMethodID(env, list_cls, "add", "(Ljava/lang/Object;)Z");
    jobject list = (*env)->NewObject(env, list_cls, list_new_id);

    for(i = 0; i < len; i++)
    {
        if((handle = iptc_init(tables[i])) == NULL)
        {
            perror("fail to iptc_init");

            goto end;
        }

        for(chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle))
        {
            for(entry = iptc_first_rule(chain, handle), j = 0; entry; entry = iptc_next_rule(entry, handle), j++)
            {
                (*env)->CallObjectMethod(env, list, list_add_id, fill_rule(env, entry, handle, tables[i], chain, j));
            }
        }
    }

    end:
    (*env)->DeleteLocalRef(env, list_cls);

    return list;
}

int parseRule(JNIEnv *env, const struct RULE **rule, const char **table, const char **chain, jobject j_rule, int *num)
{
    int rv = 1;
    const char *src_ip;
    const char *dst_ip;
    const char *table_name;
    const char *chain_name;
    const char *target_name;
    struct RULE * entry;
    int match_type;
    struct ipt_entry_target *target;
    size_t target_size;
    size_t entry_size;
    size_t match_size = 0;

    jclass rule_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Rule");   
    jclass target_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Target");
    jclass address_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Address");
    jclass match_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Match");

    jmethodID rule_new_id = (*env)->GetMethodID(env, rule_cls, "<init>", "()V");
    jmethodID rule_getTable_id = (*env)->GetMethodID(env, rule_cls, "getTable", "()Ljava/lang/String;");
    jmethodID rule_getChain_id = (*env)->GetMethodID(env, rule_cls, "getChain", "()Ljava/lang/String;");
    jmethodID rule_getNum_id = (*env)->GetMethodID(env, rule_cls, "getNum", "()I");
    jmethodID rule_getTarget_id = (*env)->GetMethodID(env, rule_cls, "getTarget", "()Lorg/linux/lib/netfilter/Target;");
    jmethodID rule_getSourceAddr_id = (*env)->GetMethodID(env, rule_cls, "getSourceAddr", "()Lorg/linux/lib/netfilter/Address;");
    jmethodID rule_getDestAddr_id = (*env)->GetMethodID(env, rule_cls, "getDestAddr", "()Lorg/linux/lib/netfilter/Address;");
    jmethodID rule_getMatch_id = (*env)->GetMethodID(env, rule_cls, "getMatch", "()Lorg/linux/lib/netfilter/Match;");
    jmethodID rule_getProto_id = (*env)->GetMethodID(env, rule_cls, "getProto", "()I");
    jmethodID target_getName_id = (*env)->GetMethodID(env, target_cls, "getName", "()Ljava/lang/String;");
    jmethodID target_getAddr_id = (*env)->GetMethodID(env, target_cls, "getAddr", "()Lorg/linux/lib/netfilter/Address;");
    jmethodID address_getIp_id = (*env)->GetMethodID(env, address_cls, "getIp", "()Ljava/lang/String;");
    jmethodID address_getPort_id = (*env)->GetMethodID(env, address_cls, "getPort", "()I");
    jmethodID match_getSport_id = (*env)->GetMethodID(env, match_cls, "getSport", "()I");
    jmethodID match_getDport_id = (*env)->GetMethodID(env, match_cls, "getDport", "()I");
    jmethodID match_getType_id = (*env)->GetMethodID(env, match_cls, "getType", "()I");
    jmethodID match_getTimeStart_id  = (*env)->GetMethodID(env, match_cls, "getTimeStart", "()Ljava/lang/String;");
    jmethodID match_getTimeStop_id = (*env)->GetMethodID(env, match_cls, "getTimeStop", "()Ljava/lang/String;");

    jobject j_target = (*env)->CallObjectMethod(env, j_rule, rule_getTarget_id);
    jobject j_addr_src = (*env)->CallObjectMethod(env, j_rule, rule_getSourceAddr_id);
    jobject j_addr_dest = (*env)->CallObjectMethod(env, j_rule, rule_getDestAddr_id);
    jobject j_match = (*env)->CallObjectMethod(env, j_rule, rule_getMatch_id);

    table_name = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, j_rule, rule_getTable_id), 0);
    *table = table_name;

    chain_name = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, j_rule, rule_getChain_id), 0);
    *chain = chain_name;

    int proto = (*env)->CallObjectMethod(env, j_rule, rule_getProto_id);

    if(num != NULL)
    {
        *num = (*env)->CallObjectMethod(env, j_rule, rule_getNum_id);

        #ifdef DEBUG
        if(DEBUG == D_DEBUG)
        {
            printf("num is set.\n");
        }
        #endif
    }

    jstring j_src_ip = j_addr_src == NULL ? NULL : (*env)->CallObjectMethod(env, j_addr_src, address_getIp_id);
    if(j_src_ip != NULL)
    {
        src_ip = (*env)->GetStringUTFChars(env, j_src_ip, 0);

        (*env)->DeleteLocalRef(env, j_src_ip);
    }
    else
    {
        src_ip = NULL;
    }
    int src_port = j_addr_src == NULL ? NULL : (*env)->CallObjectMethod(env, j_addr_src, address_getPort_id);

    jstring j_dst_ip = j_addr_dest == NULL ? NULL : (*env)->CallObjectMethod(env, j_addr_dest, address_getIp_id);
    if(j_dst_ip != NULL)
    {
        dst_ip = (*env)->GetStringUTFChars(env, j_dst_ip, 0);

        (*env)->DeleteLocalRef(env, j_dst_ip);
    }
    else
    {
        dst_ip = NULL;
    }
    int dst_port = j_addr_dest == NULL ? NULL : (*env)->CallObjectMethod(env, j_addr_dest, address_getPort_id);

    target_name = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, j_target, target_getName_id), 0);

    if(j_match)
    {
        match_type = (*env)->CallObjectMethod(env, j_match, match_getType_id);

        if(match_type & MATCH_TCP)
        {
            match_size += (sizeof(struct ipt_tcp) + sizeof(struct ipt_entry_match));
        }

        if(!(match_type & MATCH_TCP) && match_type & MATCH_UDP)
        {
            match_size += (sizeof(struct ipt_udp) + sizeof(struct ipt_entry_match));
        }

        if(match_type & MATCH_TIME)
        {
            match_size += (sizeof(struct ipt_time) + sizeof(struct ipt_entry_match));
        }

        if(match_type & MATCH_LIMIT)
        {
        }

        match_size = IPT_ALIGN(match_size);
    }

    if(strcmp(target_name, "DNAT") == 0 || strcmp(target_name, "SNAT") == 0)
    {
        target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)) + IPT_ALIGN(sizeof(struct nf_nat_multi_range));
    }
    else
    {
        target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int));
    }

    #ifndef X64
    target_size -= IPT_ALIGN(sizeof(int));
    #endif

    entry_size = sizeof(struct ipt_entry) + match_size + target_size;

    entry = calloc(1, entry_size);
    entry->target_offset = sizeof(struct ipt_entry) + match_size;
    entry->next_offset = entry_size;

    if(src_ip)
    {
        inet_aton(src_ip, &(entry->ip.src));
        entry->ip.smsk.s_addr = -1;
    }

    if(dst_ip)
    {
        inet_aton(dst_ip, &(entry->ip.dst));
        entry->ip.dmsk.s_addr = -1;
    }

    if(proto == IPPROTO_TCP || proto == IPPROTO_UDP)
    {
        entry->ip.proto = proto;
    }

    if(j_match)
    {
        int inc = 0;

        if(match_type & MATCH_TCP)
        {
            struct ipt_entry_match *match = (struct ipt_entry_match*)(entry->elems + inc);
            match->u.user.match_size = IPT_ALIGN(sizeof(struct ipt_tcp) + sizeof(struct ipt_entry_match));
            inc += match->u.user.match_size;
            strcpy(match->u.user.name, "tcp");

            struct ipt_tcp *m_tcp = (struct ipt_tcp*)match->data;

            int sport = (*env)->CallObjectMethod(env, j_match, match_getSport_id);
            int dport = (*env)->CallObjectMethod(env, j_match, match_getDport_id);

            if(sport < MIN_PORT || sport > MAX_PORT)
            {
                m_tcp->spts[0] = MIN_PORT;
                m_tcp->spts[1] = MAX_PORT;
            }
            else
            {
                m_tcp->spts[0] = sport;
                m_tcp->spts[1] = sport;
            }

            if(dport < MIN_PORT || dport > MAX_PORT)
            {
                m_tcp->dpts[0] = MIN_PORT;
                m_tcp->dpts[1] = MAX_PORT;
            }
            else
            {
                m_tcp->dpts[0] = dport;
                m_tcp->dpts[1] = dport;
            }
        }

        if(!(match_type & MATCH_TCP) && match_type & MATCH_UDP)
        {
            struct ipt_entry_match *match = (struct ipt_entry_match*)(entry->elems + inc);
            match->u.user.match_size = IPT_ALIGN(sizeof(struct ipt_udp) + sizeof(struct ipt_entry_match));
            inc += match->u.user.match_size;
            strcpy(match->u.user.name, "udp");

            struct ipt_udp *m_udp = (struct ipt_tcp*)match->data;

            int sport = (*env)->CallObjectMethod(env, j_match, match_getSport_id);
            int dport = (*env)->CallObjectMethod(env, j_match, match_getDport_id);

            if(sport < MIN_PORT || sport > MAX_PORT)
            {
                m_udp->spts[0] = MIN_PORT;
                m_udp->spts[1] = MAX_PORT;
            }
            else
            {
                m_udp->spts[0] = sport;
                m_udp->spts[1] = sport;
            }

            if(dport < MIN_PORT || dport > MAX_PORT)
            {
                m_udp->dpts[0] = MIN_PORT;
                m_udp->dpts[1] = MAX_PORT;
            }
            else
            {
                m_udp->dpts[0] = dport;
                m_udp->dpts[1] = dport;
            }
        }

        if(match_type & MATCH_TIME)
        {
            struct ipt_entry_match *match = (struct ipt_entry_match*)(entry->elems + inc);
            match->u.user.match_size = IPT_ALIGN(sizeof(struct ipt_time) + sizeof(struct ipt_entry_match));
            inc += match->u.user.match_size;
            strcpy(match->u.user.name, "time");

            const char *t_start;
            const char *t_stop;
            jstring j_t_start;
            jstring j_t_stop;
            struct ipt_time *m_time = (struct ipt_time*)(match->data);

            j_t_start = (*env)->CallObjectMethod(env, j_match, match_getTimeStart_id);
            j_t_stop = (*env)->CallObjectMethod(env, j_match, match_getTimeStop_id);

            t_start = j_t_start ? (*env)->GetStringUTFChars(env, j_t_start, 0) : NULL;
            t_stop = j_t_stop ? (*env)->GetStringUTFChars(env, j_t_stop, 0) : NULL;

            m_time->monthdays_match    = XT_TIME_ALL_MONTHDAYS;
            m_time->weekdays_match    = XT_TIME_ALL_WEEKDAYS;
            m_time->daytime_start    = XT_TIME_MIN_DAYTIME;
            m_time->daytime_stop    = XT_TIME_MAX_DAYTIME;
            m_time->date_start    = 0;
            m_time->date_stop    = INT_MAX;
            m_time->flags        |=XT_TIME_LOOCAL_TZ;

            if(t_start)
            {
                m_time->daytime_start = time_parse_minutes(t_start);
                m_time->flags |= F_TIME_START;

                (*env)->ReleaseStringUTFChars(env, j_t_start, t_start);
                (*env)->DeleteLocalRef(env, j_t_start);
            }

            if(t_stop)
            {
                m_time->daytime_stop = time_parse_minutes(t_stop);
                m_time->flags |= F_TIME_STOP;

                (*env)->ReleaseStringUTFChars(env, j_t_stop, t_stop);
                (*env)->DeleteLocalRef(env, j_t_stop);
            }
        }

        if(match_type & MATCH_LIMIT)
        {
        }
    }

    target = (struct ipt_entry_target*)(entry->elems + match_size);
    target->u.target_size = target_size;
    strcpy(target->u.user.name, target_name);

    if(strcmp(target_name, "DNAT") == 0 || strcmp(target_name, "SNAT") == 0)
    {
        jobject addr = (*env)->CallObjectMethod(env, j_target, target_getAddr_id);

        if(addr == NULL)
        {
            rv = -2;
            goto end;
        }

        const char *ip = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, addr, address_getIp_id), 0);
        int port = (*env)->CallObjectMethod(env, addr, address_getPort_id);

        (*env)->DeleteLocalRef(env, addr);
        struct in_addr addr_in;

        inet_pton(AF_INET, ip, &addr_in);

        struct nf_nat_multi_range *mr = (struct nf_nat_multi_range*)target->data;

        if(port != -1)
        {
            mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
            mr->range[0].max.tcp.port = htons(port);
            mr->range[0].min.tcp.port = htons(port);
        }

        mr->range[0].flags |= IP_NAT_RANGE_MAP_IPS;
        mr->range[0].max_ip = addr_in.s_addr;
        mr->range[0].min_ip = addr_in.s_addr;

        mr->rangesize++;
    }

    *rule = entry;

    end:

    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_appendRule(JNIEnv *env, jobject obj, jobject j_rule)
{
    int rv = 1;

    jclass rule_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Rule");   
    jmethodID rule_genAppend_id = (*env)->GetMethodID(env, rule_cls, "genAppend", "()Ljava/lang/String;");
    jmethodID rule_getId_id = (*env)->GetMethodID(env, rule_cls, "getId", "()I");
    jmethodID rule_toString_id = (*env)->GetMethodID(env, rule_cls, "toString", "()Ljava/lang/String;");

    #ifndef SHELL
    struct iptc_handle *handle;
    const struct RULE *entry;
    const char *table;
    const char *chain;

    parseRule(env, &entry, &table, &chain, j_rule, NULL);

    handle = iptc_init(table);

    if((rv = iptc_append_entry(chain, entry, handle)) != 1)
    {
        perror("fail to append entry");
        goto end;
    }

    if((rv = iptc_commit(handle)) != 1)
    {
        perror("fail to commit");
        goto end;
    }
    #else
    char *cmd = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, j_rule, rule_genAppend_id), 0);
    system(cmd);
    #endif

    rv = (*env)->CallObjectMethod(env, j_rule, rule_getId_id);

    #ifdef DEBUG
    if(DEBUG == D_DEBUG)
    {
        printf("rule_id : %d\n", rv);
    }
    #endif

    end:

    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_replaceRule(JNIEnv *env, jobject obj, jobject j_rule)
{
    int rv = 1;
    struct iptc_handle *handle;
    const struct RULE *entry;
    const char *table;
    const char *chain;
    int num;

    parseRule(env, &entry, &table, &chain, j_rule, &num);

    handle = iptc_init(table);

    if((rv = iptc_replace_entry(chain, entry, num, handle)) != 1)
    {
        perror("fail to append entry");
        goto end;
    }

    if((rv = iptc_commit(handle)) != 1)
    {
        perror("fail to commit");
        goto end;
    }


    jclass rule_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Rule");   
    jmethodID rule_getId_id = (*env)->GetMethodID(env, rule_cls, "getId", "()I");
    jmethodID rule_toString_id = (*env)->GetMethodID(env, rule_cls, "toString", "()Ljava/lang/String;");

    rv = (*env)->CallObjectMethod(env, j_rule, rule_getId_id);

    end:

    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_insertRule(JNIEnv *env, jobject obj, jobject j_rule)
{
    int rv = 1;
    struct iptc_handle *handle;
    const struct RULE *entry;
    const char *table;
    const char *chain;
    int num;

    parseRule(env, &entry, &table, &chain, j_rule, &num);

    #ifdef DEBUG
    if(DEBUG == D_DEBUG)
    {
        printf("parse result: table - %s, chain - %s, num - %d\n", table, chain, num);
    }
    #endif

    handle = iptc_init(table);

    if((rv = iptc_insert_entry(chain, entry, num, handle)) != 1)
    {
        perror("fail to append entry");
        goto end;
    }

    if((rv = iptc_commit(handle)) != 1)
    {
        perror("fail to commit");
        goto end;
    }

    jclass rule_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Rule");   
    jmethodID rule_getId_id = (*env)->GetMethodID(env, rule_cls, "getId", "()I");
    jmethodID rule_toString_id = (*env)->GetMethodID(env, rule_cls, "toString", "()Ljava/lang/String;");

    rv = (*env)->CallObjectMethod(env, j_rule, rule_getId_id);

    end:

    return rv;
}

int clean_f_tab(char *tab)
{
    int rv = 1;
    struct iptc_handle *handle;
    const char *chain;

    if((handle = iptc_init(tab)) == NULL)
    {
        perror("fail to init");
        rv = -1;
        goto end;
    }

    for(chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle))
    {
        iptc_flush_entries(chain, handle);   
    }

    iptc_commit(handle);

    end:

    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_cleanRules__(JNIEnv *env, jobject obj)
{
    int rv = 1;
    int tab_size, i;

    tab_size = sizeof(tables) / sizeof(tables[0]);

    for(i = 0; i < tab_size; i++)
    {
        if((rv = clean_f_tab(tables[i])) != 1)
        {
            break;
        }
    }

    end:
    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_cleanRules__Ljava_lang_String_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring j_table, jstring j_chain)
{
    int rv = 1;
    struct iptc_handle *handle;
    const char *table = (*env)->GetStringUTFChars(env, j_table, 0);
    const char *chain = (*env)->GetStringUTFChars(env, j_chain, 0);

    if((handle = iptc_init(table)) == NULL)
    {
        perror("fail to init");

        rv = -1;

        goto end;
    }

    if((rv = iptc_flush_entries(chain, handle)) != 1)
    {
        perror("fail to flush");

        goto end;
    }

    if((rv = iptc_commit(handle)) != 1)
    {
        perror("fail to commit");

        goto end;
    }

    end:

    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_delRule__Ljava_lang_String_2Ljava_lang_String_2I(JNIEnv *env, jobject obj, jstring j_table, jstring j_chain, jint num)
{
    int rv = 1;
    struct iptc_handle *handle;
    const char *table = (*env)->GetStringUTFChars(env, j_table, 0);
    const char *chain = (*env)->GetStringUTFChars(env, j_chain, 0);

    #ifdef DEBUG
    if(DEBUG == D_DEBUG)
    {
        printf("del_rule.\n");
        printf("table:%s, chain:%s, num:%d\n", table, chain, num);
    }
    #endif

    if((handle = iptc_init(table)) == NULL)
    {
        perror("fail to init");

        rv = -1;

        goto end;
    }

    if((rv = iptc_delete_num_entry(chain, num, handle)) != 1)
    {
        perror("fail to del_num");

        goto end;
    }

    if((rv = iptc_commit(handle)) != 1)
    {
        perror("fail to commit");

        goto end;
    }

    end:

    return rv;
}

JNIEXPORT jint JNICALL Java_org_linux_lib_netfilter_Filter_delRule__I(JNIEnv *env, jobject obj, jint id)
{
    int rv = 1;
    int size_list = 0;
    int i;

    jclass list_cls = (*env)->FindClass(env, "java/util/ArrayList");
    jclass rule_cls = (*env)->FindClass(env, "org/linux/lib/netfilter/Rule");
    jmethodID list_size_id = (*env)->GetMethodID(env, list_cls, "size", "()I");
    jmethodID list_get_id = (*env)->GetMethodID(env, list_cls, "get", "(I)Ljava/lang/Object;");
    jmethodID rule_getId_id = (*env)->GetMethodID(env, rule_cls, "getId", "()I");
    jmethodID rule_getTable_id = (*env)->GetMethodID(env, rule_cls, "getTable", "()Ljava/lang/String;");
    jmethodID rule_getChain_id = (*env)->GetMethodID(env, rule_cls, "getChain", "()Ljava/lang/String;");
    jmethodID rule_getNum_id = (*env)->GetMethodID(env, rule_cls, "getNum", "()I");

    #ifndef SHELL
    jobject j_list = Java_org_linux_lib_netfilter_Filter_getRules(env, obj);

    size_list = (*env)->CallObjectMethod(env, j_list, list_size_id);

    for(i = 0; i < size_list; i++)
    {
        jobject j_rule = (*env)->CallObjectMethod(env, j_list, list_get_id, i);
        int id_l = (*env)->CallObjectMethod(env, j_rule, rule_getId_id);

        if(id == id_l)
        {
            struct iptc_handle *handle;
            char *table;
            char *chain;
            int num = (*env)->CallObjectMethod(env, j_rule, rule_getNum_id);

            table = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, j_rule, rule_getTable_id), 0);
            chain = (*env)->GetStringUTFChars(env, (*env)->CallObjectMethod(env, j_rule, rule_getChain_id), 0);


            handle = iptc_init(table);
            rv = iptc_delete_num_entry(chain, num, handle);
            rv = iptc_commit(handle);
        }
    }
    #else
    system("iptables --table nat --flush");
    #endif

    end:

    return rv;
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有