@@ -10197,9 +10197,165 @@ gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type)
10197
10197
}
10198
10198
10199
10199
static void
10200
- gen_batadv_offsets_v15 (compiler_state_t * cstate , bpf_u_int32 type )
10200
+ gen_prepare_var_offset (compiler_state_t * cstate , bpf_abs_offset * off , struct slist * s )
10201
+ {
10202
+ struct slist * s2 ;
10203
+
10204
+ if (!off -> is_variable )
10205
+ off -> is_variable = 1 ;
10206
+ if (off -> reg == -1 ) {
10207
+ off -> reg = alloc_reg (cstate );
10208
+
10209
+ s2 = new_stmt (cstate , BPF_ALU |BPF_AND );
10210
+ s2 -> s .k = 0 ;
10211
+ s2 = new_stmt (cstate , BPF_ST );
10212
+ s2 -> s .k = off -> reg ;
10213
+ sappend (s , s2 );
10214
+ }
10215
+ }
10216
+
10217
+ /**
10218
+ * gen_batadv_loadx_tvlv_len_offset() - load offset to tvlv_len into X
10219
+ * @cstate: our compiler state
10220
+ * @bat_offset: our offset to the start of the batman-adv packet header
10221
+ * @field_offset: offset of tvlv_len field within the batman-adv packet header
10222
+ * @s: instructions list to append to
10223
+ *
10224
+ * Will load: X = bat_offset + field_offset. So that [X] in the packet will
10225
+ * point to the most-significant byte of the tvlv_len in a batman-adv packet.
10226
+ */
10227
+ static void
10228
+ gen_batadv_loadx_tvlv_len_offset (compiler_state_t * cstate ,
10229
+ bpf_abs_offset * bat_offset ,
10230
+ bpf_u_int32 field_offset , struct slist * s )
10231
+ {
10232
+ struct slist * s2 ;
10233
+
10234
+ s2 = new_stmt (cstate , BPF_LD |BPF_MEM );
10235
+ s2 -> s .k = bat_offset -> reg ;
10236
+ sappend (s , s2 );
10237
+
10238
+ s2 = new_stmt (cstate , BPF_ALU |BPF_ADD |BPF_K );
10239
+ s2 -> s .k = bat_offset -> constant_part + field_offset ;
10240
+ sappend (s , s2 );
10241
+
10242
+ s2 = new_stmt (cstate , BPF_MISC |BPF_TAX );
10243
+ s2 -> s .k = 0 ;
10244
+ sappend (s , s2 );
10245
+ }
10246
+
10247
+ /**
10248
+ * gen_batadv_loadx_tvlv_len() - load tvlv_len value into X
10249
+ * @cstate: our compiler state
10250
+ * @bat_offset: our offset to the start of the batman-adv packet header
10251
+ * @field_offset: offset of tvlv_len field within the batman-adv packet header
10252
+ * @s: instructions list to append to
10253
+ *
10254
+ * Loads the value of the 2 byte tvlv_len field in a given batman-adv packet
10255
+ * header into the X register.
10256
+ */
10257
+ static void
10258
+ gen_batadv_loadx_tvlv_len (compiler_state_t * cstate , bpf_abs_offset * bat_offset ,
10259
+ bpf_u_int32 field_offset , struct slist * s )
10260
+ {
10261
+ struct slist * s2 ;
10262
+
10263
+ /* load offset to tvlv_len field into X register */
10264
+ gen_batadv_loadx_tvlv_len_offset (cstate , bat_offset , field_offset , s );
10265
+
10266
+ /* clear A register */
10267
+ s2 = new_stmt (cstate , BPF_ALU |BPF_AND |BPF_K );
10268
+ s2 -> s .k = 0 ;
10269
+ sappend (s , s2 );
10270
+
10271
+ /* load most significant byte of tvlv_len */
10272
+ s2 = new_stmt (cstate , BPF_LD |BPF_IND |BPF_B );
10273
+ s2 -> s .k = 0 ;
10274
+ sappend (s , s2 );
10275
+
10276
+ /* multiply by 2^8 for real value of MSB, make room for LSB */
10277
+ s2 = new_stmt (cstate , BPF_ALU |BPF_LSH |BPF_K );
10278
+ s2 -> s .k = 8 ;
10279
+ sappend (s , s2 );
10280
+
10281
+ /* load least significant byte of tvlv_len */
10282
+ s2 = new_stmt (cstate , BPF_LD |BPF_IND |BPF_B );
10283
+ s2 -> s .k = 1 ;
10284
+ sappend (s , s2 );
10285
+
10286
+ s2 = new_stmt (cstate , BPF_MISC |BPF_TAX );
10287
+ s2 -> s .k = 0 ;
10288
+ sappend (s , s2 );
10289
+ }
10290
+
10291
+ /**
10292
+ * gen_batadv_offset_addx() - add X register to a variable offset
10293
+ * @cstate: our compiler state
10294
+ * @off: the (variable) offset to add to
10295
+ * @s: instructions list to append to
10296
+ *
10297
+ * Adds the value from the X register to the given variable offset.
10298
+ */
10299
+ static void
10300
+ gen_batadv_offset_addx (compiler_state_t * cstate , bpf_abs_offset * off ,
10301
+ struct slist * s )
10302
+ {
10303
+ struct slist * s2 ;
10304
+
10305
+ s2 = new_stmt (cstate , BPF_LD |BPF_MEM );
10306
+ s2 -> s .k = off -> reg ;
10307
+ sappend (s , s2 );
10308
+
10309
+ s2 = new_stmt (cstate , BPF_ALU |BPF_ADD |BPF_X );
10310
+ s2 -> s .k = 0 ;
10311
+ sappend (s , s2 );
10312
+
10313
+ s2 = new_stmt (cstate , BPF_ST );
10314
+ s2 -> s .k = off -> reg ;
10315
+ sappend (s , s2 );
10316
+ }
10317
+
10318
+ /**
10319
+ * gen_batadv_offsets_add_tvlv_len() - add tvlv_len to payload offsets
10320
+ * @cstate: our compiler state
10321
+ * @b0: instructions block to add to
10322
+ * @field_offset: offset of tvlv_len field within the batman-adv packet header
10323
+ *
10324
+ * Adds the tvlv_len value from/in a batman-adv packet header to the offsets
10325
+ * of cstate->off_linkpl and cstate->off_linktype.
10326
+ *
10327
+ * Return: The updated instructions block.
10328
+ */
10329
+ static struct block *
10330
+ gen_batadv_offsets_add_tvlv_len (compiler_state_t * cstate , struct block * b0 ,
10331
+ bpf_u_int32 field_offset )
10332
+ {
10333
+ struct slist s ;
10334
+
10335
+ s .next = NULL ;
10336
+
10337
+ /* turn constant-only offsets into variable offsets as we need to add
10338
+ * variable offset values (tvlv_len) to them later */
10339
+ gen_prepare_var_offset (cstate , & cstate -> off_linkpl , & s );
10340
+ gen_prepare_var_offset (cstate , & cstate -> off_linktype , & s );
10341
+
10342
+ /* load tvlv_len into X register */
10343
+ gen_batadv_loadx_tvlv_len (cstate , & cstate -> off_linkpl , field_offset , & s );
10344
+
10345
+ gen_batadv_offset_addx (cstate , & cstate -> off_linkpl , & s );
10346
+ gen_batadv_offset_addx (cstate , & cstate -> off_linktype , & s );
10347
+
10348
+ sappend (s .next , b0 -> head -> stmts );
10349
+ b0 -> head -> stmts = s .next ;
10350
+
10351
+ return b0 ;
10352
+ }
10353
+
10354
+ static struct block *
10355
+ gen_batadv_offsets_v15 (compiler_state_t * cstate , struct block * b0 , bpf_u_int32 type )
10201
10356
{
10202
10357
size_t offset ;
10358
+ bpf_u_int32 field_offset ;
10203
10359
10204
10360
switch (type ) {
10205
10361
case BATADV_BCAST : /* 0x01 */
@@ -10208,6 +10364,13 @@ gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type)
10208
10364
case BATADV_CODED : /* 0x02 */
10209
10365
offset = sizeof (struct batadv_coded_packet );
10210
10366
break ;
10367
+ case BATADV_MCAST : /* 0x05 */
10368
+ offset = sizeof (struct batadv_mcast_packet );
10369
+ field_offset = (bpf_u_int32 )offsetof(struct batadv_mcast_packet ,
10370
+ tvlv_len );
10371
+
10372
+ b0 = gen_batadv_offsets_add_tvlv_len (cstate , b0 , field_offset );
10373
+ break ;
10211
10374
case BATADV_UNICAST : /* 0x40 */
10212
10375
offset = sizeof (struct batadv_unicast_packet );
10213
10376
break ;
@@ -10217,32 +10380,31 @@ gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type)
10217
10380
case BATADV_UNICAST_4ADDR : /* 0x42 */
10218
10381
offset = sizeof (struct batadv_unicast_4addr_packet );
10219
10382
break ;
10220
- case BATADV_MCAST : /* 0x05 */
10221
- /* unsupported for now, needs variable offset to
10222
- * take tvlv_len into account
10223
- */
10224
- /* fall through */
10225
10383
default :
10226
10384
offset = 0 ;
10227
10385
}
10228
10386
10229
10387
if (offset )
10230
10388
gen_batadv_push_offset (cstate , (u_int )offset );
10389
+
10390
+ return b0 ;
10231
10391
}
10232
10392
10233
- static void
10234
- gen_batadv_offsets (compiler_state_t * cstate , bpf_u_int32 version , bpf_u_int32 type )
10393
+ static struct block *
10394
+ gen_batadv_offsets (compiler_state_t * cstate , struct block * b0 , bpf_u_int32 version , bpf_u_int32 type )
10235
10395
{
10236
10396
switch (version ) {
10237
10397
case 14 :
10238
10398
gen_batadv_offsets_v14 (cstate , type );
10239
10399
break ;
10240
10400
case 15 :
10241
- gen_batadv_offsets_v15 (cstate , type );
10401
+ b0 = gen_batadv_offsets_v15 (cstate , b0 , type );
10242
10402
break ;
10243
10403
default :
10244
10404
break ;
10245
10405
}
10406
+
10407
+ return b0 ;
10246
10408
}
10247
10409
10248
10410
struct block *
@@ -10265,7 +10427,7 @@ gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version,
10265
10427
10266
10428
if (has_type ) {
10267
10429
b0 = gen_batadv_check_type (cstate , b0 , version , type );
10268
- gen_batadv_offsets (cstate , version , type );
10430
+ b0 = gen_batadv_offsets (cstate , b0 , version , type );
10269
10431
}
10270
10432
10271
10433
return b0 ;
0 commit comments