@@ -71,35 +71,82 @@ struct nf_ct_frag6_queue
7171};
7272
7373static struct inet_frags nf_frags ;
74- static struct netns_frags nf_init_frags ;
7574
7675#ifdef CONFIG_SYSCTL
7776static struct ctl_table nf_ct_frag6_sysctl_table [] = {
7877 {
7978 .procname = "nf_conntrack_frag6_timeout" ,
80- .data = & nf_init_frags .timeout ,
79+ .data = & init_net . nf_frag . frags .timeout ,
8180 .maxlen = sizeof (unsigned int ),
8281 .mode = 0644 ,
8382 .proc_handler = proc_dointvec_jiffies ,
8483 },
8584 {
8685 .procname = "nf_conntrack_frag6_low_thresh" ,
87- .data = & nf_init_frags .low_thresh ,
86+ .data = & init_net . nf_frag . frags .low_thresh ,
8887 .maxlen = sizeof (unsigned int ),
8988 .mode = 0644 ,
9089 .proc_handler = proc_dointvec ,
9190 },
9291 {
9392 .procname = "nf_conntrack_frag6_high_thresh" ,
94- .data = & nf_init_frags .high_thresh ,
93+ .data = & init_net . nf_frag . frags .high_thresh ,
9594 .maxlen = sizeof (unsigned int ),
9695 .mode = 0644 ,
9796 .proc_handler = proc_dointvec ,
9897 },
9998 { }
10099};
101100
102- static struct ctl_table_header * nf_ct_frag6_sysctl_header ;
101+ static int __net_init nf_ct_frag6_sysctl_register (struct net * net )
102+ {
103+ struct ctl_table * table ;
104+ struct ctl_table_header * hdr ;
105+
106+ table = nf_ct_frag6_sysctl_table ;
107+ if (!net_eq (net , & init_net )) {
108+ table = kmemdup (table , sizeof (nf_ct_frag6_sysctl_table ),
109+ GFP_KERNEL );
110+ if (table == NULL )
111+ goto err_alloc ;
112+
113+ table [0 ].data = & net -> ipv6 .frags .high_thresh ;
114+ table [1 ].data = & net -> ipv6 .frags .low_thresh ;
115+ table [2 ].data = & net -> ipv6 .frags .timeout ;
116+ }
117+
118+ hdr = register_net_sysctl (net , "net/netfilter" , table );
119+ if (hdr == NULL )
120+ goto err_reg ;
121+
122+ net -> ipv6 .sysctl .frags_hdr = hdr ;
123+ return 0 ;
124+
125+ err_reg :
126+ if (!net_eq (net , & init_net ))
127+ kfree (table );
128+ err_alloc :
129+ return - ENOMEM ;
130+ }
131+
132+ static void __net_exit nf_ct_frags6_sysctl_unregister (struct net * net )
133+ {
134+ struct ctl_table * table ;
135+
136+ table = net -> nf_frag .sysctl .frags_hdr -> ctl_table_arg ;
137+ unregister_net_sysctl_table (net -> nf_frag .sysctl .frags_hdr );
138+ if (!net_eq (net , & init_net ))
139+ kfree (table );
140+ }
141+
142+ #else
143+ static int __net_init nf_ct_frag6_sysctl_register (struct net * net )
144+ {
145+ return 0 ;
146+ }
147+ static void __net_exit nf_ct_frags6_sysctl_unregister (struct net * net )
148+ {
149+ }
103150#endif
104151
105152static unsigned int nf_hashfn (struct inet_frag_queue * q )
@@ -131,13 +178,6 @@ static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq)
131178 inet_frag_kill (& fq -> q , & nf_frags );
132179}
133180
134- static void nf_ct_frag6_evictor (void )
135- {
136- local_bh_disable ();
137- inet_frag_evictor (& nf_init_frags , & nf_frags );
138- local_bh_enable ();
139- }
140-
141181static void nf_ct_frag6_expire (unsigned long data )
142182{
143183 struct nf_ct_frag6_queue * fq ;
@@ -158,9 +198,9 @@ static void nf_ct_frag6_expire(unsigned long data)
158198}
159199
160200/* Creation primitives. */
161-
162- static __inline__ struct nf_ct_frag6_queue *
163- fq_find ( __be32 id , u32 user , struct in6_addr * src , struct in6_addr * dst )
201+ static inline struct nf_ct_frag6_queue * fq_find ( struct net * net , __be32 id ,
202+ u32 user , struct in6_addr * src ,
203+ struct in6_addr * dst )
164204{
165205 struct inet_frag_queue * q ;
166206 struct ip6_create_arg arg ;
@@ -174,7 +214,7 @@ fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst)
174214 read_lock_bh (& nf_frags .lock );
175215 hash = inet6_hash_frag (id , src , dst , nf_frags .rnd );
176216
177- q = inet_frag_find (& nf_init_frags , & nf_frags , & arg , hash );
217+ q = inet_frag_find (& net -> nf_frag . frags , & nf_frags , & arg , hash );
178218 local_bh_enable ();
179219 if (q == NULL )
180220 goto oom ;
@@ -312,7 +352,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
312352 fq -> q .meat += skb -> len ;
313353 if (payload_len > fq -> q .max_size )
314354 fq -> q .max_size = payload_len ;
315- atomic_add (skb -> truesize , & nf_init_frags . mem );
355+ atomic_add (skb -> truesize , & fq -> q . net -> mem );
316356
317357 /* The first fragment.
318358 * nhoffset is obtained from the first fragment, of course.
@@ -322,7 +362,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
322362 fq -> q .last_in |= INET_FRAG_FIRST_IN ;
323363 }
324364 write_lock (& nf_frags .lock );
325- list_move_tail (& fq -> q .lru_list , & nf_init_frags . lru_list );
365+ list_move_tail (& fq -> q .lru_list , & fq -> q . net -> lru_list );
326366 write_unlock (& nf_frags .lock );
327367 return 0 ;
328368
@@ -391,7 +431,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
391431 clone -> ip_summed = head -> ip_summed ;
392432
393433 NFCT_FRAG6_CB (clone )-> orig = NULL ;
394- atomic_add (clone -> truesize , & nf_init_frags . mem );
434+ atomic_add (clone -> truesize , & fq -> q . net -> mem );
395435 }
396436
397437 /* We have to remove fragment header from datagram and to relocate
@@ -415,7 +455,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
415455 head -> csum = csum_add (head -> csum , fp -> csum );
416456 head -> truesize += fp -> truesize ;
417457 }
418- atomic_sub (head -> truesize , & nf_init_frags . mem );
458+ atomic_sub (head -> truesize , & fq -> q . net -> mem );
419459
420460 head -> local_df = 1 ;
421461 head -> next = NULL ;
@@ -527,6 +567,8 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
527567{
528568 struct sk_buff * clone ;
529569 struct net_device * dev = skb -> dev ;
570+ struct net * net = skb_dst (skb ) ? dev_net (skb_dst (skb )-> dev )
571+ : dev_net (skb -> dev );
530572 struct frag_hdr * fhdr ;
531573 struct nf_ct_frag6_queue * fq ;
532574 struct ipv6hdr * hdr ;
@@ -560,10 +602,13 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
560602 hdr = ipv6_hdr (clone );
561603 fhdr = (struct frag_hdr * )skb_transport_header (clone );
562604
563- if (atomic_read (& nf_init_frags .mem ) > nf_init_frags .high_thresh )
564- nf_ct_frag6_evictor ();
605+ if (atomic_read (& net -> nf_frag .frags .mem ) > net -> nf_frag .frags .high_thresh ) {
606+ local_bh_disable ();
607+ inet_frag_evictor (& net -> nf_frag .frags , & nf_frags );
608+ local_bh_enable ();
609+ }
565610
566- fq = fq_find (fhdr -> identification , user , & hdr -> saddr , & hdr -> daddr );
611+ fq = fq_find (net , fhdr -> identification , user , & hdr -> saddr , & hdr -> daddr );
567612 if (fq == NULL ) {
568613 pr_debug ("Can't find and can't create new queue\n" );
569614 goto ret_orig ;
@@ -621,8 +666,31 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
621666 nf_conntrack_put_reasm (skb );
622667}
623668
669+ static int nf_ct_net_init (struct net * net )
670+ {
671+ net -> nf_frag .frags .high_thresh = IPV6_FRAG_HIGH_THRESH ;
672+ net -> nf_frag .frags .low_thresh = IPV6_FRAG_LOW_THRESH ;
673+ net -> nf_frag .frags .timeout = IPV6_FRAG_TIMEOUT ;
674+ inet_frags_init_net (& net -> nf_frag .frags );
675+
676+ return nf_ct_frag6_sysctl_register (net );
677+ }
678+
679+ static void nf_ct_net_exit (struct net * net )
680+ {
681+ nf_ct_frags6_sysctl_unregister (net );
682+ inet_frags_exit_net (& net -> nf_frag .frags , & nf_frags );
683+ }
684+
685+ static struct pernet_operations nf_ct_net_ops = {
686+ .init = nf_ct_net_init ,
687+ .exit = nf_ct_net_exit ,
688+ };
689+
624690int nf_ct_frag6_init (void )
625691{
692+ int ret = 0 ;
693+
626694 nf_frags .hashfn = nf_hashfn ;
627695 nf_frags .constructor = ip6_frag_init ;
628696 nf_frags .destructor = NULL ;
@@ -631,32 +699,17 @@ int nf_ct_frag6_init(void)
631699 nf_frags .match = ip6_frag_match ;
632700 nf_frags .frag_expire = nf_ct_frag6_expire ;
633701 nf_frags .secret_interval = 10 * 60 * HZ ;
634- nf_init_frags .timeout = IPV6_FRAG_TIMEOUT ;
635- nf_init_frags .high_thresh = IPV6_FRAG_HIGH_THRESH ;
636- nf_init_frags .low_thresh = IPV6_FRAG_LOW_THRESH ;
637- inet_frags_init_net (& nf_init_frags );
638702 inet_frags_init (& nf_frags );
639703
640- #ifdef CONFIG_SYSCTL
641- nf_ct_frag6_sysctl_header = register_net_sysctl (& init_net , "net/netfilter" ,
642- nf_ct_frag6_sysctl_table );
643- if (!nf_ct_frag6_sysctl_header ) {
704+ ret = register_pernet_subsys (& nf_ct_net_ops );
705+ if (ret )
644706 inet_frags_fini (& nf_frags );
645- return - ENOMEM ;
646- }
647- #endif
648707
649- return 0 ;
708+ return ret ;
650709}
651710
652711void nf_ct_frag6_cleanup (void )
653712{
654- #ifdef CONFIG_SYSCTL
655- unregister_net_sysctl_table (nf_ct_frag6_sysctl_header );
656- nf_ct_frag6_sysctl_header = NULL ;
657- #endif
713+ unregister_pernet_subsys (& nf_ct_net_ops );
658714 inet_frags_fini (& nf_frags );
659-
660- nf_init_frags .low_thresh = 0 ;
661- nf_ct_frag6_evictor ();
662715}
0 commit comments