IPFW 'ipfw table add' syntax curiosities

Reading the ipfw(8) man page, at the beginning, it states the following syntax for adding elements to tables:
Code:
LOOKUP TABLES
  ...
  ipfw [set N] table name add table-key [value]
  ipfw [set N] table name add [table-key value ...]
  ipfw [set N] table name atomic add [table-key value ...]
  ...

I thought for the longest time that, for an 'addr' or 'number' table, when adding an address/port, I was supplying the value element in the above syntax. Yet, I always noticed this output from ipfw:
Code:
# ipfw table foo create type addr
# ipfw table foo add 127.0.0.1/32
added: 127.0.0.1/32 0
That trailing 0 always bothered me, but I never really gave it much thought.

So when I went to try out adding multiple IPv4 addresses using a single table-add command, I was stumped why it didn't work as expected:
Code:
# ipfw table foo add 127.0.0.1 127.0.0.2 127.0.0.3 127.0.0.4
added: 127.0.0.1/32 2130706434
added: 127.0.0.3/32 2130706436

Where did 2130706434 come from? Reading the man page, this is how I thought I was supposed to add multiple addresses in a single ipfw table-add command:
Code:
One or more entries can be added to a table at once using add command.
Addition of all items are performed atomically.  By default, error in
addition of one entry does not influence addition of other entries.
However, non-zero error code is returned in that case.  Special atomic
keyword may be specified before add to indicate all-or-none add request.

It turns out, the address supplied to the table-add command is not for the 'value' operand, it's the table-key operand! In the case of adding a single IP address to a table, value is optional, and it defaults to '0'. So in the prior example, since I wasn't specifying '0' for the value operand, the next IP address was getting parsed as a number and used instead! This begs the question: wtf is the purpose of the value operand when adding an address/port to a table? If I want to add multiple addresses or ports to a table in the same command invocation, I have to supply this '0' operand myself:
Code:
# ipfw table foo add 127.0.0.1 0 127.0.0.2 0 127.0.0.3 0 127.0.0.4 0
added: 127.0.0.1/32 0
added: 127.0.0.2/32 0
added: 127.0.0.3/32 0
added: 127.0.0.4/32 0

Looking deeper into the man page, the only bit discussing value is for some other use of a lookup table:
Code:
The tablearg feature provides the ability to use a value, looked up in
the table, as the argument for a rule action, action parameter or rule
option.  This can significantly reduce number of rules in some
configurations.  If two tables are used in a rule, the result of the
second (destination) is used.

 Each record may hold one or more values according to value-mask.  This
 mask is set on table creation via valtype option.  The following value
 types are supported:

 value-mask: value-type[,value-mask]

 value-type: skipto | pipe | fib | nat | dscp | tag | divert |
         netgraph | limit | ipv4 | ipv6 | mark

The valtype operand to the table-create command isn't used or specified when creating an 'addr' or 'number' table, and looking at the 'info' command for the table, it's defined to "legacy":
Code:
# ipfw table foo info
--- table(foo), set(0) ---
 kindex: 43, type: addr
 references: 0, valtype: legacy
 algorithm: addr:radix
 items: 4, size: 776

As far as I can determine, I think this is an artifact of the ipfw table-add command just being too overloaded w/ functionality. That, or it is a remnant of some prior function that has yet to be fully removed. Does anyone have any insight on this? It feels like the wording in the man page needs to be clarified a bit (especially when wanting to add multiple addresses/ports in a single command), but without understanding what the 'value' operand is supposed to be, I don't know how that clarification should actually look. Maybe the ipfw parser needs to take into consideration the table's type when parsing the 'add' command and, at least for addr/number tables, shouldn't expect the presence of the 'value' operand at all?
 
I use a file with the list of networks and a simple script to populate the table.
This script may be used as a part of your ipfw script.

Code:
#!/bin/sh

ipfw='/sbin/ipfw -q'

${ipfw} table 3 flush
for ip in `cat /root/netlist`; do
${ipfw} table 3 add $ip
done

#how to use in ipfw script
#${ipfw} add 33 count all from table\(3\) to me
#${ipfw} add 33 count all from me to table\(3\)

file netlist looks lile:
Code:
32.156.0.0/22
35.6.1.0/21
45.7.4.0/21
 
I use a file with the list of networks and a simple script to populate the table.
This script may be used as a part of your ipfw script.

Same; in fact, I already had a working, though slightly-more complex, parsing loop going on to handle comments and white space, that called ipfw's table-add command once-per-address. Catch is, I had a lot of IPs to add, and the firewall startup was very slow as a result, so I spent part of last night and today making that parsing loop build out a list of address arguments to pass to ipfw so as to reduce the number of times the command is actually invoked. It was here that I encountered the initial problem with needing to have that '0' value after each address value, and so, I thought I'd inquire as to the nature of that '0' values purpose. In any event, the firewall script start-up time is now significantly improved; Instead of ipfw being invoked thousands of times, it's only invoked a few hundred times, taking up to a hundred addresses per invocation.
 
Back
Top