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

TOMOYO Linux Cross Reference
Linux/net/ipv4/esp4.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include <linux/config.h>
  2 #include <linux/module.h>
  3 #include <net/inet_ecn.h>
  4 #include <net/ip.h>
  5 #include <net/xfrm.h>
  6 #include <net/esp.h>
  7 #include <asm/scatterlist.h>
  8 #include <linux/crypto.h>
  9 #include <linux/pfkeyv2.h>
 10 #include <linux/random.h>
 11 #include <net/icmp.h>
 12 #include <net/udp.h>
 13 
 14 #define MAX_SG_ONSTACK 4
 15 
 16 /* decapsulation data for use when post-processing */
 17 struct esp_decap_data {
 18         xfrm_address_t  saddr;
 19         __u16           sport;
 20         __u8            proto;
 21 };
 22 
 23 int esp_output(struct sk_buff *skb)
 24 {
 25         int err;
 26         struct dst_entry *dst = skb->dst;
 27         struct xfrm_state *x  = dst->xfrm;
 28         struct iphdr *iph, *top_iph;
 29         struct ip_esp_hdr *esph;
 30         struct crypto_tfm *tfm;
 31         struct esp_data *esp;
 32         struct sk_buff *trailer;
 33         struct udphdr *uh = NULL;
 34         struct xfrm_encap_tmpl *encap = NULL;
 35         int blksize;
 36         int clen;
 37         int alen;
 38         int nfrags;
 39         union {
 40                 struct iphdr    iph;
 41                 char            buf[60];
 42         } tmp_iph;
 43 
 44         /* First, if the skb is not checksummed, complete checksum. */
 45         if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL) {
 46                 err = -EINVAL;
 47                 goto error_nolock;
 48         }
 49 
 50         spin_lock_bh(&x->lock);
 51         err = xfrm_check_output(x, skb, AF_INET);
 52         if (err)
 53                 goto error;
 54         err = -ENOMEM;
 55 
 56         /* Strip IP header in transport mode. Save it. */
 57         if (!x->props.mode) {
 58                 iph = skb->nh.iph;
 59                 memcpy(&tmp_iph, iph, iph->ihl*4);
 60                 __skb_pull(skb, iph->ihl*4);
 61         }
 62         /* Now skb is pure payload to encrypt */
 63 
 64         /* Round to block size */
 65         clen = skb->len;
 66 
 67         esp = x->data;
 68         alen = esp->auth.icv_trunc_len;
 69         tfm = esp->conf.tfm;
 70         blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
 71         clen = (clen + 2 + blksize-1)&~(blksize-1);
 72         if (esp->conf.padlen)
 73                 clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
 74 
 75         if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
 76                 goto error;
 77 
 78         /* Fill padding... */
 79         do {
 80                 int i;
 81                 for (i=0; i<clen-skb->len - 2; i++)
 82                         *(u8*)(trailer->tail + i) = i+1;
 83         } while (0);
 84         *(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
 85         pskb_put(skb, trailer, clen - skb->len);
 86 
 87         encap = x->encap;
 88 
 89         iph = skb->nh.iph;
 90         if (x->props.mode) {
 91                 top_iph = (struct iphdr*)skb_push(skb, x->props.header_len);
 92                 esph = (struct ip_esp_hdr*)(top_iph+1);
 93                 if (encap && encap->encap_type) {
 94                         switch (encap->encap_type) {
 95                         case UDP_ENCAP_ESPINUDP:
 96                                 uh = (struct udphdr*) esph;
 97                                 esph = (struct ip_esp_hdr*)(uh+1);
 98                                 top_iph->protocol = IPPROTO_UDP;
 99                                 break;
100                         default:
101                                 printk(KERN_INFO
102                                        "esp_output(): Unhandled encap: %u\n",
103                                        encap->encap_type);
104                                 top_iph->protocol = IPPROTO_ESP;
105                                 break;
106                         }
107                 } else
108                         top_iph->protocol = IPPROTO_ESP;
109                 *(u8*)(trailer->tail - 1) = IPPROTO_IPIP;
110                 top_iph->ihl = 5;
111                 top_iph->version = 4;
112                 top_iph->tos = iph->tos;        /* DS disclosed */
113                 if (x->props.flags & XFRM_STATE_NOECN)
114                         IP_ECN_clear(top_iph);
115                 top_iph->tot_len = htons(skb->len + alen);
116                 top_iph->frag_off = iph->frag_off&htons(IP_DF);
117                 if (!(top_iph->frag_off))
118                         ip_select_ident(top_iph, dst, 0);
119                 top_iph->ttl = iph->ttl;        /* TTL disclosed */
120                 top_iph->check = 0;
121                 top_iph->saddr = x->props.saddr.a4;
122                 top_iph->daddr = x->id.daddr.a4;
123                 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
124         } else {
125                 esph = (struct ip_esp_hdr*)skb_push(skb, x->props.header_len);
126                 top_iph = (struct iphdr*)skb_push(skb, iph->ihl*4);
127                 memcpy(top_iph, &tmp_iph, iph->ihl*4);
128                 if (encap && encap->encap_type) {
129                         switch (encap->encap_type) {
130                         case UDP_ENCAP_ESPINUDP:
131                                 uh = (struct udphdr*) esph;
132                                 esph = (struct ip_esp_hdr*)(uh+1);
133                                 top_iph->protocol = IPPROTO_UDP;
134                                 break;
135                         default:
136                                 printk(KERN_INFO
137                                        "esp_output(): Unhandled encap: %u\n",
138                                        encap->encap_type);
139                                 top_iph->protocol = IPPROTO_ESP;
140                                 break;
141                         }
142                 } else
143                         top_iph->protocol = IPPROTO_ESP;
144                 iph = &tmp_iph.iph;
145                 top_iph->tot_len = htons(skb->len + alen);
146                 top_iph->check = 0;
147                 top_iph->frag_off = iph->frag_off;
148                 *(u8*)(trailer->tail - 1) = iph->protocol;
149         }
150 
151         /* this is non-NULL only with UDP Encapsulation */
152         if (encap && uh) {
153                 uh->source = encap->encap_sport;
154                 uh->dest = encap->encap_dport;
155                 uh->len = htons(skb->len + alen - sizeof(struct iphdr));
156                 uh->check = 0;
157         }
158 
159         esph->spi = x->id.spi;
160         esph->seq_no = htonl(++x->replay.oseq);
161 
162         if (esp->conf.ivlen)
163                 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
164 
165         do {
166                 struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
167                 struct scatterlist *sg = sgbuf;
168 
169                 if (unlikely(nfrags > MAX_SG_ONSTACK)) {
170                         sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
171                         if (!sg)
172                                 goto error;
173                 }
174                 skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
175                 crypto_cipher_encrypt(tfm, sg, sg, clen);
176                 if (unlikely(sg != sgbuf))
177                         kfree(sg);
178         } while (0);
179 
180         if (esp->conf.ivlen) {
181                 memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
182                 crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
183         }
184 
185         if (esp->auth.icv_full_len) {
186                 esp->auth.icv(esp, skb, (u8*)esph-skb->data,
187                               sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
188                 pskb_put(skb, trailer, alen);
189         }
190 
191         ip_send_check(top_iph);
192 
193         skb->nh.raw = skb->data;
194 
195         x->curlft.bytes += skb->len;
196         x->curlft.packets++;
197         spin_unlock_bh(&x->lock);
198         if ((skb->dst = dst_pop(dst)) == NULL) {
199                 err = -EHOSTUNREACH;
200                 goto error_nolock;
201         }
202         return NET_XMIT_BYPASS;
203 
204 error:
205         spin_unlock_bh(&x->lock);
206 error_nolock:
207         kfree_skb(skb);
208         return err;
209 }
210 
211 /*
212  * Note: detecting truncated vs. non-truncated authentication data is very
213  * expensive, so we only support truncated data, which is the recommended
214  * and common case.
215  */
216 int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
217 {
218         struct iphdr *iph;
219         struct ip_esp_hdr *esph;
220         struct esp_data *esp = x->data;
221         struct sk_buff *trailer;
222         int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
223         int alen = esp->auth.icv_trunc_len;
224         int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
225         int nfrags;
226         int encap_len = 0;
227 
228         if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
229                 goto out;
230 
231         if (elen <= 0 || (elen & (blksize-1)))
232                 goto out;
233 
234         /* If integrity check is required, do this. */
235         if (esp->auth.icv_full_len) {
236                 u8 sum[esp->auth.icv_full_len];
237                 u8 sum1[alen];
238                 
239                 esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
240 
241                 if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
242                         BUG();
243 
244                 if (unlikely(memcmp(sum, sum1, alen))) {
245                         x->stats.integrity_failed++;
246                         goto out;
247                 }
248         }
249 
250         if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0)
251                 goto out;
252 
253         skb->ip_summed = CHECKSUM_NONE;
254 
255         esph = (struct ip_esp_hdr*)skb->data;
256         iph = skb->nh.iph;
257 
258         /* Get ivec. This can be wrong, check against another impls. */
259         if (esp->conf.ivlen)
260                 crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm));
261 
262         {
263                 u8 nexthdr[2];
264                 struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
265                 struct scatterlist *sg = sgbuf;
266                 u8 workbuf[60];
267                 int padlen;
268 
269                 if (unlikely(nfrags > MAX_SG_ONSTACK)) {
270                         sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
271                         if (!sg)
272                                 goto out;
273                 }
274                 skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
275                 crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
276                 if (unlikely(sg != sgbuf))
277                         kfree(sg);
278 
279                 if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
280                         BUG();
281 
282                 padlen = nexthdr[0];
283                 if (padlen+2 >= elen)
284                         goto out;
285 
286                 /* ... check padding bits here. Silly. :-) */ 
287 
288                 if (x->encap && decap && decap->decap_type) {
289                         struct esp_decap_data *encap_data;
290                         struct udphdr *uh = (struct udphdr *) (iph+1);
291 
292                         encap_data = (struct esp_decap_data *) (decap->decap_data);
293                         encap_data->proto = 0;
294 
295                         switch (decap->decap_type) {
296                         case UDP_ENCAP_ESPINUDP:
297 
298                                 if ((void*)uh == (void*)esph) {
299                                         printk(KERN_DEBUG
300                                                "esp_input(): Got ESP; expecting ESPinUDP\n");
301                                         break;
302                                 }
303 
304                                 encap_data->proto = AF_INET;
305                                 encap_data->saddr.a4 = iph->saddr;
306                                 encap_data->sport = uh->source;
307                                 encap_len = (void*)esph - (void*)uh;
308                                 if (encap_len != sizeof(*uh))
309                                   printk(KERN_DEBUG
310                                          "esp_input(): UDP -> ESP: too much room: %d\n",
311                                          encap_len);
312                                 break;
313 
314                         default:
315                                 printk(KERN_INFO
316                                "esp_input(): processing unknown encap type: %u\n",
317                                        decap->decap_type);
318                                 break;
319                         }
320                 }
321 
322                 iph->protocol = nexthdr[1];
323                 pskb_trim(skb, skb->len - alen - padlen - 2);
324                 memcpy(workbuf, skb->nh.raw, iph->ihl*4);
325                 skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
326                 skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
327                 memcpy(skb->nh.raw, workbuf, iph->ihl*4);
328                 skb->nh.iph->tot_len = htons(skb->len);
329         }
330 
331         return 0;
332 
333 out:
334         return -EINVAL;
335 }
336 
337 int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
338 {
339   
340         if (x->encap) {
341                 struct xfrm_encap_tmpl *encap;
342                 struct esp_decap_data *decap_data;
343 
344                 encap = x->encap;
345                 decap_data = (struct esp_decap_data *)(decap->decap_data);
346 
347                 /* first, make sure that the decap type == the encap type */
348                 if (encap->encap_type != decap->decap_type)
349                         return -EINVAL;
350 
351                 /* Next, if we don't have an encap type, then ignore it */
352                 if (!encap->encap_type)
353                         return 0;
354 
355                 switch (encap->encap_type) {
356                 case UDP_ENCAP_ESPINUDP:
357                         /*
358                          * 1) if the NAT-T peer's IP or port changed then
359                          *    advertize the change to the keying daemon.
360                          *    This is an inbound SA, so just compare
361                          *    SRC ports.
362                          */
363                         if (decap_data->proto == AF_INET &&
364                             (decap_data->saddr.a4 != x->props.saddr.a4 ||
365                              decap_data->sport != encap->encap_sport)) {
366                                 xfrm_address_t ipaddr;
367 
368                                 ipaddr.a4 = decap_data->saddr.a4;
369                                 km_new_mapping(x, &ipaddr, decap_data->sport);
370                                         
371                                 /* XXX: perhaps add an extra
372                                  * policy check here, to see
373                                  * if we should allow or
374                                  * reject a packet from a
375                                  * different source
376                                  * address/port.
377                                  */
378                         }
379                 
380                         /*
381                          * 2) ignore UDP/TCP checksums in case
382                          *    of NAT-T in Transport Mode, or
383                          *    perform other post-processing fixes
384                          *    as per * draft-ietf-ipsec-udp-encaps-06,
385                          *    section 3.1.2
386                          */
387                         if (!x->props.mode)
388                                 skb->ip_summed = CHECKSUM_UNNECESSARY;
389 
390                         break;
391                 default:
392                         printk(KERN_INFO
393                                "esp4_post_input(): Unhandled encap type: %u\n",
394                                encap->encap_type);
395                         break;
396                 }
397         }
398         return 0;
399 }
400 
401 static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
402 {
403         struct esp_data *esp = x->data;
404         u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
405 
406         if (x->props.mode) {
407                 mtu = (mtu + 2 + blksize-1)&~(blksize-1);
408         } else {
409                 /* The worst case. */
410                 mtu += 2 + blksize;
411         }
412         if (esp->conf.padlen)
413                 mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
414 
415         return mtu + x->props.header_len + esp->auth.icv_trunc_len;
416 }
417 
418 void esp4_err(struct sk_buff *skb, u32 info)
419 {
420         struct iphdr *iph = (struct iphdr*)skb->data;
421         struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));
422         struct xfrm_state *x;
423 
424         if (skb->h.icmph->type != ICMP_DEST_UNREACH ||
425             skb->h.icmph->code != ICMP_FRAG_NEEDED)
426                 return;
427 
428         x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
429         if (!x)
430                 return;
431         printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n",
432                ntohl(esph->spi), ntohl(iph->daddr));
433         xfrm_state_put(x);
434 }
435 
436 void esp_destroy(struct xfrm_state *x)
437 {
438         struct esp_data *esp = x->data;
439 
440         if (!esp)
441                 return;
442 
443         if (esp->conf.tfm) {
444                 crypto_free_tfm(esp->conf.tfm);
445                 esp->conf.tfm = NULL;
446         }
447         if (esp->conf.ivec) {
448                 kfree(esp->conf.ivec);
449                 esp->conf.ivec = NULL;
450         }
451         if (esp->auth.tfm) {
452                 crypto_free_tfm(esp->auth.tfm);
453                 esp->auth.tfm = NULL;
454         }
455         if (esp->auth.work_icv) {
456                 kfree(esp->auth.work_icv);
457                 esp->auth.work_icv = NULL;
458         }
459         kfree(esp);
460 }
461 
462 int esp_init_state(struct xfrm_state *x, void *args)
463 {
464         struct esp_data *esp = NULL;
465 
466         /* null auth and encryption can have zero length keys */
467         if (x->aalg) {
468                 if (x->aalg->alg_key_len > 512)
469                         goto error;
470         }
471         if (x->ealg == NULL)
472                 goto error;
473 
474         esp = kmalloc(sizeof(*esp), GFP_KERNEL);
475         if (esp == NULL)
476                 return -ENOMEM;
477 
478         memset(esp, 0, sizeof(*esp));
479 
480         if (x->aalg) {
481                 struct xfrm_algo_desc *aalg_desc;
482 
483                 esp->auth.key = x->aalg->alg_key;
484                 esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
485                 esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
486                 if (esp->auth.tfm == NULL)
487                         goto error;
488                 esp->auth.icv = esp_hmac_digest;
489 
490                 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
491                 BUG_ON(!aalg_desc);
492 
493                 if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
494                     crypto_tfm_alg_digestsize(esp->auth.tfm)) {
495                         printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
496                                x->aalg->alg_name,
497                                crypto_tfm_alg_digestsize(esp->auth.tfm),
498                                aalg_desc->uinfo.auth.icv_fullbits/8);
499                         goto error;
500                 }
501 
502                 esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
503                 esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
504 
505                 esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
506                 if (!esp->auth.work_icv)
507                         goto error;
508         }
509         esp->conf.key = x->ealg->alg_key;
510         esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
511         if (x->props.ealgo == SADB_EALG_NULL)
512                 esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB);
513         else
514                 esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
515         if (esp->conf.tfm == NULL)
516                 goto error;
517         esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
518         esp->conf.padlen = 0;
519         if (esp->conf.ivlen) {
520                 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
521                 get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
522         }
523         crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len);
524         x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
525         if (x->props.mode)
526                 x->props.header_len += sizeof(struct iphdr);
527         if (x->encap) {
528                 struct xfrm_encap_tmpl *encap = x->encap;
529 
530                 if (encap->encap_type) {
531                         switch (encap->encap_type) {
532                         case UDP_ENCAP_ESPINUDP:
533                                 x->props.header_len += sizeof(struct udphdr);
534                                 break;
535                         default:
536                                 printk (KERN_INFO
537                                 "esp_init_state(): Unhandled encap type: %u\n",
538                                         encap->encap_type);
539                                 break;
540                         }
541                 }
542         }
543         x->data = esp;
544         x->props.trailer_len = esp4_get_max_size(x, 0) - x->props.header_len;
545         return 0;
546 
547 error:
548         if (esp) {
549                 if (esp->auth.tfm)
550                         crypto_free_tfm(esp->auth.tfm);
551                 if (esp->auth.work_icv)
552                         kfree(esp->auth.work_icv);
553                 if (esp->conf.tfm)
554                         crypto_free_tfm(esp->conf.tfm);
555                 kfree(esp);
556         }
557         return -EINVAL;
558 }
559 
560 static struct xfrm_type esp_type =
561 {
562         .description    = "ESP4",
563         .owner          = THIS_MODULE,
564         .proto          = IPPROTO_ESP,
565         .init_state     = esp_init_state,
566         .destructor     = esp_destroy,
567         .get_max_size   = esp4_get_max_size,
568         .input          = esp_input,
569         .post_input     = esp_post_input,
570         .output         = esp_output
571 };
572 
573 static struct inet_protocol esp4_protocol = {
574         .handler        =       xfrm4_rcv,
575         .err_handler    =       esp4_err,
576         .no_policy      =       1,
577 };
578 
579 static int __init esp4_init(void)
580 {
581         struct xfrm_decap_state decap;
582 
583         if (sizeof(struct esp_decap_data)  <
584             sizeof(decap.decap_data)) {
585                 extern void decap_data_too_small(void);
586 
587                 decap_data_too_small();
588         }
589 
590         if (xfrm_register_type(&esp_type, AF_INET) < 0) {
591                 printk(KERN_INFO "ip esp init: can't add xfrm type\n");
592                 return -EAGAIN;
593         }
594         if (inet_add_protocol(&esp4_protocol, IPPROTO_ESP) < 0) {
595                 printk(KERN_INFO "ip esp init: can't add protocol\n");
596                 xfrm_unregister_type(&esp_type, AF_INET);
597                 return -EAGAIN;
598         }
599         return 0;
600 }
601 
602 static void __exit esp4_fini(void)
603 {
604         if (inet_del_protocol(&esp4_protocol, IPPROTO_ESP) < 0)
605                 printk(KERN_INFO "ip esp close: can't remove protocol\n");
606         if (xfrm_unregister_type(&esp_type, AF_INET) < 0)
607                 printk(KERN_INFO "ip esp close: can't remove xfrm type\n");
608 }
609 
610 module_init(esp4_init);
611 module_exit(esp4_fini);
612 MODULE_LICENSE("GPL");
613 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp