00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include <sys/types.h>
00012
00013 #include <err.h>
00014 #include <errno.h>
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018
00019 #include "dnet.h"
00020 #include "mod.h"
00021
00022 static void
00023 usage(void)
00024 {
00025 fprintf(stderr, "Usage: dnet fw show\n"
00026 " dnet fw add|delete allow|block in|out "
00027 "<device>|any <proto> <src>[:<sport>[-<max>]] "
00028 "<dst>[:<dport>[-<max>]] [<type>[/<code>]]\n");
00029 exit(1);
00030 }
00031
00032 static int
00033 print_rule(const struct fw_rule *fr, void *arg)
00034 {
00035 struct protoent *pr;
00036 char proto[16], sport[16], dport[16], typecode[16];
00037
00038 if (fr->fw_proto == 0)
00039 proto[0] = '\0';
00040 else if ((pr = getprotobynumber(fr->fw_proto)) == NULL)
00041 snprintf(proto, sizeof(proto), "%d ", fr->fw_proto);
00042 else
00043 snprintf(proto, sizeof(proto), "%s ", pr->p_name);
00044
00045 sport[0] = dport[0] = typecode[0] = '\0';
00046
00047 switch (fr->fw_proto) {
00048 case IP_PROTO_ICMP:
00049 if (fr->fw_sport[1] && fr->fw_dport[1])
00050 snprintf(typecode, sizeof(typecode), " %d/%d",
00051 fr->fw_sport[0], fr->fw_dport[0]);
00052 else if (fr->fw_sport[1])
00053 snprintf(typecode, sizeof(typecode), " %d",
00054 fr->fw_sport[0]);
00055 break;
00056 case IP_PROTO_TCP:
00057 case IP_PROTO_UDP:
00058 if (fr->fw_sport[0] == fr->fw_sport[1]) {
00059 snprintf(sport, sizeof(sport), ":%d", fr->fw_sport[0]);
00060 } else
00061 snprintf(sport, sizeof(sport), ":%d-%d",
00062 fr->fw_sport[0], fr->fw_sport[1]);
00063
00064 if (fr->fw_dport[0] == fr->fw_dport[1]) {
00065 snprintf(dport, sizeof(dport), ":%d", fr->fw_dport[0]);
00066 } else
00067 snprintf(dport, sizeof(dport), ":%d-%d",
00068 fr->fw_dport[0], fr->fw_dport[1]);
00069 break;
00070 }
00071 printf("%s %s %s %s%s%s %s%s%s\n",
00072 fr->fw_op == FW_OP_ALLOW ? "allow" : "block",
00073 fr->fw_dir == FW_DIR_IN ? "in" : "out",
00074 *fr->fw_device ? fr->fw_device : "any",
00075 proto,
00076 fr->fw_src.addr_type ? addr_ntoa(&fr->fw_src) : "",
00077 sport,
00078 fr->fw_dst.addr_type ? addr_ntoa(&fr->fw_dst) : "",
00079 dport,
00080 typecode);
00081
00082 return (0);
00083 }
00084
00085 static int
00086 arg_to_fr(int argc, char *argv[], struct fw_rule *fr)
00087 {
00088 struct protoent *pr;
00089 char *p;
00090
00091 if (argc < 6) {
00092 errno = EINVAL;
00093 return (-1);
00094 }
00095 memset(fr, 0, sizeof(*fr));
00096
00097 fr->fw_op = strcmp(argv[0], "allow") ? FW_OP_BLOCK : FW_OP_ALLOW;
00098
00099 fr->fw_dir = strcmp(argv[1], "in") ? FW_DIR_OUT : FW_DIR_IN;
00100
00101 if (strcmp(argv[2], "any") != 0)
00102 strlcpy(fr->fw_device, argv[2], sizeof(fr->fw_device));
00103
00104 if ((pr = getprotobyname(argv[3])) != NULL)
00105 fr->fw_proto = pr->p_proto;
00106 else
00107 fr->fw_proto = atoi(argv[3]);
00108
00109 p = strtok(argv[4], ":");
00110
00111 if (addr_aton(p, &fr->fw_src) < 0)
00112 return (-1);
00113
00114 if ((p = strtok(NULL, ":")) != NULL) {
00115 fr->fw_sport[0] = (uint16_t)strtol(p, &p, 10);
00116 if (*p == '-')
00117 fr->fw_sport[1] = (uint16_t)strtol(p + 1, NULL, 10);
00118 else
00119 fr->fw_sport[1] = fr->fw_sport[0];
00120 } else if (fr->fw_proto == IP_PROTO_TCP || fr->fw_proto == IP_PROTO_UDP) {
00121 fr->fw_sport[0] = 0;
00122 fr->fw_sport[1] = TCP_PORT_MAX;
00123 }
00124 p = strtok(argv[5], ":");
00125
00126 if (addr_aton(p, &fr->fw_dst) < 0)
00127 return (-1);
00128
00129 if ((p = strtok(NULL, ":")) != NULL) {
00130 fr->fw_dport[0] = (uint16_t)strtol(p, &p, 10);
00131 if (*p == '-')
00132 fr->fw_dport[1] = (uint16_t)strtol(p + 1, NULL, 10);
00133 else
00134 fr->fw_dport[1] = fr->fw_dport[0];
00135 } else if (fr->fw_proto == IP_PROTO_TCP || fr->fw_proto == IP_PROTO_UDP) {
00136 fr->fw_dport[0] = 0;
00137 fr->fw_dport[1] = TCP_PORT_MAX;
00138 }
00139 if (argc > 6) {
00140 if (fr->fw_proto != IP_PROTO_ICMP &&
00141 fr->fw_proto != IP_PROTO_IGMP) {
00142 errno = EINVAL;
00143 return (-1);
00144 }
00145 fr->fw_sport[0] = (uint16_t)strtol(argv[6], &p, 10);
00146 fr->fw_sport[1] = 0xff;
00147 if (*p == '/') {
00148 fr->fw_dport[0] = (uint16_t)strtol(p + 1, NULL, 10);
00149 fr->fw_dport[1] = 0xff;
00150 }
00151 }
00152 return (0);
00153 }
00154
00155 int
00156 fw_main(int argc, char *argv[])
00157 {
00158 struct fw_rule fr;
00159 fw_t *fw;
00160
00161 if (argc < 2 || *(argv[1]) == '-')
00162 usage();
00163
00164 if ((fw = fw_open()) == NULL)
00165 err(1, "fw_open");
00166
00167 if (argc == 2 && strcmp(argv[1], "show") == 0) {
00168 if (fw_loop(fw, print_rule, NULL) < 0)
00169 err(1, "fw_loop");
00170 } else if (argc > 2 && strcmp(argv[1], "add") == 0) {
00171 if (arg_to_fr(argc - 2, argv + 2, &fr) < 0)
00172 err(1, "arg_to_fr");
00173 printf("+ ");
00174 print_rule(&fr, NULL);
00175 if (fw_add(fw, &fr) < 0)
00176 err(1, "fw_add");
00177 } else if (argc > 2 && strcmp(argv[1], "delete") == 0) {
00178 if (arg_to_fr(argc - 2, argv + 2, &fr) < 0)
00179 err(1, "arg_to_fr");
00180 printf("- ");
00181 print_rule(&fr, NULL);
00182 if (fw_delete(fw, &fr) < 0)
00183 err(1, "fw_delete");
00184 } else
00185 usage();
00186
00187 fw_close(fw);
00188
00189 exit(0);
00190 }
00191
00192 struct mod mod_fw = {
00193 "fw",
00194 MOD_TYPE_KERN,
00195 fw_main
00196 };