@@ -10041,9 +10041,165 @@ gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type)
10041
10041
}
10042
10042
10043
10043
static void
10044
- gen_batadv_offsets_v15 (compiler_state_t * cstate , bpf_u_int32 type )
10044
+ gen_prepare_var_offset (compiler_state_t * cstate , bpf_abs_offset * off , struct slist * s )
10045
+ {
10046
+ struct slist * s2 ;
10047
+
10048
+ if (!off -> is_variable )
10049
+ off -> is_variable = 1 ;
10050
+ if (off -> reg == -1 ) {
10051
+ off -> reg = alloc_reg (cstate );
10052
+
10053
+ s2 = new_stmt (cstate , BPF_ALU |BPF_AND );
10054
+ s2 -> s .k = 0 ;
10055
+ s2 = new_stmt (cstate , BPF_ST );
10056
+ s2 -> s .k = off -> reg ;
10057
+ sappend (s , s2 );
10058
+ }
10059
+ }
10060
+
10061
+ /**
10062
+ * gen_batadv_loadx_tvlv_len_offset() - load offset to tvlv_len into X
10063
+ * @cstate: our compiler state
10064
+ * @bat_offset: our offset to the start of the batman-adv packet header
10065
+ * @field_offset: offset of tvlv_len field within the batman-adv packet header
10066
+ * @s: instructions list to append to
10067
+ *
10068
+ * Will load: X = bat_offset + field_offset. So that [X] in the packet will
10069
+ * point to the most-significant byte of the tvlv_len in a batman-adv packet.
10070
+ */
10071
+ static void
10072
+ gen_batadv_loadx_tvlv_len_offset (compiler_state_t * cstate ,
10073
+ bpf_abs_offset * bat_offset ,
10074
+ bpf_u_int32 field_offset , struct slist * s )
10075
+ {
10076
+ struct slist * s2 ;
10077
+
10078
+ s2 = new_stmt (cstate , BPF_LD |BPF_MEM );
10079
+ s2 -> s .k = bat_offset -> reg ;
10080
+ sappend (s , s2 );
10081
+
10082
+ s2 = new_stmt (cstate , BPF_ALU |BPF_ADD |BPF_K );
10083
+ s2 -> s .k = bat_offset -> constant_part + field_offset ;
10084
+ sappend (s , s2 );
10085
+
10086
+ s2 = new_stmt (cstate , BPF_MISC |BPF_TAX );
10087
+ s2 -> s .k = 0 ;
10088
+ sappend (s , s2 );
10089
+ }
10090
+
10091
+ /**
10092
+ * gen_batadv_loadx_tvlv_len() - load tvlv_len value into X
10093
+ * @cstate: our compiler state
10094
+ * @bat_offset: our offset to the start of the batman-adv packet header
10095
+ * @field_offset: offset of tvlv_len field within the batman-adv packet header
10096
+ * @s: instructions list to append to
10097
+ *
10098
+ * Loads the value of the 2 byte tvlv_len field in a given batman-adv packet
10099
+ * header into the X register.
10100
+ */
10101
+ static void
10102
+ gen_batadv_loadx_tvlv_len (compiler_state_t * cstate , bpf_abs_offset * bat_offset ,
10103
+ bpf_u_int32 field_offset , struct slist * s )
10104
+ {
10105
+ struct slist * s2 ;
10106
+
10107
+ /* load offset to tvlv_len field into X register */
10108
+ gen_batadv_loadx_tvlv_len_offset (cstate , bat_offset , field_offset , s );
10109
+
10110
+ /* clear A register */
10111
+ s2 = new_stmt (cstate , BPF_ALU |BPF_AND |BPF_K );
10112
+ s2 -> s .k = 0 ;
10113
+ sappend (s , s2 );
10114
+
10115
+ /* load most significant byte of tvlv_len */
10116
+ s2 = new_stmt (cstate , BPF_LD |BPF_IND |BPF_B );
10117
+ s2 -> s .k = 0 ;
10118
+ sappend (s , s2 );
10119
+
10120
+ /* multiply by 2^8 for real value of MSB, make room for LSB */
10121
+ s2 = new_stmt (cstate , BPF_ALU |BPF_LSH |BPF_K );
10122
+ s2 -> s .k = 8 ;
10123
+ sappend (s , s2 );
10124
+
10125
+ /* load least significant byte of tvlv_len */
10126
+ s2 = new_stmt (cstate , BPF_LD |BPF_IND |BPF_B );
10127
+ s2 -> s .k = 1 ;
10128
+ sappend (s , s2 );
10129
+
10130
+ s2 = new_stmt (cstate , BPF_MISC |BPF_TAX );
10131
+ s2 -> s .k = 0 ;
10132
+ sappend (s , s2 );
10133
+ }
10134
+
10135
+ /**
10136
+ * gen_batadv_offset_addx() - add X register to a variable offset
10137
+ * @cstate: our compiler state
10138
+ * @off: the (variable) offset to add to
10139
+ * @s: instructions list to append to
10140
+ *
10141
+ * Adds the value from the X register to the given variable offset.
10142
+ */
10143
+ static void
10144
+ gen_batadv_offset_addx (compiler_state_t * cstate , bpf_abs_offset * off ,
10145
+ struct slist * s )
10146
+ {
10147
+ struct slist * s2 ;
10148
+
10149
+ s2 = new_stmt (cstate , BPF_LD |BPF_MEM );
10150
+ s2 -> s .k = off -> reg ;
10151
+ sappend (s , s2 );
10152
+
10153
+ s2 = new_stmt (cstate , BPF_ALU |BPF_ADD |BPF_X );
10154
+ s2 -> s .k = 0 ;
10155
+ sappend (s , s2 );
10156
+
10157
+ s2 = new_stmt (cstate , BPF_ST );
10158
+ s2 -> s .k = off -> reg ;
10159
+ sappend (s , s2 );
10160
+ }
10161
+
10162
+ /**
10163
+ * gen_batadv_offsets_add_tvlv_len() - add tvlv_len to payload offsets
10164
+ * @cstate: our compiler state
10165
+ * @b0: instructions block to add to
10166
+ * @field_offset: offset of tvlv_len field within the batman-adv packet header
10167
+ *
10168
+ * Adds the tvlv_len value from/in a batman-adv packet header to the offsets
10169
+ * of cstate->off_linkpl and cstate->off_linktype.
10170
+ *
10171
+ * Return: The updated instructions block.
10172
+ */
10173
+ static struct block *
10174
+ gen_batadv_offsets_add_tvlv_len (compiler_state_t * cstate , struct block * b0 ,
10175
+ bpf_u_int32 field_offset )
10176
+ {
10177
+ struct slist s ;
10178
+
10179
+ s .next = NULL ;
10180
+
10181
+ /* turn constant-only offsets into variable offsets as we need to add
10182
+ * variable offset values (tvlv_len) to them later */
10183
+ gen_prepare_var_offset (cstate , & cstate -> off_linkpl , & s );
10184
+ gen_prepare_var_offset (cstate , & cstate -> off_linktype , & s );
10185
+
10186
+ /* load tvlv_len into X register */
10187
+ gen_batadv_loadx_tvlv_len (cstate , & cstate -> off_linkpl , field_offset , & s );
10188
+
10189
+ gen_batadv_offset_addx (cstate , & cstate -> off_linkpl , & s );
10190
+ gen_batadv_offset_addx (cstate , & cstate -> off_linktype , & s );
10191
+
10192
+ sappend (s .next , b0 -> head -> stmts );
10193
+ b0 -> head -> stmts = s .next ;
10194
+
10195
+ return b0 ;
10196
+ }
10197
+
10198
+ static struct block *
10199
+ gen_batadv_offsets_v15 (compiler_state_t * cstate , struct block * b0 , bpf_u_int32 type )
10045
10200
{
10046
10201
size_t offset ;
10202
+ size_t field_offset ;
10047
10203
10048
10204
switch (type ) {
10049
10205
case BATADV_BCAST : /* 0x01 */
@@ -10052,6 +10208,12 @@ gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type)
10052
10208
case BATADV_CODED : /* 0x02 */
10053
10209
offset = sizeof (struct batadv_coded_packet );
10054
10210
break ;
10211
+ case BATADV_MCAST : /* 0x05 */
10212
+ offset = sizeof (struct batadv_mcast_packet );
10213
+ field_offset = offsetof(struct batadv_mcast_packet , tvlv_len );
10214
+
10215
+ b0 = gen_batadv_offsets_add_tvlv_len (cstate , b0 , field_offset );
10216
+ break ;
10055
10217
case BATADV_UNICAST : /* 0x40 */
10056
10218
offset = sizeof (struct batadv_unicast_packet );
10057
10219
break ;
@@ -10061,32 +10223,31 @@ gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type)
10061
10223
case BATADV_UNICAST_4ADDR : /* 0x42 */
10062
10224
offset = sizeof (struct batadv_unicast_4addr_packet );
10063
10225
break ;
10064
- case BATADV_MCAST : /* 0x05 */
10065
- /* unsupported for now, needs variable offset to
10066
- * take tvlv_len into account
10067
- */
10068
- /* fall through */
10069
10226
default :
10070
10227
offset = 0 ;
10071
10228
}
10072
10229
10073
10230
if (offset )
10074
10231
gen_batadv_push_offset (cstate , (u_int )offset );
10232
+
10233
+ return b0 ;
10075
10234
}
10076
10235
10077
- static void
10078
- gen_batadv_offsets (compiler_state_t * cstate , bpf_u_int32 version , bpf_u_int32 type )
10236
+ static struct block *
10237
+ gen_batadv_offsets (compiler_state_t * cstate , struct block * b0 , bpf_u_int32 version , bpf_u_int32 type )
10079
10238
{
10080
10239
switch (version ) {
10081
10240
case 14 :
10082
10241
gen_batadv_offsets_v14 (cstate , type );
10083
10242
break ;
10084
10243
case 15 :
10085
- gen_batadv_offsets_v15 (cstate , type );
10244
+ b0 = gen_batadv_offsets_v15 (cstate , b0 , type );
10086
10245
break ;
10087
10246
default :
10088
10247
break ;
10089
10248
}
10249
+
10250
+ return b0 ;
10090
10251
}
10091
10252
10092
10253
struct block *
@@ -10109,7 +10270,7 @@ gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version,
10109
10270
10110
10271
if (has_type ) {
10111
10272
b0 = gen_batadv_check_type (cstate , b0 , version , type );
10112
- gen_batadv_offsets (cstate , version , type );
10273
+ b0 = gen_batadv_offsets (cstate , b0 , version , type );
10113
10274
}
10114
10275
10115
10276
return b0 ;
0 commit comments