~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/xfrm/xfrm_ipcomp.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /net/xfrm/xfrm_ipcomp.c (Version linux-6.12-rc7) and /net/xfrm/xfrm_ipcomp.c (Version policy-sample)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*                                                
  3  * IP Payload Compression Protocol (IPComp) -     
  4  *                                                
  5  * Copyright (c) 2003 James Morris <jmorris@in    
  6  * Copyright (c) 2003-2008 Herbert Xu <herbert    
  7  *                                                
  8  * Todo:                                          
  9  *   - Tunable compression parameters.            
 10  *   - Compression stats.                         
 11  *   - Adaptive compression.                      
 12  */                                               
 13                                                   
 14 #include <linux/crypto.h>                         
 15 #include <linux/err.h>                            
 16 #include <linux/list.h>                           
 17 #include <linux/module.h>                         
 18 #include <linux/mutex.h>                          
 19 #include <linux/percpu.h>                         
 20 #include <linux/slab.h>                           
 21 #include <linux/smp.h>                            
 22 #include <linux/vmalloc.h>                        
 23 #include <net/ip.h>                               
 24 #include <net/ipcomp.h>                           
 25 #include <net/xfrm.h>                             
 26                                                   
 27 struct ipcomp_tfms {                              
 28         struct list_head list;                    
 29         struct crypto_comp * __percpu *tfms;      
 30         int users;                                
 31 };                                                
 32                                                   
 33 static DEFINE_MUTEX(ipcomp_resource_mutex);       
 34 static void * __percpu *ipcomp_scratches;         
 35 static int ipcomp_scratch_users;                  
 36 static LIST_HEAD(ipcomp_tfms_list);               
 37                                                   
 38 static int ipcomp_decompress(struct xfrm_state    
 39 {                                                 
 40         struct ipcomp_data *ipcd = x->data;       
 41         const int plen = skb->len;                
 42         int dlen = IPCOMP_SCRATCH_SIZE;           
 43         const u8 *start = skb->data;              
 44         u8 *scratch = *this_cpu_ptr(ipcomp_scr    
 45         struct crypto_comp *tfm = *this_cpu_pt    
 46         int err = crypto_comp_decompress(tfm,     
 47         int len;                                  
 48                                                   
 49         if (err)                                  
 50                 return err;                       
 51                                                   
 52         if (dlen < (plen + sizeof(struct ip_co    
 53                 return -EINVAL;                   
 54                                                   
 55         len = dlen - plen;                        
 56         if (len > skb_tailroom(skb))              
 57                 len = skb_tailroom(skb);          
 58                                                   
 59         __skb_put(skb, len);                      
 60                                                   
 61         len += plen;                              
 62         skb_copy_to_linear_data(skb, scratch,     
 63                                                   
 64         while ((scratch += len, dlen -= len) >    
 65                 skb_frag_t *frag;                 
 66                 struct page *page;                
 67                                                   
 68                 if (WARN_ON(skb_shinfo(skb)->n    
 69                         return -EMSGSIZE;         
 70                                                   
 71                 frag = skb_shinfo(skb)->frags     
 72                 page = alloc_page(GFP_ATOMIC);    
 73                                                   
 74                 if (!page)                        
 75                         return -ENOMEM;           
 76                                                   
 77                 len = PAGE_SIZE;                  
 78                 if (dlen < len)                   
 79                         len = dlen;               
 80                                                   
 81                 skb_frag_fill_page_desc(frag,     
 82                 memcpy(skb_frag_address(frag),    
 83                                                   
 84                 skb->truesize += len;             
 85                 skb->data_len += len;             
 86                 skb->len += len;                  
 87                                                   
 88                 skb_shinfo(skb)->nr_frags++;      
 89         }                                         
 90                                                   
 91         return 0;                                 
 92 }                                                 
 93                                                   
 94 int ipcomp_input(struct xfrm_state *x, struct     
 95 {                                                 
 96         int nexthdr;                              
 97         int err = -ENOMEM;                        
 98         struct ip_comp_hdr *ipch;                 
 99                                                   
100         if (skb_linearize_cow(skb))               
101                 goto out;                         
102                                                   
103         skb->ip_summed = CHECKSUM_NONE;           
104                                                   
105         /* Remove ipcomp header and decompress    
106         ipch = (void *)skb->data;                 
107         nexthdr = ipch->nexthdr;                  
108                                                   
109         skb->transport_header = skb->network_h    
110         __skb_pull(skb, sizeof(*ipch));           
111         err = ipcomp_decompress(x, skb);          
112         if (err)                                  
113                 goto out;                         
114                                                   
115         err = nexthdr;                            
116                                                   
117 out:                                              
118         return err;                               
119 }                                                 
120 EXPORT_SYMBOL_GPL(ipcomp_input);                  
121                                                   
122 static int ipcomp_compress(struct xfrm_state *    
123 {                                                 
124         struct ipcomp_data *ipcd = x->data;       
125         const int plen = skb->len;                
126         int dlen = IPCOMP_SCRATCH_SIZE;           
127         u8 *start = skb->data;                    
128         struct crypto_comp *tfm;                  
129         u8 *scratch;                              
130         int err;                                  
131                                                   
132         local_bh_disable();                       
133         scratch = *this_cpu_ptr(ipcomp_scratch    
134         tfm = *this_cpu_ptr(ipcd->tfms);          
135         err = crypto_comp_compress(tfm, start,    
136         if (err)                                  
137                 goto out;                         
138                                                   
139         if ((dlen + sizeof(struct ip_comp_hdr)    
140                 err = -EMSGSIZE;                  
141                 goto out;                         
142         }                                         
143                                                   
144         memcpy(start + sizeof(struct ip_comp_h    
145         local_bh_enable();                        
146                                                   
147         pskb_trim(skb, dlen + sizeof(struct ip    
148         return 0;                                 
149                                                   
150 out:                                              
151         local_bh_enable();                        
152         return err;                               
153 }                                                 
154                                                   
155 int ipcomp_output(struct xfrm_state *x, struct    
156 {                                                 
157         int err;                                  
158         struct ip_comp_hdr *ipch;                 
159         struct ipcomp_data *ipcd = x->data;       
160                                                   
161         if (skb->len < ipcd->threshold) {         
162                 /* Don't bother compressing */    
163                 goto out_ok;                      
164         }                                         
165                                                   
166         if (skb_linearize_cow(skb))               
167                 goto out_ok;                      
168                                                   
169         err = ipcomp_compress(x, skb);            
170                                                   
171         if (err) {                                
172                 goto out_ok;                      
173         }                                         
174                                                   
175         /* Install ipcomp header, convert into    
176         ipch = ip_comp_hdr(skb);                  
177         ipch->nexthdr = *skb_mac_header(skb);     
178         ipch->flags = 0;                          
179         ipch->cpi = htons((u16 )ntohl(x->id.sp    
180         *skb_mac_header(skb) = IPPROTO_COMP;      
181 out_ok:                                           
182         skb_push(skb, -skb_network_offset(skb)    
183         return 0;                                 
184 }                                                 
185 EXPORT_SYMBOL_GPL(ipcomp_output);                 
186                                                   
187 static void ipcomp_free_scratches(void)           
188 {                                                 
189         int i;                                    
190         void * __percpu *scratches;               
191                                                   
192         if (--ipcomp_scratch_users)               
193                 return;                           
194                                                   
195         scratches = ipcomp_scratches;             
196         if (!scratches)                           
197                 return;                           
198                                                   
199         for_each_possible_cpu(i)                  
200                 vfree(*per_cpu_ptr(scratches,     
201                                                   
202         free_percpu(scratches);                   
203         ipcomp_scratches = NULL;                  
204 }                                                 
205                                                   
206 static void * __percpu *ipcomp_alloc_scratches    
207 {                                                 
208         void * __percpu *scratches;               
209         int i;                                    
210                                                   
211         if (ipcomp_scratch_users++)               
212                 return ipcomp_scratches;          
213                                                   
214         scratches = alloc_percpu(void *);         
215         if (!scratches)                           
216                 return NULL;                      
217                                                   
218         ipcomp_scratches = scratches;             
219                                                   
220         for_each_possible_cpu(i) {                
221                 void *scratch;                    
222                                                   
223                 scratch = vmalloc_node(IPCOMP_    
224                 if (!scratch)                     
225                         return NULL;              
226                 *per_cpu_ptr(scratches, i) = s    
227         }                                         
228                                                   
229         return scratches;                         
230 }                                                 
231                                                   
232 static void ipcomp_free_tfms(struct crypto_com    
233 {                                                 
234         struct ipcomp_tfms *pos;                  
235         int cpu;                                  
236                                                   
237         list_for_each_entry(pos, &ipcomp_tfms_    
238                 if (pos->tfms == tfms)            
239                         break;                    
240         }                                         
241                                                   
242         WARN_ON(list_entry_is_head(pos, &ipcom    
243                                                   
244         if (--pos->users)                         
245                 return;                           
246                                                   
247         list_del(&pos->list);                     
248         kfree(pos);                               
249                                                   
250         if (!tfms)                                
251                 return;                           
252                                                   
253         for_each_possible_cpu(cpu) {              
254                 struct crypto_comp *tfm = *per    
255                 crypto_free_comp(tfm);            
256         }                                         
257         free_percpu(tfms);                        
258 }                                                 
259                                                   
260 static struct crypto_comp * __percpu *ipcomp_a    
261 {                                                 
262         struct ipcomp_tfms *pos;                  
263         struct crypto_comp * __percpu *tfms;      
264         int cpu;                                  
265                                                   
266                                                   
267         list_for_each_entry(pos, &ipcomp_tfms_    
268                 struct crypto_comp *tfm;          
269                                                   
270                 /* This can be any valid CPU I    
271                 tfm = this_cpu_read(*pos->tfms    
272                                                   
273                 if (!strcmp(crypto_comp_name(t    
274                         pos->users++;             
275                         return pos->tfms;         
276                 }                                 
277         }                                         
278                                                   
279         pos = kmalloc(sizeof(*pos), GFP_KERNEL    
280         if (!pos)                                 
281                 return NULL;                      
282                                                   
283         pos->users = 1;                           
284         INIT_LIST_HEAD(&pos->list);               
285         list_add(&pos->list, &ipcomp_tfms_list    
286                                                   
287         pos->tfms = tfms = alloc_percpu(struct    
288         if (!tfms)                                
289                 goto error;                       
290                                                   
291         for_each_possible_cpu(cpu) {              
292                 struct crypto_comp *tfm = cryp    
293                                                   
294                 if (IS_ERR(tfm))                  
295                         goto error;               
296                 *per_cpu_ptr(tfms, cpu) = tfm;    
297         }                                         
298                                                   
299         return tfms;                              
300                                                   
301 error:                                            
302         ipcomp_free_tfms(tfms);                   
303         return NULL;                              
304 }                                                 
305                                                   
306 static void ipcomp_free_data(struct ipcomp_dat    
307 {                                                 
308         if (ipcd->tfms)                           
309                 ipcomp_free_tfms(ipcd->tfms);     
310         ipcomp_free_scratches();                  
311 }                                                 
312                                                   
313 void ipcomp_destroy(struct xfrm_state *x)         
314 {                                                 
315         struct ipcomp_data *ipcd = x->data;       
316         if (!ipcd)                                
317                 return;                           
318         xfrm_state_delete_tunnel(x);              
319         mutex_lock(&ipcomp_resource_mutex);       
320         ipcomp_free_data(ipcd);                   
321         mutex_unlock(&ipcomp_resource_mutex);     
322         kfree(ipcd);                              
323 }                                                 
324 EXPORT_SYMBOL_GPL(ipcomp_destroy);                
325                                                   
326 int ipcomp_init_state(struct xfrm_state *x, st    
327 {                                                 
328         int err;                                  
329         struct ipcomp_data *ipcd;                 
330         struct xfrm_algo_desc *calg_desc;         
331                                                   
332         err = -EINVAL;                            
333         if (!x->calg) {                           
334                 NL_SET_ERR_MSG(extack, "Missin    
335                 goto out;                         
336         }                                         
337                                                   
338         if (x->encap) {                           
339                 NL_SET_ERR_MSG(extack, "IPComp    
340                 goto out;                         
341         }                                         
342                                                   
343         err = -ENOMEM;                            
344         ipcd = kzalloc(sizeof(*ipcd), GFP_KERN    
345         if (!ipcd)                                
346                 goto out;                         
347                                                   
348         mutex_lock(&ipcomp_resource_mutex);       
349         if (!ipcomp_alloc_scratches())            
350                 goto error;                       
351                                                   
352         ipcd->tfms = ipcomp_alloc_tfms(x->calg    
353         if (!ipcd->tfms)                          
354                 goto error;                       
355         mutex_unlock(&ipcomp_resource_mutex);     
356                                                   
357         calg_desc = xfrm_calg_get_byname(x->ca    
358         BUG_ON(!calg_desc);                       
359         ipcd->threshold = calg_desc->uinfo.com    
360         x->data = ipcd;                           
361         err = 0;                                  
362 out:                                              
363         return err;                               
364                                                   
365 error:                                            
366         ipcomp_free_data(ipcd);                   
367         mutex_unlock(&ipcomp_resource_mutex);     
368         kfree(ipcd);                              
369         goto out;                                 
370 }                                                 
371 EXPORT_SYMBOL_GPL(ipcomp_init_state);             
372                                                   
373 MODULE_LICENSE("GPL");                            
374 MODULE_DESCRIPTION("IP Payload Compression Pro    
375 MODULE_AUTHOR("James Morris <jmorris@intercode    
376                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php