NAME
lsfcc - a Linux Socket Filter Command Compiler
SYNOPSIS
lsfcc [-o <output filename>] <input files>
DESCRIPTION
lsfcc is a compiler that will accept directives written in a simple C-like language to create a filter program that can be applied by either the Linux Socket Filter or the Berkeley Packet Filter.
OPTIONS
-o <output filename> changes the filename of the created program from "lsf.out" to the supplied value.
SYNTAX
There are a number of basic top-level constructs.
packet
This is used to teach lsfcc about new packet formats.
packet udp {
u_int16_t source;
u_int16_t dest;
u_int16_t len;
u_int16_t check;
};
The block begins with the keyword packet , followed by an arbitrary name for this packet, and then a brace delimited list of fields. Each field consists of a keyword describing the size of the field, followed by an arbitrary name for the field, followed by a semi-colon. There may optionally be a colon and a number before the semi-colon, in which case that number is taken to be the width of the field in bits, and the original size keyword disregarded. Size keywords include (u_)?int(8|16|32)_t, (unsigned )?(char|int|long) and various other things.
This syntax is stolen in a large part from C (and in fact struct may be used as an alias for packet ), and is intended to make it easy to use cut-and-pasting from C header files to build new declarations.
No, I'm not going to write a BNF grammar. Go and read the source.
base
This informs the compiler of the starting offset of a packet header. When the compiler sees a directive of the form udp[source] ,it loads the source field from a udp header structure assumed to be starting at offset 0 in the packet. This is not necessarily what you want. By specifying a base statement such as
base udp 0x1000;
the compiler will load all field references rooted at a udp header from an offset of 0x1000.
fields
This quite naturally brings us to the point of describing fields. Fields are referenced as a chain of headers, followed by either a field name or byte offset and length.
udp[source] refers to the source field in the udp header.
ip.udp[source] refers to the source field in a udp header immediately following an ip header.
foo.bar.bob[12, 4] refers to the 4 bytes of data starting at a 12 byte offset into the payload of a packet consisting of a bob packet encapsulated in a bar packet encapsulated in a foo packet.
ip[2.1, 1.3] refers to the 11 bits (1 * 8 + 3) of data at a bit offset of 17 (2 * 8 + 1) into the payload of this ip packet.
And so on.
directives
And finally, directives. This should all be terribly familiar. There are three keywords, accept, deny, and if. Accept and deny do about what you would expect (stop examining the packet and either accept or deny it, in case you don't), and if is used in constructing conditional statements.
This is all stolen direct from C, so to save explanation, here's an example.
if((udp[source] < 1024) && (udp[dest] < 1024)) accept;
deny;
This will only allow packets between privileged ports.
BUGS
Endianness is not handled in any way, shape or form.
Feature completeness isn't.
This manpage is terrible.
SEE ALSO
AUTHOR
This manual page was written by Mikolaj J. Habryn <[email protected]>.