/* add_filter_rule() * */ static int add_filter_rule(int proto, const char * rhost, const char * iaddr, unsigned short iport) { int r = 0; struct ipt_entry * e; struct ipt_entry * tmp; struct ipt_entry_match *match = NULL; struct ipt_entry_target *target = NULL; e = calloc(1, sizeof(struct ipt_entry)); if(!e) { syslog(LOG_ERR, "%s: calloc(%d) error", "add_filter_rule", (int)sizeof(struct ipt_entry)); return -1; } e->ip.proto = proto; if(proto == IPPROTO_TCP) { match = get_tcp_match(iport,0); } else { match = get_udp_match(iport,0); } e->nfcache = NFC_IP_DST_PT; e->ip.dst.s_addr = inet_addr(iaddr); e->ip.dmsk.s_addr = INADDR_NONE; target = get_accept_target(); e->nfcache |= NFC_UNKNOWN; tmp = realloc(e, sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size); if(!tmp) { syslog(LOG_ERR, "%s: realloc(%d) error", "add_filter_rule", (int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size)); free(e); free(match); free(target); return -1; } e = tmp; memcpy(e->elems, match, match->u.match_size); memcpy(e->elems + match->u.match_size, target, target->u.target_size); e->target_offset = sizeof(struct ipt_entry) + match->u.match_size; e->next_offset = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; /* remote host */ if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) { e->ip.src.s_addr = inet_addr(rhost); e->ip.smsk.s_addr = INADDR_NONE; } r = iptc_init_verify_and_append("filter", miniupnpd_forward_chain, e, "add_filter_rule()"); free(target); free(match); free(e); return r; }
/* iptables -t mangle -A MINIUPNPD -s iaddr -d rhost * -p proto --sport iport --dport rport -j DSCP * --set-dscp 0xXXXX */ static int addpeerdscprule(int proto, unsigned char dscp, const char * iaddr, unsigned short iport, const char * rhost, unsigned short rport) { int r = 0; struct ipt_entry * e; struct ipt_entry_match *match = NULL; struct ipt_entry_target *target = NULL; e = calloc(1, sizeof(struct ipt_entry)); e->ip.proto = proto; /* TODO: Fill port matches and SNAT */ if(proto == IPPROTO_TCP) { match = get_tcp_match(rport, iport); } else { match = get_udp_match(rport, iport); } e->nfcache = NFC_IP_DST_PT | NFC_IP_SRC_PT; target = get_dscp_target(dscp); e->nfcache |= NFC_UNKNOWN; e = realloc(e, sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size); memcpy(e->elems, match, match->u.match_size); memcpy(e->elems + match->u.match_size, target, target->u.target_size); e->target_offset = sizeof(struct ipt_entry) + match->u.match_size; e->next_offset = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; /* internal host */ if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*"))) { e->ip.src.s_addr = inet_addr(iaddr); e->ip.smsk.s_addr = INADDR_NONE; } /* remote host */ if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) { e->ip.dst.s_addr = inet_addr(rhost); e->ip.dmsk.s_addr = INADDR_NONE; } r = iptc_init_verify_and_append("mangle", miniupnpd_nat_chain, e, "addpeerDSCPrule()"); free(target); free(match); free(e); return r; }
/* add nat rule * iptables -t nat -A MINIUPNPD -p proto --dport eport -j DNAT --to iaddr:iport * */ int addnatrule(int proto, unsigned short eport, const char * iaddr, unsigned short iport, const char * eaddr) /* Chun add: for CD_ROUTER */ { int r = 0; struct ipt_entry * e; struct ipt_entry_match *match = NULL; struct ipt_entry_target *target = NULL; e = calloc(1, sizeof(struct ipt_entry)); e->ip.proto = proto; if(proto == IPPROTO_TCP) { match = get_tcp_match(eport); } else { match = get_udp_match(eport); } e->nfcache = NFC_IP_DST_PT; /* Chun add: for CD_ROUTER */ if(eaddr) { e->ip.src.s_addr = inet_addr(eaddr); e->ip.smsk.s_addr = INADDR_NONE; } target = get_dnat_target(iaddr, iport); e->nfcache |= NFC_UNKNOWN; e = realloc(e, sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size); memcpy(e->elems, match, match->u.match_size); memcpy(e->elems + match->u.match_size, target, target->u.target_size); e->target_offset = sizeof(struct ipt_entry) + match->u.match_size; e->next_offset = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; r = iptc_init_verify_and_append("nat", e, "addnatrule()"); free(target); free(match); free(e); return r; }
/* add nat rule * iptables -t nat -A MINIUPNPD -p proto --dport eport -j DNAT --to iaddr:iport * */ static int addnatrule(int proto, unsigned short eport, const char * iaddr, unsigned short iport, const char * rhost) { int r = 0; struct ipt_entry * e; struct ipt_entry_match *match = NULL; struct ipt_entry_target *target = NULL; e = calloc(1, sizeof(struct ipt_entry)); e->ip.proto = proto; if(proto == IPPROTO_TCP) { match = get_tcp_match(eport); } else { match = get_udp_match(eport); } e->nfcache = NFC_IP_DST_PT; target = get_dnat_target(iaddr, iport); e->nfcache |= NFC_UNKNOWN; e = realloc(e, sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size); memcpy(e->elems, match, match->u.match_size); memcpy(e->elems + match->u.match_size, target, target->u.target_size); e->target_offset = sizeof(struct ipt_entry) + match->u.match_size; e->next_offset = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; /* remote host */ if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) { e->ip.src.s_addr = inet_addr(rhost); e->ip.smsk.s_addr = INADDR_NONE; } r = iptc_init_verify_and_append("nat", miniupnpd_nat_chain, e, "addnatrule()"); free(target); free(match); free(e); return r; }
/* add_filter_rule() * */ int add_filter_rule(int proto, const char * iaddr, unsigned short iport) { int r = 0; struct ipt_entry * e; struct ipt_entry_match *match = NULL; struct ipt_entry_target *target = NULL; e = calloc(1, sizeof(struct ipt_entry)); e->ip.proto = proto; if(proto == IPPROTO_TCP) { match = get_tcp_match(iport); } else { match = get_udp_match(iport); } e->nfcache = NFC_IP_DST_PT; e->ip.dst.s_addr = inet_addr(iaddr); e->ip.dmsk.s_addr = INADDR_NONE; target = get_accept_target(); e->nfcache |= NFC_UNKNOWN; e = realloc(e, sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size); memcpy(e->elems, match, match->u.match_size); memcpy(e->elems + match->u.match_size, target, target->u.target_size); e->target_offset = sizeof(struct ipt_entry) + match->u.match_size; e->next_offset = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; r = iptc_init_verify_and_append("filter", e, "add_filter_rule()"); free(target); free(match); free(e); return r; }
void iptc_add_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append) { iptc_handle_t 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 = calloc(1, sizeof(*chain_entry)); if (src) { chain_entry->ip.src.s_addr = inet_addr(src); chain_entry->ip.smsk.s_addr = inet_addr("255.255.255.255"); } if (dest) { chain_entry->ip.dst.s_addr = inet_addr(dest); chain_entry->ip.dmsk.s_addr = inet_addr("255.255.255.255"); } if (iniface) strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ); if (outiface) strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ); if (strcmp(protocol, "TCP") == 0) { chain_entry->ip.proto = IPPROTO_TCP; entry_match = get_tcp_match(srcports, destports, &chain_entry->nfcache); } else if (strcmp(protocol, "UDP") == 0) { chain_entry->ip.proto = IPPROTO_UDP; entry_match = get_udp_match(srcports, destports, &chain_entry->nfcache); } else { trace(1, "Unsupported protocol: %s", protocol); return; } 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 = calloc(1, size); entry_target->u.user.target_size = size; strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN); } else if (strcmp(target, "DNAT") == 0) { entry_target = get_dnat_target(dnat_to, &chain_entry->nfcache); } if (entry_match) match_size = entry_match->u.match_size; else match_size = 0; chain_entry = realloc(chain_entry, sizeof(*chain_entry) + match_size + entry_target->u.target_size); 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) { trace(1, "libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno)); return; } strncpy(labelit, chain, sizeof(ipt_chainlabel)); result = iptc_is_chain(chain, handle); if (!result) { trace(1, "libiptc error: Chain %s does not exist!", chain); return; } if (append) result = iptc_append_entry(labelit, chain_entry, &handle); else result = iptc_insert_entry(labelit, chain_entry, 0, &handle); if (!result) { trace(1, "libiptc error: Can't add, %s", iptc_strerror(errno)); return; } result = iptc_commit(&handle); if (!result) { trace(1, "libiptc error: Commit error, %s", iptc_strerror(errno)); return; } else trace(3, "added new rule to block successfully"); if (entry_match) free(entry_match); free(entry_target); free(chain_entry); }