www.pudn.com > tdi_fw.zip > flt_rule.c
// $Id: flt_rule.c,v 1.2 2002/11/12 10:49:11 dev Exp $ #include#include "flt_rule.h" #include "ipc.h" #include "tdi_fw_svc.h" struct str_value { const char *str; int value; }; static int str_value(const struct str_value *sv, const char *str); static int get_amp(char *str, u_long *addr, u_long *mask, u_short *port, u_short *port2); static struct str_value filter_sv[] = { {"ALLOW", FILTER_ALLOW}, {"DENY", FILTER_DENY}, {NULL, 0} }; static struct str_value proto_sv[] = { {"TCP", IPPROTO_TCP}, {"UDP", IPPROTO_UDP}, {"RawIP", IPPROTO_IP}, {NULL, 0} }; static struct str_value direction_sv[] = { {"IN", DIRECTION_IN}, {"OUT", DIRECTION_OUT}, {NULL, 0} }; /* * rule is like this: * * ALLOW|DENY TCP|UDP|RawIP IN|OUT FROM TO [NOLOG]|[CLIENT|SERVER ] */ int parse_rule(char *str, struct flt_rule *rule) { static char delim[] = " \t"; char *p = str, *p2; int v; memset(rule, 0, sizeof(*rule)); // by default log using of all rules! rule->log = 1; /* ALLOW|DENY */ if (*p == '\0') { error("PARSE\tparse_rule: filter ALLOW or DENY is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; v = str_value(filter_sv, p); if (v == -1) { error("PARSE\tparse_rule: \"%s\" is not ALLOW or DENY filter", p); return 0; } rule->result = v; p = p2; /* TCP|UDP|RawIP */ if (p == NULL) { error("PARSE\tparse_rule: protocol TCP, UDP or RawIP is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; v = str_value(proto_sv, p); if (v == -1) { error("PARSE\tparse_rule: \"%s\" is not TCP, UDP or RawIP protocol", p); return 0; } rule->proto = v; p = p2; /* IN|OUT */ if (p == NULL) { error("PARSE\tparse_rule: direction IN or OUT is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; v = str_value(direction_sv, p); if (v == -1) { error("PARSE\tparse_rule: \"%s\" is not IN or OUT direction", p); return 0; } rule->direction = v; p = p2; /* FROM */ if (p == NULL) { error("PARSE\tparse_rule: keyword FROM is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; if (strcmp(p, "FROM") != 0) { error("PARSE\tparse_rule: \"%s\" is not FROM keyword", p); return 0; } p = p2; /* */ if (p == NULL) { error("PARSE\tparse_rule: from address is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; if (!get_amp(p, &rule->addr_from, &rule->mask_from, &rule->port_from, &rule->port2_from)) { error("PARSE\tparse_rule: invalid from address \"%s\"", p); return 0; } p = p2; /* TO */ if (p == NULL) { error("PARSE\tparse_rule: keyword TO is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; if (strcmp(p, "TO") != 0) { error("PARSE\tparse_rule: \"%s\" is not TO keyword"); return 0; } p = p2; /* */ if (p == NULL) { error("PARSE\tparse_rule: to address is missing"); return 0; } p2 = strpbrk(p, delim); if (p2 != NULL) *(p2++) = '\0'; if (!get_amp(p, &rule->addr_to, &rule->mask_to, &rule->port_to, &rule->port2_to)) { error("PARSE\tparse_rule: invalid to address \"%s\"", p); return 0; } p = p2; /* NOLOG */ if (p != NULL) { if (strcmp(p, "NOLOG") == 0) rule->log = 0; else { error("PARSE\tparse_rule: invalid to address \"%s\"", p); return 0; } } return 1; } int str_value(const struct str_value *sv, const char *str) { while (sv->str != NULL) { if (strcmp(sv->str, str) == 0) return sv->value; sv++; } return -1; } int get_amp(char *string, u_long *addr, u_long *mask, u_short *port, u_short *port2) { char *p, *addr_str = NULL, *mask_str = NULL, *port_str = NULL, *port2_str = NULL; int result = 0; addr_str = string; // "/mask" p = strchr(string, '/'); if (p != NULL) { *(p++) = '\0'; mask_str = p; } // ":port" p = strchr(mask_str ? mask_str : string, ':'); if (p != NULL) { *(p++) = '\0'; port_str = p; // "-port2" p = strchr(port_str, '-'); if (p != NULL) { *(p++) = '\0'; port2_str = p; } } // is it ANY? if (strcmp(addr_str, "ANY") == 0) { // 0.0.0.0/0 *addr = INADDR_ANY; *mask = INADDR_ANY; } else { // [/ ] *addr = inet_addr(addr_str); if (*addr == INADDR_NONE && strcmp(addr_str, "255.255.255.255") != 0) { if (g_rules_resolve_addr) { // try to resolve addr struct hostent *he = gethostbyname(addr_str); if (he == NULL) { error("PARSE\tUnable to resolve: %s", addr_str); return 0; } *addr = *(u_long *)he->h_addr; // ??? do we need to log it ??? } else { error("PARSE\tInvalid address: %s", addr_str); return 0; } } if (mask_str != NULL) { // int n = atoi(mask_str); if ((n == 0 && strcmp(mask_str, "0") != 0) || n < 0 || n > 32) { error("PARSE\tInvalid mask: %s", mask_str); return 0; } if (n == 0) *mask = 0; else { int i; for (i = 1, *mask = 1; i < n; i++) *mask |= *mask << 1; } } else *mask = INADDR_NONE; // default mask 255.255.255.255 } if (port_str) { int n = atoi(port_str); if ((n == 0 && strcmp(port_str, "0") != 0) || n < 0 || n > 0xffff) { error("PARSE\tInvalid port: %s", port_str); return 0; } *port = (USHORT)n; } else *port = 0; if (port2_str) { int n = atoi(port2_str); if ((n == 0 && strcmp(port2_str, "0") != 0) || n < 0 || n > 0xffff) { error("PARSE\tInvalid port2: %s", port2_str); return 0; } *port2 = (USHORT)n; } else *port2 = 0; // make network order *port = htons(*port); *port2 = htons(*port2); return 1; }