Remove radix from compilation.
[ipfw.git] / ipfw / ipfw2.c
index ed12d9c..571ff39 100644 (file)
@@ -224,6 +224,12 @@ static struct _s_x rule_action_params[] = {
        { NULL, 0 }     /* terminator */
 };
 
+/* index of 'lookup ... ' keys in the kernel */
+static int lookup_key[] = {
+       TOK_DSTIP, TOK_SRCIP, TOK_DSTPORT, TOK_SRCPORT,
+       TOK_UID, TOK_GID, TOK_JAIL,
+       TOK_PROTO, TOK_MACTYPE, 0, };
+
 static struct _s_x rule_options[] = {
        { "tagged",             TOK_TAGGED },
        { "uid",                TOK_UID },
@@ -290,6 +296,7 @@ static struct _s_x rule_options[] = {
        { "dst-ip6",            TOK_DSTIP6},
        { "src-ipv6",           TOK_SRCIP6},
        { "src-ip6",            TOK_SRCIP6},
+       { "lookup",             TOK_LOOKUP},
        { "//",                 TOK_COMMENT },
 
        { "not",                TOK_NOT },              /* pseudo option */
@@ -358,7 +365,8 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
        if (s < 0)
                err(EX_UNAVAILABLE, "socket");
 
-       if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
+       if (optname == IP_FW_GET || optname == IP_FW_DYN_GET ||
+           optname == IP_DUMMYNET_GET ||
            optname == IP_FW_ADD || optname == IP_FW_TABLE_LIST ||
            optname == IP_FW_TABLE_GETSIZE || 
            optname == IP_FW_NAT_GET_CONFIG || 
@@ -742,6 +750,16 @@ print_ip(ipfw_insn_ip *cmd, char const *s)
        int len = F_LEN((ipfw_insn *)cmd);
        uint32_t *a = ((ipfw_insn_u32 *)cmd)->d;
 
+       if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) {
+               uint32_t d = a[1];
+               const char *arg = "<invalid>";
+
+               if (d < sizeof(lookup_key)/sizeof(lookup_key[0]))
+                       arg = match_value(rule_options, lookup_key[d]);
+               printf("%s lookup %s %d,%d", cmd->o.len & F_NOT ? " not": "",
+                       arg, cmd->o.arg1, a[0]);
+               return;
+       }
        printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s);
 
        if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) {
@@ -1719,12 +1737,14 @@ void
 ipfw_list(int ac, char *av[], int show_counters)
 {
        struct ip_fw *r;
-       ipfw_dyn_rule *dynrules, *d;
+       ipfw_dyn_rule *dynrules = NULL;
+       ipfw_dyn_rule *d;
 
 #define NEXT(r)        ((struct ip_fw *)((char *)r + RULESIZE(r)))
        char *lim;
        void *data = NULL;
-       int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
+       int bcwidth, n, nbytes, pcwidth, width, nstat;
+       int ndyn = 0;
        int exitval = EX_OK;
        int lac;
        char **lav;
@@ -1732,8 +1752,13 @@ ipfw_list(int ac, char *av[], int show_counters)
        char *endptr;
        int seen = 0;
        uint8_t set;
+       int ocmd = IP_FW_GET;
+
+       if (co.do_pipe)
+               ocmd = IP_DUMMYNET_GET;
+       else if (co.do_dynamic)
+               ocmd = IP_FW_DYN_GET;
 
-       const int ocmd = co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
        int nalloc = 1024;      /* start somewhere... */
 
        last = 0;
@@ -1767,19 +1792,25 @@ ipfw_list(int ac, char *av[], int show_counters)
         * Count static rules. They have variable size so we
         * need to scan the list to count them.
         */
+       nstat = 0;
+       r = data;
+
+       if (!co.do_dynamic) {
        for (nstat = 1, r = data, lim = (char *)data + nbytes;
                    r->rulenum < IPFW_DEFAULT_RULE && (char *)r < lim;
                    ++nstat, r = NEXT(r) )
                ; /* nothing */
+       }
 
        /*
         * Count dynamic rules. This is easier as they have
         * fixed size.
         */
-       r = NEXT(r);
-       dynrules = (ipfw_dyn_rule *)r ;
-       n = (char *)r - (char *)data;
-       ndyn = (nbytes - n) / sizeof *dynrules;
+       if (co.do_dynamic) {
+               dynrules = (ipfw_dyn_rule *)r ;
+               n = (char *)r - (char *)data;
+               ndyn = (nbytes - n) / sizeof *dynrules;
+       }
 
        /* if showing stats, figure out column widths ahead of time */
        bcwidth = pcwidth = 0;
@@ -1847,6 +1878,7 @@ ipfw_list(int ac, char *av[], int show_counters)
 
        /* display specific rules requested on command line */
 
+       if (!co.do_dynamic) {
        for (lac = ac, lav = av; lac != 0; lac--) {
                /* convert command line rule # */
                last = rnum = strtoul(*lav++, &endptr, 10);
@@ -1874,6 +1906,7 @@ ipfw_list(int ac, char *av[], int show_counters)
                        warnx("rule %lu does not exist", rnum);
                }
        }
+       }
 
        if (co.do_dynamic && ndyn) {
                printf("## Dynamic rules:\n");
@@ -2740,9 +2773,11 @@ chkarg:
 
                /*
                 * In the kernel we assume AF_INET and use only
-                * sin_port and sin_addr.
+                * sin_port and sin_addr. Remember to set sin_len as
+                * the routing code seems to use it too.
                 */
                p->sa.sin_family = AF_INET;
+               //p->sa.sin_len = sizeof(struct sockaddr_in);
                p->sa.sin_port = 0;
                /*
                 * locate the address-port separator (':' or ',')
@@ -2859,7 +2894,7 @@ chkarg:
                        if (have_tag)
                                errx(EX_USAGE, "tag and untag cannot be "
                                    "specified more than once");
-                       GET_UINT_ARG(tag, 1, IPFW_DEFAULT_RULE - 1, i,
+                       GET_UINT_ARG(tag, IPFW_ARG_MIN, IPFW_ARG_MAX, i,
                           rule_action_params);
                        have_tag = cmd;
                        fill_cmd(cmd, O_TAG, (i == TOK_TAG) ? 0: F_NOT, tag);
@@ -3336,7 +3371,7 @@ read_options:
                        if (c->limit_mask == 0)
                                errx(EX_USAGE, "limit: missing limit mask");
 
-                       GET_UINT_ARG(c->conn_limit, 1, IPFW_DEFAULT_RULE - 1,
+                       GET_UINT_ARG(c->conn_limit, IPFW_ARG_MIN, IPFW_ARG_MAX,
                            TOK_LIMIT, rule_options);
 
                        ac--; av++;
@@ -3464,7 +3499,7 @@ read_options:
                        else {
                                uint16_t tag;
 
-                               GET_UINT_ARG(tag, 1, IPFW_DEFAULT_RULE - 1,
+                               GET_UINT_ARG(tag, IPFW_ARG_MIN, IPFW_ARG_MAX,
                                    TOK_TAGGED, rule_options);
                                fill_cmd(cmd, O_TAGGED, 0, tag);
                        }
@@ -3477,6 +3512,36 @@ read_options:
                        ac--; av++;
                        break;
 
+               case TOK_LOOKUP: {
+                       ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd;
+                       char *p;
+                       int j;
+
+                       if (ac < 2)
+                               errx(EX_USAGE, "format: lookup argument tablenum[,arg]");
+                       cmd->opcode = O_IP_DST_LOOKUP;
+                       cmd->len |= F_INSN_SIZE(ipfw_insn) + 2;
+                       i = match_token(rule_options, *av);
+                       for (j = 0; lookup_key[j] ; j++) {
+                               if (i == lookup_key[j])
+                                       break;
+                       }
+                       if (lookup_key[j] == 0)
+                               errx(EX_USAGE, "format: cannot lookup on %s", *av);
+                       c->d[1] = j; // i converted to option
+                       ac--; av++;
+                       p = strchr(*av, ',');
+                       if (p) {
+                               *p++ = '\0';
+                               c->d[0] = strtoul(p, NULL, 0);
+                       } else {
+                               c->d[0] = ~0;
+                       }
+                       cmd->arg1 = strtoul(*av, NULL, 0);
+                       ac--; av++;
+                   }
+                       break;
+
                default:
                        errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
                }