@@ -223,7 +223,7 @@ struct packet_fanout {
223
223
unsigned int num_members ;
224
224
u16 id ;
225
225
u8 type ;
226
- u8 pad ;
226
+ u8 defrag ;
227
227
atomic_t rr_cur ;
228
228
struct list_head list ;
229
229
struct sock * arr [PACKET_FANOUT_MAX ];
@@ -447,6 +447,41 @@ static struct sock *fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb
447
447
return f -> arr [cur ];
448
448
}
449
449
450
+ static struct sk_buff * fanout_check_defrag (struct sk_buff * skb )
451
+ {
452
+ const struct iphdr * iph ;
453
+ u32 len ;
454
+
455
+ if (skb -> protocol != htons (ETH_P_IP ))
456
+ return skb ;
457
+
458
+ if (!pskb_may_pull (skb , sizeof (struct iphdr )))
459
+ return skb ;
460
+
461
+ iph = ip_hdr (skb );
462
+ if (iph -> ihl < 5 || iph -> version != 4 )
463
+ return skb ;
464
+ if (!pskb_may_pull (skb , iph -> ihl * 4 ))
465
+ return skb ;
466
+ iph = ip_hdr (skb );
467
+ len = ntohs (iph -> tot_len );
468
+ if (skb -> len < len || len < (iph -> ihl * 4 ))
469
+ return skb ;
470
+
471
+ if (ip_is_fragment (ip_hdr (skb ))) {
472
+ skb = skb_clone (skb , GFP_ATOMIC );
473
+ if (skb ) {
474
+ if (pskb_trim_rcsum (skb , len ))
475
+ return skb ;
476
+ memset (IPCB (skb ), 0 , sizeof (struct inet_skb_parm ));
477
+ if (ip_defrag (skb , IP_DEFRAG_AF_PACKET ))
478
+ return NULL ;
479
+ skb -> rxhash = 0 ;
480
+ }
481
+ }
482
+ return skb ;
483
+ }
484
+
450
485
static int packet_rcv_fanout_hash (struct sk_buff * skb , struct net_device * dev ,
451
486
struct packet_type * pt , struct net_device * orig_dev )
452
487
{
@@ -461,6 +496,12 @@ static int packet_rcv_fanout_hash(struct sk_buff *skb, struct net_device *dev,
461
496
return 0 ;
462
497
}
463
498
499
+ if (f -> defrag ) {
500
+ skb = fanout_check_defrag (skb );
501
+ if (!skb )
502
+ return 0 ;
503
+ }
504
+
464
505
skb_get_rxhash (skb );
465
506
466
507
sk = fanout_demux_hash (f , skb , num );
@@ -519,10 +560,12 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
519
560
spin_unlock (& f -> lock );
520
561
}
521
562
522
- static int fanout_add (struct sock * sk , u16 id , u8 type )
563
+ static int fanout_add (struct sock * sk , u16 id , u16 type_flags )
523
564
{
524
565
struct packet_sock * po = pkt_sk (sk );
525
566
struct packet_fanout * f , * match ;
567
+ u8 type = type_flags & 0xff ;
568
+ u8 defrag = (type_flags & PACKET_FANOUT_FLAG_DEFRAG ) ? 1 : 0 ;
526
569
int err ;
527
570
528
571
switch (type ) {
@@ -548,12 +591,15 @@ static int fanout_add(struct sock *sk, u16 id, u8 type)
548
591
break ;
549
592
}
550
593
}
594
+ if (match && match -> defrag != defrag )
595
+ return - EINVAL ;
551
596
if (!match ) {
552
597
match = kzalloc (sizeof (* match ), GFP_KERNEL );
553
598
if (match ) {
554
599
write_pnet (& match -> net , sock_net (sk ));
555
600
match -> id = id ;
556
601
match -> type = type ;
602
+ match -> defrag = defrag ;
557
603
atomic_set (& match -> rr_cur , 0 );
558
604
INIT_LIST_HEAD (& match -> list );
559
605
spin_lock_init (& match -> lock );
0 commit comments