denyhosts/libiptc.c

224 lines
6.5 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;
struct ipt_entry_match *entry_match;
for (entry = iptc_first_rule(chain, handle); entry; entry = iptc_next_rule(entry, handle)) {
const char *t = iptc_get_target(entry, handle);
entry_match = (struct ipt_entry_match *)entry->elems;
//printf("u.user.name: %s\n", entry_match->u.user.name);
char addr[64];
memset(addr, 0, 64);
inet_ntop(AF_INET, &(entry->ip.src), addr, sizeof(addr));
//printf("%s\n", addr);
//printf("%s\n", t);
if (0 == strcmp(ipv4, addr) && 0 == strcmp(t, "DROP") && 0 == strcmp(entry_match->u.user.name, "tcp")) {
r = 0;
break;
}
}
return r;
}
int show_all_rule(char *ipv4)
{
int r = 0;
struct xtc_handle *handle;
const char *chain = NULL;
struct ipt_counters counter;
handle = iptc_init("filter");
if ( !handle ) {
printf("Error initializing: %s\n", iptc_strerror(errno));
exit(errno);
}
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;
}
}
iptc_free(handle);
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 - 2);
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 = NULL;
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, XT_EXTENSION_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);
iptc_free(handle);
return 0;
}