From 63d51b566ea270b45b5b34b1feab37b8faa28232 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 9 May 2004 23:20:43 +0000 Subject: main fieryfilter work git-svn-id: file:///home/lennart/svn/public/fieryfilter/fieryfilter@31 79e6afc9-17da-0310-ae3c-b873bff394f4 --- client/rule.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 client/rule.c (limited to 'client/rule.c') diff --git a/client/rule.c b/client/rule.c new file mode 100644 index 0000000..60c7081 --- /dev/null +++ b/client/rule.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include + +#include "rule.h" +#include "format.h" + +static int id = 0; + +rule_t* rule_new() { + rule_t* rule = g_new0(rule_t, 1); + + rule->enabled = TRUE; + rule->realized = FALSE; + rule->match = 0; + + rule->direction = DIR_OUTGOING; + rule->src_netmask_bits = 32; + rule->dst_netmask_bits = 32; + + rule->id = id++; + + //g_message("allocated rule %u", rule->id); + + return rule; +} + +void rule_free(rule_t *rule) { + //g_message("freed rule %u", rule->id); + + if (rule->being_edited) + g_message("WARNING! Rule being currently edited is freed!"); + g_free(rule); +} + +rule_t* rule_new_from_conn_info(conn_info_t *ci) { + rule_t *rule = rule_new(); + g_assert(ci); + + rule->enabled = TRUE; + rule->realized = FALSE; + rule->match = MATCH_DIRECTION | MATCH_TYPE; + + strncpy(rule->description, ci->type_string, sizeof(rule->description)); + strncpy(rule->device_in, ci->device_in, IFNAMSIZ); + strncpy(rule->device_out, ci->device_out, IFNAMSIZ); + + rule->protocol = ci->protocol; + rule->port = ci->port; + rule->icmp_type = ci->icmp_type; + rule->direction = ci->direction; + + rule->src_ip_address = ci->src_ip_address; + rule->dst_ip_address = ci->dst_ip_address; + + rule->src_netmask_bits = 32; + rule->dst_netmask_bits = 32; + + if (ci->broadcast) + rule->match |= MATCH_BROADCAST; + + if (ci->direction == DIR_INCOMING) + rule->match |= MATCH_SOURCE; + + if (ci->direction == DIR_OUTGOING) + rule->match |= MATCH_DESTINATION; + + if (ci->direction == DIR_PASSING) + rule->match |= MATCH_DESTINATION|MATCH_SOURCE; + + return rule; +} + +rule_t* rule_new_from_xml(xmlDocPtr doc, xmlNodePtr node) { + rule_t *rule = rule_new(); + xmlChar *text = NULL; + + rule->match = 0; + rule->enabled = TRUE; + rule->realized = TRUE; + + for (node = node->xmlChildrenNode; node; node = node->next) { + + if (node->type == XML_TEXT_NODE) + continue; + + if (node->type != XML_ELEMENT_NODE) + goto finish; + + text = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + + if (!xmlStrcmp(node->name, "description")) + g_strlcpy(rule->description, text, sizeof(rule->description)); + else if (!xmlStrcmp(node->name, "direction")) { + rule->match |= MATCH_DIRECTION; + + if (!xmlStrcmp(text, "incoming")) + rule->direction = DIR_INCOMING; + else if (!xmlStrcmp(text, "outgoing")) + rule->direction = DIR_OUTGOING; + else if (!xmlStrcmp(text, "passing")) + rule->direction = DIR_PASSING; + else + goto finish; + + } else if (!xmlStrcmp(node->name, "protocol")) { + rule->match |= MATCH_TYPE; + + if (!xmlStrcmp(text, "udp")) + rule->protocol = IPPROTO_UDP; + else if (!xmlStrcmp(text, "tcp")) + rule->protocol = IPPROTO_TCP; + else if (!xmlStrcmp(text, "tcp")) + rule->protocol = IPPROTO_ICMP; + else + goto finish; + + } else if (!xmlStrcmp(node->name, "destination-port")) { + rule->match |= MATCH_TYPE; + rule->port = atoi(text); + } else if (!xmlStrcmp(node->name, "icmp-type")) { + rule->match |= MATCH_TYPE; + rule->icmp_type = atoi(text); + } else if (!xmlStrcmp(node->name, "source")) { + rule->match |= MATCH_SOURCE; + if (!inet_aton(text, (struct in_addr*) &rule->src_ip_address)) + goto finish; + } else if (!xmlStrcmp(node->name, "destination")) { + rule->match |= MATCH_DESTINATION; + if (!inet_aton(text, (struct in_addr*) &rule->dst_ip_address)) + goto finish; + } else if (!xmlStrcmp(node->name, "input-device")) { + rule->match |= MATCH_INTERFACES; + g_strlcpy(rule->device_in, text, sizeof(rule->device_in)); + } else if (!xmlStrcmp(node->name, "output-device")) { + rule->match |= MATCH_INTERFACES; + g_strlcpy(rule->device_out, text, sizeof(rule->device_out)); + } else if (!xmlStrcmp(node->name, "source-netmask-bits")) { + rule->src_netmask_bits = atoi(text); + } else if (!xmlStrcmp(node->name, "destination-netmask-bits")) { + rule->dst_netmask_bits = atoi(text); + } else if (!xmlStrcmp(node->name, "broadcast")) { + rule->match |= MATCH_BROADCAST; + rule->match &= ~MATCH_UNICAST; + } else if (!xmlStrcmp(node->name, "unicast")) { + rule->match |= MATCH_UNICAST; + rule->match &= ~MATCH_BROADCAST; + } else if (!xmlStrcmp(node->name, "target")) { + + if (!xmlStrcmp(text, "drop")) + rule->verdict = VERDICT_DROP; + else if (!xmlStrcmp(text, "reject")) + rule->verdict = VERDICT_REJECT; + else if (!xmlStrcmp(text, "accept")) + rule->verdict = VERDICT_ACCEPT; + else if (!xmlStrcmp(text, "query") || !xmlStrcmp(text, "ask")) + rule->verdict = VERDICT_QUERY; + else + goto finish; + } else if (!xmlStrcmp(node->name, "disabled")) { + rule->enabled = FALSE; + } else + goto finish; + + if (text) + xmlFree(text); + text = NULL; + } + + return rule; + +finish: + if (text) + xmlFree(text); + + rule_free(rule); + return NULL; +} + + +gchar* rule_match_string(rule_t* rule) { + static char txt[256], txt2[256]; + guint l; + g_assert(rule); + + txt[0] = 0; + + if (rule->match & MATCH_DIRECTION) { + switch (rule->direction) { + case DIR_INCOMING: g_strlcat(txt, "incoming; ", sizeof(txt)); break; + case DIR_OUTGOING: g_strlcat(txt, "outgoing; ", sizeof(txt)); break; + case DIR_PASSING: g_strlcat(txt, "passing; ", sizeof(txt)); break; + } + + if (rule->match & MATCH_INTERFACES) { + if (rule->direction == DIR_INCOMING) + snprintf(txt2, sizeof(txt2), "device %s; ", rule->device_in); + else if (rule->direction == DIR_OUTGOING) + snprintf(txt2, sizeof(txt2), "device %s; ", rule->device_out); + else + snprintf(txt2, sizeof(txt2), "devices %s to %s; ", rule->device_in, rule->device_out); + + g_strlcat(txt, txt2, sizeof(txt)); + } + } + + if (rule->match & MATCH_TYPE) { + if (rule->protocol == IPPROTO_ICMP) + snprintf(txt2, sizeof(txt2), "protocol ICMP; type %s; ", icmp_type_str(rule->icmp_type)); + else + snprintf(txt2, sizeof(txt2), "protocol %s; port %u; ", rule->protocol == IPPROTO_TCP ? "TCP" : "UDP", rule->port); + + g_strlcat(txt, txt2, sizeof(txt)); + } + + if (rule->match & MATCH_SOURCE) { + if (rule->src_netmask_bits < 32) + snprintf(txt2, sizeof(txt2), "from %s/%i; ", format_ip_address(rule->src_ip_address), rule->src_netmask_bits); + else + snprintf(txt2, sizeof(txt2), "from %s; ", format_ip_address(rule->src_ip_address)); + + g_strlcat(txt, txt2, sizeof(txt)); + } + + if (rule->match & MATCH_DESTINATION) { + if (rule->dst_netmask_bits < 32) + snprintf(txt2, sizeof(txt2), "to %s/%i; ", format_ip_address(rule->dst_ip_address), rule->dst_netmask_bits); + else + snprintf(txt2, sizeof(txt2), "to %s; ", format_ip_address(rule->dst_ip_address)); + g_strlcat(txt, txt2, sizeof(txt)); + } + + if (rule->match & MATCH_BROADCAST) + g_strlcat(txt, "broadcast; ", sizeof(txt)); + + if (rule->match & MATCH_UNICAST) + g_strlcat(txt, "unicast; ", sizeof(txt)); + + + if ((l = strlen(txt)) > 2) { + txt[l-2] = 0; + return txt; + } else + return "all"; +} + +int rule_to_xml(rule_t*rule, xmlDocPtr doc, xmlNodePtr parent) { + static char txt[256]; + + xmlNodePtr node = NULL; + + if (!(node = xmlNewDocNode(doc, NULL, "rule", NULL))) + goto finish; + + snprintf(txt, sizeof(txt), "%u", rule->id); + xmlNewProp(node, "id", txt); + + xmlNewTextChild(node, NULL, "description", rule->description); + + if (!rule->enabled) + xmlNewTextChild(node, NULL, "disabled", NULL); + + xmlNewTextChild(node, NULL, "target", format_verdict(rule->verdict, FORMAT_XML)); + + if (rule->match & MATCH_DIRECTION) { + + xmlNewTextChild(node, NULL, "direction", rule->direction == DIR_INCOMING ? "incoming" : (rule->direction == DIR_OUTGOING ? "outgoing" : "passing")); + + if (rule->match & MATCH_INTERFACES) { + if ((rule->direction == DIR_INCOMING || rule->direction == DIR_PASSING) && rule->device_in[0]) + xmlNewTextChild(node, NULL, "input-device", rule->device_in); + else if ((rule->direction == DIR_OUTGOING || rule->direction == DIR_PASSING) && rule->device_out[0]) + xmlNewTextChild(node, NULL, "output-device", rule->device_out); + } + } + + if (rule->match & MATCH_TYPE) { + xmlNewTextChild(node, NULL, "protocol", rule->protocol == IPPROTO_UDP ? "udp" : (rule->protocol == IPPROTO_ICMP ? "icmp" : "tcp")); + + if (rule->protocol == IPPROTO_ICMP) { + snprintf(txt, sizeof(txt), "%u", rule->icmp_type); + xmlNewTextChild(node, NULL, "icmp-type", txt); + } else { + snprintf(txt, sizeof(txt), "%u", rule->port); + xmlNewTextChild(node, NULL, "destination-port", txt); + } + } + + if (rule->match & MATCH_SOURCE) { + xmlNewTextChild(node, NULL, "source", format_ip_address(rule->src_ip_address)); + if (rule->src_netmask_bits < 32) { + snprintf(txt, sizeof(txt), "%u", rule->src_netmask_bits); + xmlNewTextChild(node, NULL, "source-netmask-bits", txt); + } + } + + if (rule->match & MATCH_DESTINATION) { + xmlNewTextChild(node, NULL, "destination", format_ip_address(rule->dst_ip_address)); + if (rule->dst_netmask_bits < 32) { + snprintf(txt, sizeof(txt), "%u", rule->dst_netmask_bits); + xmlNewTextChild(node, NULL, "destination-netmask-bits", txt); + } + } else if (rule->match & MATCH_BROADCAST) + xmlNewTextChild(node, NULL, "broadcast", NULL); + else if (rule->match & MATCH_UNICAST) + xmlNewTextChild(node, NULL, "unicast", NULL); + + + xmlAddChild(parent, node); + return 0; + +finish: + if (node) + xmlFreeNode(node); + + return -1; +} -- cgit