/*
* fw.c
*
* Copyright (c) 2001 Dug Song <dugsong@monkey.org>
*
* $Id: fw.c,v 1.4 2005/02/14 20:45:04 dugsong Exp $
*/
#include "config.h"
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dnet.h"
#include "mod.h"
static void
usage(void)
{
fprintf(stderr, "Usage: dnet fw show\n"
" dnet fw add|delete allow|block in|out "
"<device>|any <proto> <src>[:<sport>[-<max>]] "
"<dst>[:<dport>[-<max>]] [<type>[/<code>]]\n");
exit(1);
}
static int
print_rule(const struct fw_rule *fr, void *arg)
{
struct protoent *pr;
char proto[16], sport[16], dport[16], typecode[16];
if (fr->fw_proto == 0)
proto[0] = '\0';
else if ((pr = getprotobynumber(fr->fw_proto)) == NULL)
snprintf(proto, sizeof(proto), "%d ", fr->fw_proto);
else
snprintf(proto, sizeof(proto), "%s ", pr->p_name);
sport[0] = dport[0] = typecode[0] = '\0';
switch (fr->fw_proto) {
case IP_PROTO_ICMP:
if (fr->fw_sport[1] && fr->fw_dport[1])
snprintf(typecode, sizeof(typecode), " %d/%d",
fr->fw_sport[0], fr->fw_dport[0]);
else if (fr->fw_sport[1])
snprintf(typecode, sizeof(typecode), " %d",
fr->fw_sport[0]);
break;
case IP_PROTO_TCP:
case IP_PROTO_UDP:
if (fr->fw_sport[0] == fr->fw_sport[1]) {
snprintf(sport, sizeof(sport), ":%d", fr->fw_sport[0]);
} else
snprintf(sport, sizeof(sport), ":%d-%d",
fr->fw_sport[0], fr->fw_sport[1]);
if (fr->fw_dport[0] == fr->fw_dport[1]) {
snprintf(dport, sizeof(dport), ":%d", fr->fw_dport[0]);
} else
snprintf(dport, sizeof(dport), ":%d-%d",
fr->fw_dport[0], fr->fw_dport[1]);
break;
}
printf("%s %s %s %s%s%s %s%s%s\n",
fr->fw_op == FW_OP_ALLOW ? "allow" : "block",
fr->fw_dir == FW_DIR_IN ? "in" : "out",
*fr->fw_device ? fr->fw_device : "any",
proto,
fr->fw_src.addr_type ? addr_ntoa(&fr->fw_src) : "",
sport,
fr->fw_dst.addr_type ? addr_ntoa(&fr->fw_dst) : "",
dport,
typecode);
return (0);
}
static int
arg_to_fr(int argc, char *argv[], struct fw_rule *fr)
{
struct protoent *pr;
char *p;
if (argc < 6) {
errno = EINVAL;
return (-1);
}
memset(fr, 0, sizeof(*fr));
fr->fw_op = strcmp(argv[0], "allow") ? FW_OP_BLOCK : FW_OP_ALLOW;
fr->fw_dir = strcmp(argv[1], "in") ? FW_DIR_OUT : FW_DIR_IN;
if (strcmp(argv[2], "any") != 0)
strlcpy(fr->fw_device, argv[2], sizeof(fr->fw_device));
if ((pr = getprotobyname(argv[3])) != NULL)
fr->fw_proto = pr->p_proto;
else
fr->fw_proto = atoi(argv[3]);
p = strtok(argv[4], ":");
if (addr_aton(p, &fr->fw_src) < 0)
return (-1);
if ((p = strtok(NULL, ":")) != NULL) {
fr->fw_sport[0] = (uint16_t)strtol(p, &p, 10);
if (*p == '-')
fr->fw_sport[1] = (uint16_t)strtol(p + 1, NULL, 10);
else
fr->fw_sport[1] = fr->fw_sport[0];
} else if (fr->fw_proto == IP_PROTO_TCP || fr->fw_proto == IP_PROTO_UDP) {
fr->fw_sport[0] = 0;
fr->fw_sport[1] = TCP_PORT_MAX;
}
p = strtok(argv[5], ":");
if (addr_aton(p, &fr->fw_dst) < 0)
return (-1);
if ((p = strtok(NULL, ":")) != NULL) {
fr->fw_dport[0] = (uint16_t)strtol(p, &p, 10);
if (*p == '-')
fr->fw_dport[1] = (uint16_t)strtol(p + 1, NULL, 10);
else
fr->fw_dport[1] = fr->fw_dport[0];
} else if (fr->fw_proto == IP_PROTO_TCP || fr->fw_proto == IP_PROTO_UDP) {
fr->fw_dport[0] = 0;
fr->fw_dport[1] = TCP_PORT_MAX;
}
if (argc > 6) {
if (fr->fw_proto != IP_PROTO_ICMP &&
fr->fw_proto != IP_PROTO_IGMP) {
errno = EINVAL;
return (-1);
}
fr->fw_sport[0] = (uint16_t)strtol(argv[6], &p, 10);
fr->fw_sport[1] = 0xff;
if (*p == '/') {
fr->fw_dport[0] = (uint16_t)strtol(p + 1, NULL, 10);
fr->fw_dport[1] = 0xff;
}
}
return (0);
}
int
fw_main(int argc, char *argv[])
{
struct fw_rule fr;
fw_t *fw;
if (argc < 2 || *(argv[1]) == '-')
usage();
if ((fw = fw_open()) == NULL)
err(1, "fw_open");
if (argc == 2 && strcmp(argv[1], "show") == 0) {
if (fw_loop(fw, print_rule, NULL) < 0)
err(1, "fw_loop");
} else if (argc > 2 && strcmp(argv[1], "add") == 0) {
if (arg_to_fr(argc - 2, argv + 2, &fr) < 0)
err(1, "arg_to_fr");
printf("+ ");
print_rule(&fr, NULL);
if (fw_add(fw, &fr) < 0)
err(1, "fw_add");
} else if (argc > 2 && strcmp(argv[1], "delete") == 0) {
if (arg_to_fr(argc - 2, argv + 2, &fr) < 0)
err(1, "arg_to_fr");
printf("- ");
print_rule(&fr, NULL);
if (fw_delete(fw, &fr) < 0)
err(1, "fw_delete");
} else
usage();
fw_close(fw);
exit(0);
}
struct mod mod_fw = {
"fw",
MOD_TYPE_KERN,
fw_main
};
syntax highlighted by Code2HTML, v. 0.9.1