Jan Engelhardt | 9640e52 | 2007-09-10 11:50:46 +0000 | [diff] [blame] | 1 | U32 tests whether quantities of up to 4 bytes extracted from a packet have |
| 2 | specified values. The specification of what to extract is general enough to |
| 3 | find data at given offsets from tcp headers or payloads. |
| 4 | .TP |
Jan Engelhardt | fea74bf | 2009-01-12 04:53:18 +0100 | [diff] [blame] | 5 | [\fB!\fP] \fB\-\-u32\fP \fItests\fP |
Jan Engelhardt | 9640e52 | 2007-09-10 11:50:46 +0000 | [diff] [blame] | 6 | The argument amounts to a program in a small language described below. |
| 7 | .IP |
| 8 | tests := location "=" value | tests "&&" location "=" value |
| 9 | .IP |
| 10 | value := range | value "," range |
| 11 | .IP |
| 12 | range := number | number ":" number |
| 13 | .PP |
| 14 | a single number, \fIn\fR, is interpreted the same as \fIn:n\fR. \fIn:m\fR is |
| 15 | interpreted as the range of numbers \fB>=n\fR and \fB<=m\fR. |
| 16 | .IP "" 4 |
| 17 | location := number | location operator number |
| 18 | .IP "" 4 |
| 19 | operator := "&" | "<<" | ">>" | "@" |
| 20 | .PP |
| 21 | The operators \fB&\fR, \fB<<\fR, \fB>>\fR and \fB&&\fR mean the same as in C. |
| 22 | The \fB=\fR is really a set membership operator and the value syntax describes |
| 23 | a set. The \fB@\fR operator is what allows moving to the next header and is |
| 24 | described further below. |
| 25 | .PP |
| 26 | There are currently some artificial implementation limits on the size of the |
| 27 | tests: |
| 28 | .IP " *" |
| 29 | no more than 10 of "\fB=\fR" (and 9 "\fB&&\fR"s) in the u32 argument |
| 30 | .IP " *" |
| 31 | no more than 10 ranges (and 9 commas) per value |
| 32 | .IP " *" |
| 33 | no more than 10 numbers (and 9 operators) per location |
| 34 | .PP |
| 35 | To describe the meaning of location, imagine the following machine that |
| 36 | interprets it. There are three registers: |
| 37 | .IP |
| 38 | A is of type \fBchar *\fR, initially the address of the IP header |
| 39 | .IP |
| 40 | B and C are unsigned 32 bit integers, initially zero |
| 41 | .PP |
| 42 | The instructions are: |
| 43 | .IP |
| 44 | number B = number; |
| 45 | .IP |
| 46 | C = (*(A+B)<<24) + (*(A+B+1)<<16) + (*(A+B+2)<<8) + *(A+B+3) |
| 47 | .IP |
| 48 | &number C = C & number |
| 49 | .IP |
| 50 | << number C = C << number |
| 51 | .IP |
| 52 | >> number C = C >> number |
| 53 | .IP |
| 54 | @number A = A + C; then do the instruction number |
| 55 | .PP |
Jan Engelhardt | fea74bf | 2009-01-12 04:53:18 +0100 | [diff] [blame] | 56 | Any access of memory outside [skb\->data,skb\->end] causes the match to fail. |
Jan Engelhardt | 9640e52 | 2007-09-10 11:50:46 +0000 | [diff] [blame] | 57 | Otherwise the result of the computation is the final value of C. |
| 58 | .PP |
| 59 | Whitespace is allowed but not required in the tests. However, the characters |
| 60 | that do occur there are likely to require shell quoting, so it is a good idea |
| 61 | to enclose the arguments in quotes. |
| 62 | .PP |
| 63 | Example: |
| 64 | .IP |
| 65 | match IP packets with total length >= 256 |
| 66 | .IP |
| 67 | The IP header contains a total length field in bytes 2-3. |
| 68 | .IP |
Jan Engelhardt | fea74bf | 2009-01-12 04:53:18 +0100 | [diff] [blame] | 69 | \-\-u32 "\fB0 & 0xFFFF = 0x100:0xFFFF\fP" |
Jan Engelhardt | 9640e52 | 2007-09-10 11:50:46 +0000 | [diff] [blame] | 70 | .IP |
| 71 | read bytes 0-3 |
| 72 | .IP |
| 73 | AND that with 0xFFFF (giving bytes 2-3), and test whether that is in the range |
| 74 | [0x100:0xFFFF] |
| 75 | .PP |
| 76 | Example: (more realistic, hence more complicated) |
| 77 | .IP |
| 78 | match ICMP packets with icmp type 0 |
| 79 | .IP |
| 80 | First test that it is an ICMP packet, true iff byte 9 (protocol) = 1 |
| 81 | .IP |
Jan Engelhardt | fea74bf | 2009-01-12 04:53:18 +0100 | [diff] [blame] | 82 | \-\-u32 "\fB6 & 0xFF = 1 &&\fP ... |
Jan Engelhardt | 9640e52 | 2007-09-10 11:50:46 +0000 | [diff] [blame] | 83 | .IP |
| 84 | read bytes 6-9, use \fB&\fR to throw away bytes 6-8 and compare the result to |
| 85 | 1. Next test that it is not a fragment. (If so, it might be part of such a |
| 86 | packet but we cannot always tell.) N.B.: This test is generally needed if you |
| 87 | want to match anything beyond the IP header. The last 6 bits of byte 6 and all |
| 88 | of byte 7 are 0 iff this is a complete packet (not a fragment). Alternatively, |
| 89 | you can allow first fragments by only testing the last 5 bits of byte 6. |
| 90 | .IP |
| 91 | ... \fB4 & 0x3FFF = 0 &&\fR ... |
| 92 | .IP |
| 93 | Last test: the first byte past the IP header (the type) is 0. This is where we |
| 94 | have to use the @syntax. The length of the IP header (IHL) in 32 bit words is |
| 95 | stored in the right half of byte 0 of the IP header itself. |
| 96 | .IP |
| 97 | ... \fB0 >> 22 & 0x3C @ 0 >> 24 = 0\fR" |
| 98 | .IP |
| 99 | The first 0 means read bytes 0-3, \fB>>22\fR means shift that 22 bits to the |
| 100 | right. Shifting 24 bits would give the first byte, so only 22 bits is four |
| 101 | times that plus a few more bits. \fB&3C\fR then eliminates the two extra bits |
| 102 | on the right and the first four bits of the first byte. For instance, if IHL=5, |
| 103 | then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0-1 are (in |
| 104 | binary) xxxx0101 yyzzzzzz, \fB>>22\fR gives the 10 bit value xxxx0101yy and |
| 105 | \fB&3C\fR gives 010100. \fB@\fR means to use this number as a new offset into |
| 106 | the packet, and read four bytes starting from there. This is the first 4 bytes |
| 107 | of the ICMP payload, of which byte 0 is the ICMP type. Therefore, we simply |
| 108 | shift the value 24 to the right to throw out all but the first byte and compare |
| 109 | the result with 0. |
| 110 | .PP |
| 111 | Example: |
| 112 | .IP |
| 113 | TCP payload bytes 8-12 is any of 1, 2, 5 or 8 |
| 114 | .IP |
| 115 | First we test that the packet is a tcp packet (similar to ICMP). |
| 116 | .IP |
Jan Engelhardt | fea74bf | 2009-01-12 04:53:18 +0100 | [diff] [blame] | 117 | \-\-u32 "\fB6 & 0xFF = 6 &&\fP ... |
Jan Engelhardt | 9640e52 | 2007-09-10 11:50:46 +0000 | [diff] [blame] | 118 | .IP |
| 119 | Next, test that it is not a fragment (same as above). |
| 120 | .IP |
| 121 | ... \fB0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8\fR" |
| 122 | .IP |
| 123 | \fB0>>22&3C\fR as above computes the number of bytes in the IP header. \fB@\fR |
| 124 | makes this the new offset into the packet, which is the start of the TCP |
| 125 | header. The length of the TCP header (again in 32 bit words) is the left half |
| 126 | of byte 12 of the TCP header. The \fB12>>26&3C\fR computes this length in bytes |
| 127 | (similar to the IP header before). "@" makes this the new offset, which is the |
| 128 | start of the TCP payload. Finally, 8 reads bytes 8-12 of the payload and |
| 129 | \fB=\fR checks whether the result is any of 1, 2, 5 or 8. |