1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
.TH LSFCC 1 "August 24th, 2000" "Debian GNU/Linux"
.SH NAME
lsfcc \- a Linux Socket Filter Command Compiler
.SH SYNOPSIS
.B lsfcc
.I [-o <output filename>] <input files>
.SH DESCRIPTION
.B 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.
.SH OPTIONS
.B -o <output filename>
changes the filename of the created program from "lsf.out" to the
supplied value.
.SH SYNTAX
There are a number of basic top-level constructs.
.PP
.B packet
.RS
This is used to teach lsfcc about new packet formats.
.PP
.RS
packet udp {
.RS
u_int16_t source;
.PP
u_int16_t dest;
.PP
u_int16_t len;
.PP
u_int16_t check;
.RE
};
.RE
The block begins with the keyword
.I 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.
.PP
This syntax is stolen in a large part from C (and in fact
.I struct
may be used as an alias for
.I packet
), and is intended to make it easy to use cut-and-pasting from C
header files to build new declarations.
.PP
No, I'm not going to write a BNF grammar. Go and read the source.
.RE
.B base
.RS
This informs the compiler of the starting offset of a packet
header. When the compiler sees a directive of the form
.B udp[source]
,it loads the
.I source
field from a
.I udp
header structure assumed to be starting at offset 0 in the
packet. This is not necessarily what you want. By specifying a
.I base
statement such as
.RS
base udp 0x1000;
.RE
the compiler will load all field references rooted at a udp header
from an offset of 0x1000.
.RE
.B fields
.RS
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.
.PP
.I udp[source]
refers to the source field in the udp header.
.PP
.I ip.udp[source]
refers to the source field in a udp header immediately following an ip
header.
.PP
.I 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.
.PP
.I 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.
.PP
And so on.
.RE
.B directives
.RS
And finally, directives. This should all be terribly familiar. There
are three keywords,
.I accept, deny,
and
.I if.
.I Accept
and
.I deny
do about what you would expect (stop examining the
packet and either accept or deny it, in case you don't), and
.I if
is used in constructing conditional statements.
.PP
This is all stolen direct from C, so to save explanation, here's
an example.
.PP
if((udp[source] < 1024) && (udp[dest] < 1024)) accept;
.PP
deny;
.PP
This will only allow packets between privileged ports.
.RE
.SH BUGS
Endianness is not handled in any way, shape or form.
.PP
Feature completeness isn't.
.PP
This manpage is terrible.
.SH SEE ALSO
.BR bpf(4)
.SH AUTHOR
This manual page was written by Mikolaj J. Habryn <dichro-lsfcc@rcpt.to>.
|