209 lines
6.0 KiB
C
209 lines
6.0 KiB
C
|
#include "libiptc.h"
|
||
|
|
||
|
|
||
|
int x_get_rule(const char *chain, struct xtc_handle *handle, char *ipv4)
|
||
|
{
|
||
|
int r=1;
|
||
|
const struct ipt_entry *entry;
|
||
|
|
||
|
for (entry = iptc_first_rule(chain, handle); entry; entry = iptc_next_rule(entry, handle)) {
|
||
|
iptc_get_target(entry, handle);
|
||
|
|
||
|
char addr[33];
|
||
|
memset(addr, 0, 33);
|
||
|
inet_ntop(AF_INET, &(entry->ip.dst), addr, sizeof(addr));
|
||
|
printf("%s\n", addr);
|
||
|
if (0 == strcmp(ipv4, addr))
|
||
|
{
|
||
|
r=0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
|
||
|
}
|
||
|
|
||
|
int show_all_rule(char *ipv4)
|
||
|
{
|
||
|
int r;
|
||
|
struct xtc_handle *handle;
|
||
|
const char *chain = NULL;
|
||
|
struct ipt_counters counter;
|
||
|
|
||
|
handle = iptc_init("filter");
|
||
|
|
||
|
for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle))
|
||
|
{
|
||
|
if (chain != NULL && handle != NULL) {
|
||
|
iptc_get_policy(chain, &counter, handle);
|
||
|
}
|
||
|
|
||
|
r = x_get_rule(chain, handle, ipv4);
|
||
|
if (r==0){
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
static u_int16_t parse_port(const char *port)
|
||
|
{
|
||
|
return atoi(port);
|
||
|
}
|
||
|
|
||
|
static void parse_ports(const char *portstring, u_int16_t * ports)
|
||
|
{
|
||
|
char *buffer;
|
||
|
char *cp;
|
||
|
|
||
|
buffer = strdup(portstring);
|
||
|
if ((cp = strchr(buffer, ':')) == NULL)
|
||
|
ports[0] = ports[1] = parse_port(buffer);
|
||
|
else {
|
||
|
*cp = '\0';
|
||
|
cp++;
|
||
|
|
||
|
ports[0] = buffer[0] ? parse_port(buffer) : 0;
|
||
|
ports[1] = cp[0] ? parse_port(cp) : 0xFFFF;
|
||
|
}
|
||
|
free(buffer);
|
||
|
}
|
||
|
|
||
|
struct ipt_entry_match *get_match(const char *sports, const char *dports, unsigned int *nfcache, char *protocol)
|
||
|
{
|
||
|
struct ipt_entry_match *match;
|
||
|
struct ipt_udp *udpinfo;
|
||
|
size_t size;
|
||
|
|
||
|
size = IPT_ALIGN(sizeof(*match)) + IPT_ALIGN(sizeof(*udpinfo));
|
||
|
match = (struct ipt_entry_match *)calloc(1, size);
|
||
|
match->u.match_size = size;
|
||
|
strncpy(match->u.user.name, protocol, IPT_FUNCTION_MAXNAMELEN);
|
||
|
|
||
|
udpinfo = (struct ipt_udp *)match->data;
|
||
|
udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
|
||
|
//printf("sports=%s,dports=%s\n", sports, dports);
|
||
|
if (sports) {
|
||
|
*nfcache |= NFC_IP_SRC_PT;
|
||
|
parse_ports(sports, udpinfo->spts);
|
||
|
}
|
||
|
if (dports) {
|
||
|
*nfcache |= NFC_IP_DST_PT;
|
||
|
parse_ports(dports, udpinfo->dpts);
|
||
|
}
|
||
|
|
||
|
return match;
|
||
|
}
|
||
|
|
||
|
int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src,
|
||
|
unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append)
|
||
|
{
|
||
|
struct xtc_handle *handle;
|
||
|
struct ipt_entry *chain_entry;
|
||
|
struct ipt_entry_match *entry_match = NULL;
|
||
|
struct ipt_entry_target *entry_target;
|
||
|
ipt_chainlabel labelit;
|
||
|
long match_size;
|
||
|
int result = 0;
|
||
|
|
||
|
chain_entry = (struct ipt_entry *)calloc(1, sizeof(*chain_entry));
|
||
|
|
||
|
if (src != 0) {
|
||
|
chain_entry->ip.src.s_addr = src;
|
||
|
chain_entry->ip.smsk.s_addr = 0xFFFFFFFF;
|
||
|
}
|
||
|
if (dest != 0) {
|
||
|
chain_entry->ip.dst.s_addr = dest;
|
||
|
chain_entry->ip.dmsk.s_addr = 0xFFFFFFFF;
|
||
|
}
|
||
|
|
||
|
if (iniface)
|
||
|
strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ);
|
||
|
if (outiface)
|
||
|
strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ);
|
||
|
|
||
|
chain_entry->ip.proto = protocol;
|
||
|
if (IPPROTO_UDP == protocol)
|
||
|
entry_match = get_match(srcports, destports, &chain_entry->nfcache, "udp");
|
||
|
if (IPPROTO_TCP == protocol)
|
||
|
entry_match = get_match(srcports, destports, &chain_entry->nfcache, "tcp");
|
||
|
|
||
|
if (strcmp(target, "") == 0 || strcmp(target, IPTC_LABEL_ACCEPT) == 0 || strcmp(target, IPTC_LABEL_DROP) == 0 || strcmp(target, IPTC_LABEL_QUEUE) == 0 || strcmp(target, IPTC_LABEL_RETURN) == 0) {
|
||
|
size_t size;
|
||
|
size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int));
|
||
|
entry_target = (struct ipt_entry_target *)calloc(1, size);
|
||
|
entry_target->u.user.target_size = size;
|
||
|
strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN);
|
||
|
}
|
||
|
if (entry_match) {
|
||
|
match_size = entry_match->u.match_size;
|
||
|
} else
|
||
|
match_size = 0;
|
||
|
|
||
|
struct ipt_entry *tmp_ipt = chain_entry;
|
||
|
chain_entry = (struct ipt_entry *)realloc(chain_entry, sizeof(*chain_entry) + match_size + entry_target->u.target_size);
|
||
|
if (chain_entry == NULL) {
|
||
|
free(tmp_ipt);
|
||
|
}
|
||
|
|
||
|
memcpy(chain_entry->elems + match_size, entry_target, entry_target->u.target_size);
|
||
|
chain_entry->target_offset = sizeof(*chain_entry) + match_size;
|
||
|
chain_entry->next_offset = sizeof(*chain_entry) + match_size + entry_target->u.target_size;
|
||
|
if (entry_match) {
|
||
|
memcpy(chain_entry->elems, entry_match, match_size);
|
||
|
}
|
||
|
|
||
|
handle = iptc_init(table);
|
||
|
if (!handle) {
|
||
|
printf("libiptc error: Can't initialize table %s, %s\n", table, iptc_strerror(errno));
|
||
|
free(chain_entry);
|
||
|
free(entry_target);
|
||
|
if (entry_match)
|
||
|
free(entry_match);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
strncpy(labelit, chain, sizeof(ipt_chainlabel));
|
||
|
//printf("Chain name:%s\n", chain);
|
||
|
result = iptc_is_chain(chain, handle);
|
||
|
if (!result) {
|
||
|
printf("libiptc error: Chain %s does not exist!\n", chain);
|
||
|
free(chain_entry);
|
||
|
free(entry_target);
|
||
|
if (entry_match)
|
||
|
free(entry_match);
|
||
|
return 1;
|
||
|
}
|
||
|
if (append)
|
||
|
result = iptc_append_entry(labelit, chain_entry, handle);
|
||
|
else
|
||
|
result = iptc_insert_entry(labelit, chain_entry, 0, handle);
|
||
|
if (!result) {
|
||
|
printf("libiptc error: Can't add, %s\n", iptc_strerror(errno));
|
||
|
free(chain_entry);
|
||
|
free(entry_target);
|
||
|
if (entry_match)
|
||
|
free(entry_match);
|
||
|
return 1;
|
||
|
}
|
||
|
result = iptc_commit(handle);
|
||
|
if (!result) {
|
||
|
printf("libiptc error: Commit error, %s\n", iptc_strerror(errno));
|
||
|
free(chain_entry);
|
||
|
free(entry_target);
|
||
|
if (entry_match)
|
||
|
free(entry_match);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (entry_match)
|
||
|
free(entry_match);
|
||
|
free(entry_target);
|
||
|
free(chain_entry);
|
||
|
|
||
|
return 0;
|
||
|
}
|