Author: gherzan Date: Wed Apr 14 20:57:25 2010 New Revision: 2269 Log: libpisa: add ipfw implementation for the firewall wrapper Modified: trunk/libpisa/sysdep.h trunk/libpisa/sysdep_fw.c Modified: trunk/libpisa/sysdep.h ============================================================================== --- trunk/libpisa/sysdep.h Wed Apr 14 20:03:31 2010 (r2268) +++ trunk/libpisa/sysdep.h Wed Apr 14 20:57:25 2010 (r2269) @@ -85,7 +85,10 @@ /** firewall command */ struct firewall_cmd { - /** action: add of remove rule */ + /** + * action: add or remove rule. Please leave this at the beginning of the + * file, for hashing purposes. + */ short action; /** direction with respect to the local host */ short dir; Modified: trunk/libpisa/sysdep_fw.c ============================================================================== --- trunk/libpisa/sysdep_fw.c Wed Apr 14 20:03:31 2010 (r2268) +++ trunk/libpisa/sysdep_fw.c Wed Apr 14 20:57:25 2010 (r2269) @@ -63,11 +63,58 @@ #elif defined(__APPLE__) +/** + * Bernstein's hash applied to a firewall command structure. + * See http://www.cse.yorku.ca/~oz/hash.html + */ +static unsigned int fw_cmd_hash(struct firewall_cmd *cmd) +{ + unsigned char *str = (unsigned char*)cmd; + unsigned int hash = 5381; + int c; + + /* hash only the "constant" part of the command, i.e. the rule. + * Hence, we ignore the action (add/delete rule). + */ + str += sizeof(cmd->action); + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + int pisa_firewall_do(struct firewall_cmd *cmd) { - /*TODO: ipfw implementation */ + char line[CMD_SIZE], temp[CMD_SIZE/4]; + unsigned int rule_id; + + if ((!cmd->action) || (!cmd->dir) || (!cmd->target)) { + return -1; + } + + rule_id = fw_cmd_hash(cmd); + + if (cmd->action == FW_DELETE) { + snprintf(line, sizeof(line), "ipfw del %u", rule_id); + goto out; + } + + snprintf(line, sizeof(line), "ipfw add %d %s %s %s ", + rule_id, + (cmd->target == FW_ACCEPT) ? "allow" : "deny", + (cmd->proto == FW_TCP) ? "tcp" : "udp", + (cmd->dir == FW_INPUT) ? "from any to me in" : + "from me to any out"); + + if (cmd->iface) { + snprintf(temp, sizeof(temp), "via %s", cmd->iface); + strcat(line, temp); + } - return 0; +out: + printf("FIREWALL COMMAND: %s\n", line); + return system(line); } -#endif +#endif /* OS detection */