#define BUILD_TARGET #define MODULE_DATATYPE struct ipt_reject_info #define MODULE_NAME "REJECT" #define __USE_GNU #include "../module_iface.h" #include #include #include #include #include #include #ifndef IPT_ICMP_ADMIN_PROHIBITED #define IPT_ICMP_ADMIN_PROHIBITED IPT_TCP_RESET + 1 #endif typedef struct { char *name, *alias; enum ipt_reject_with with; } rejectList; rejectList reject_types[] = { { "icmp-net-unreachable", "net-unreach", IPT_ICMP_NET_UNREACHABLE }, { "icmp-host-unreachable", "host-unreach", IPT_ICMP_HOST_UNREACHABLE }, { "icmp-port-unreachable", "port-unreach", IPT_ICMP_PORT_UNREACHABLE }, { "icmp-proto-unreachable", "proto-unreach", IPT_ICMP_PROT_UNREACHABLE }, { "icmp-net-prohibited", "net-prohib", IPT_ICMP_NET_PROHIBITED }, { "icmp-host-prohibited", "host-prohib", IPT_ICMP_HOST_PROHIBITED }, { "tcp-reset", NULL, IPT_TCP_RESET }, { "icmp-admin-prohibited", "admin-prohib", IPT_ICMP_ADMIN_PROHIBITED }, }; static void setup(void *myinfo, unsigned int *nfcache) { MODULE_DATATYPE *info = (void *)((MODULE_ENTRYTYPE *)myinfo)->data; info->with = IPT_ICMP_PORT_UNREACHABLE; *nfcache |= NFC_UNKNOWN; } static int parse_field(char *field, SV *value, void *myinfo, unsigned int *nfcache, struct ipt_entry *entry, int *flags) { MODULE_DATATYPE *info = (void *)(*(MODULE_ENTRYTYPE **)myinfo)->data; char *str, *temp; unsigned int i; rejectList *selector = NULL; STRLEN len; if(strcmp(field, "reject-with")) return(FALSE); if(!SvPOK(value)) { SET_ERRSTR("%s: Requires a string arg", field); return(FALSE); } temp = SvPV(value, len); str = malloc(len + 1); strncpy(str, temp, len); str[len] = '\0'; for(i = 0; i < sizeof(reject_types) / sizeof(rejectList); i++) { if(!strcmp(reject_types[i].name, str) || (reject_types[i].alias && !strcmp(reject_types[i].alias, str))) { selector = &reject_types[i]; break; } } free(str); if(!selector) { SET_ERRSTR("%s: Unknown reject type", field); return(FALSE); } if(selector->with == IPT_TCP_RESET && (entry->ip.proto != IPPROTO_TCP || (entry->ip.invflags & IPT_INV_PROTO))) { SET_ERRSTR("%s: TCP RST can only be used with TCP protocol", field); return(FALSE); } info->with = selector->with; return(TRUE); } static void get_fields(HV *ent_hash, void *myinfo, struct ipt_entry *entry) { MODULE_DATATYPE *info = (void *)((MODULE_ENTRYTYPE *)myinfo)->data; rejectList *selector = NULL; unsigned int i; for(i = 0; i < sizeof(reject_types) / sizeof(rejectList); i++) { if(info->with == reject_types[i].with) { selector = &reject_types[i]; break; } } if(!selector) { fprintf(stderr, "unknown reject type '%u'\n", info->with); return; } hv_store(ent_hash, "reject-with", 11, newSVpv(selector->name, 0), 0); } ModuleDef _module = { .type = MODULE_TYPE, .name = MODULE_NAME, .size = IPT_ALIGN(sizeof(MODULE_DATATYPE)), .size_uspace = IPT_ALIGN(sizeof(MODULE_DATATYPE)), .setup = setup, .parse_field = parse_field, .get_fields = get_fields, }; ModuleDef *init(void) { return(&_module); } /* vim: ts=4 */