#define INET6 #define BUILD_TARGET #define MODULE_DATATYPE struct ip6t_reject_info #define MODULE_NAME "REJECT" #define __USE_GNU #include "../module_iface.h" #include #include #include #include #include #include #include typedef struct { char *name, *alias; enum ip6t_reject_with with; } rejectList; rejectList reject_types[] = { { "icmp6-no-route" "no-route", IP6T_ICMP6_NO_ROUTE }, { "icmp6-admin-prohibited", "adm-prohibited", IP6T_ICMP6_ADM_PROHIBITED }, { "icmp6-addr-unreachable", "addr-unreach", IP6T_ICMP6_ADDR_UNREACH }, { "icmp6-port-unreachable", "port-unreach", IP6T_ICMP6_PORT_UNREACH }, { "tcp-reset", NULL, IP6T_TCP_RESET }, }; static void setup(void *myinfo, unsigned int *nfcache) { MODULE_DATATYPE *info = (void *)((MODULE_ENTRYTYPE *)myinfo)->data; info->with = IP6T_ICMP6_PORT_UNREACH; *nfcache |= NFC_UNKNOWN; } static int parse_field(char *field, SV *value, void *myinfo, unsigned int *nfcache, struct ip6t_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 == IP6T_TCP_RESET && (entry->ipv6.proto != IPPROTO_TCP || (entry->ipv6.invflags & IP6T_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 ip6t_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 = IP6T_ALIGN(sizeof(MODULE_DATATYPE)), .size_uspace = IP6T_ALIGN(sizeof(MODULE_DATATYPE)), .setup = setup, .parse_field = parse_field, .get_fields = get_fields, }; ModuleDef *init(void) { return(&_module); } /* vim: ts=4 */