[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/netipsec/xform_ipip.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*      $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.19 2008/10/02 15:37:58 zec Exp $    */
  2 /*      $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
  3 /*-
  4  * The authors of this code are John Ioannidis (ji@tla.org),
  5  * Angelos D. Keromytis (kermit@csd.uch.gr) and
  6  * Niels Provos (provos@physnet.uni-hamburg.de).
  7  *
  8  * The original version of this code was written by John Ioannidis
  9  * for BSD/OS in Athens, Greece, in November 1995.
 10  *
 11  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
 12  * by Angelos D. Keromytis.
 13  *
 14  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
 15  * and Niels Provos.
 16  *
 17  * Additional features in 1999 by Angelos D. Keromytis.
 18  *
 19  * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
 20  * Angelos D. Keromytis and Niels Provos.
 21  * Copyright (c) 2001, Angelos D. Keromytis.
 22  *
 23  * Permission to use, copy, and modify this software with or without fee
 24  * is hereby granted, provided that this entire notice is included in
 25  * all copies of any software which is or includes a copy or
 26  * modification of this software.
 27  * You may use this code under the GNU public license if you so wish. Please
 28  * contribute changes back to the authors under this freer than GPL license
 29  * so that we may further the use of strong encryption without limitations to
 30  * all.
 31  *
 32  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
 33  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
 34  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
 35  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
 36  * PURPOSE.
 37  */
 38 
 39 /*
 40  * IP-inside-IP processing
 41  */
 42 #include "opt_inet.h"
 43 #include "opt_inet6.h"
 44 #include "opt_enc.h"
 45 
 46 #include <sys/param.h>
 47 #include <sys/systm.h>
 48 #include <sys/mbuf.h>
 49 #include <sys/socket.h>
 50 #include <sys/kernel.h>
 51 #include <sys/protosw.h>
 52 #include <sys/sysctl.h>
 53 #include <sys/vimage.h>
 54 
 55 #include <net/if.h>
 56 #include <net/pfil.h>
 57 #include <net/route.h>
 58 #include <net/netisr.h>
 59 
 60 #include <netinet/in.h>
 61 #include <netinet/in_systm.h>
 62 #include <netinet/in_var.h>
 63 #include <netinet/ip.h>
 64 #include <netinet/ip_ecn.h>
 65 #include <netinet/ip_var.h>
 66 #include <netinet/ip_encap.h>
 67 
 68 #include <netipsec/ipsec.h>
 69 #include <netipsec/xform.h>
 70 
 71 #include <netipsec/ipip_var.h>
 72 
 73 #ifdef MROUTING
 74 #include <netinet/ip_mroute.h>
 75 #endif
 76 
 77 #ifdef INET6
 78 #include <netinet/ip6.h>
 79 #include <netipsec/ipsec6.h>
 80 #include <netinet6/ip6_ecn.h>
 81 #include <netinet6/in6_var.h>
 82 #include <netinet6/ip6protosw.h>
 83 #endif
 84 
 85 #include <netipsec/key.h>
 86 #include <netipsec/key_debug.h>
 87 
 88 #include <machine/stdarg.h>
 89 
 90 /*
 91  * We can control the acceptance of IP4 packets by altering the sysctl
 92  * net.inet.ipip.allow value.  Zero means drop them, all else is acceptance.
 93  */
 94 int     ipip_allow = 0;
 95 struct  ipipstat ipipstat;
 96 
 97 SYSCTL_DECL(_net_inet_ipip);
 98 SYSCTL_V_INT(V_NET, vnet_ipsec, _net_inet_ipip, OID_AUTO,
 99         ipip_allow,     CTLFLAG_RW,     ipip_allow,     0, "");
100 SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet_ipip, IPSECCTL_STATS,
101         stats,          CTLFLAG_RD,     ipipstat,       ipipstat, "");
102 
103 /* XXX IPCOMP */
104 #define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED)
105 
106 static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp);
107 
108 #ifdef INET6
109 /*
110  * Really only a wrapper for ipip_input(), for use with IPv6.
111  */
112 int
113 ip4_input6(struct mbuf **m, int *offp, int proto)
114 {
115 #if 0
116         /* If we do not accept IP-in-IP explicitly, drop.  */
117         if (!V_ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) {
118                 DPRINTF(("%s: dropped due to policy\n", __func__));
119                 V_ipipstat.ipips_pdrops++;
120                 m_freem(*m);
121                 return IPPROTO_DONE;
122         }
123 #endif
124         _ipip_input(*m, *offp, NULL);
125         return IPPROTO_DONE;
126 }
127 #endif /* INET6 */
128 
129 #ifdef INET
130 /*
131  * Really only a wrapper for ipip_input(), for use with IPv4.
132  */
133 void
134 ip4_input(struct mbuf *m, int off)
135 {
136 #if 0
137         /* If we do not accept IP-in-IP explicitly, drop.  */
138         if (!V_ipip_allow && (m->m_flags & M_IPSEC) == 0) {
139                 DPRINTF(("%s: dropped due to policy\n", __func__));
140                 V_ipipstat.ipips_pdrops++;
141                 m_freem(m);
142                 return;
143         }
144 #endif
145         _ipip_input(m, off, NULL);
146 }
147 #endif /* INET */
148 
149 /*
150  * ipip_input gets called when we receive an IP{46} encapsulated packet,
151  * either because we got it at a real interface, or because AH or ESP
152  * were being used in tunnel mode (in which case the rcvif element will
153  * contain the address of the encX interface associated with the tunnel.
154  */
155 
156 static void
157 _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
158 {
159         INIT_VNET_NET(curvnet);
160         INIT_VNET_IPSEC(curvnet);
161         register struct sockaddr_in *sin;
162         register struct ifnet *ifp;
163         register struct ifaddr *ifa;
164         struct ip *ipo;
165 #ifdef INET6
166         register struct sockaddr_in6 *sin6;
167         struct ip6_hdr *ip6 = NULL;
168         u_int8_t itos;
169 #endif
170         u_int8_t nxt;
171         int isr;
172         u_int8_t otos;
173         u_int8_t v;
174         int hlen;
175 
176         V_ipipstat.ipips_ipackets++;
177 
178         m_copydata(m, 0, 1, &v);
179 
180         switch (v >> 4) {
181 #ifdef INET
182         case 4:
183                 hlen = sizeof(struct ip);
184                 break;
185 #endif /* INET */
186 #ifdef INET6
187         case 6:
188                 hlen = sizeof(struct ip6_hdr);
189                 break;
190 #endif
191         default:
192                 V_ipipstat.ipips_family++;
193                 m_freem(m);
194                 return /* EAFNOSUPPORT */;
195         }
196 
197         /* Bring the IP header in the first mbuf, if not there already */
198         if (m->m_len < hlen) {
199                 if ((m = m_pullup(m, hlen)) == NULL) {
200                         DPRINTF(("%s: m_pullup (1) failed\n", __func__));
201                         V_ipipstat.ipips_hdrops++;
202                         return;
203                 }
204         }
205 
206         ipo = mtod(m, struct ip *);
207 
208 #ifdef MROUTING
209         if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) {
210                 if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) {
211                         ipip_mroute_input (m, iphlen);
212                         return;
213                 }
214         }
215 #endif /* MROUTING */
216 
217         /* Keep outer ecn field. */
218         switch (v >> 4) {
219 #ifdef INET
220         case 4:
221                 otos = ipo->ip_tos;
222                 break;
223 #endif /* INET */
224 #ifdef INET6
225         case 6:
226                 otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff;
227                 break;
228 #endif
229         default:
230                 panic("ipip_input: unknown ip version %u (outer)", v>>4);
231         }
232 
233         /* Remove outer IP header */
234         m_adj(m, iphlen);
235 
236         /* Sanity check */
237         if (m->m_pkthdr.len < sizeof(struct ip))  {
238                 V_ipipstat.ipips_hdrops++;
239                 m_freem(m);
240                 return;
241         }
242 
243         m_copydata(m, 0, 1, &v);
244 
245         switch (v >> 4) {
246 #ifdef INET
247         case 4:
248                 hlen = sizeof(struct ip);
249                 break;
250 #endif /* INET */
251 
252 #ifdef INET6
253         case 6:
254                 hlen = sizeof(struct ip6_hdr);
255                 break;
256 #endif
257         default:
258                 V_ipipstat.ipips_family++;
259                 m_freem(m);
260                 return; /* EAFNOSUPPORT */
261         }
262 
263         /*
264          * Bring the inner IP header in the first mbuf, if not there already.
265          */
266         if (m->m_len < hlen) {
267                 if ((m = m_pullup(m, hlen)) == NULL) {
268                         DPRINTF(("%s: m_pullup (2) failed\n", __func__));
269                         V_ipipstat.ipips_hdrops++;
270                         return;
271                 }
272         }
273 
274         /*
275          * RFC 1853 specifies that the inner TTL should not be touched on
276          * decapsulation. There's no reason this comment should be here, but
277          * this is as good as any a position.
278          */
279 
280         /* Some sanity checks in the inner IP header */
281         switch (v >> 4) {
282 #ifdef INET
283         case 4:
284                 ipo = mtod(m, struct ip *);
285                 nxt = ipo->ip_p;
286                 ip_ecn_egress(V_ip4_ipsec_ecn, &otos, &ipo->ip_tos);
287                 break;
288 #endif /* INET */
289 #ifdef INET6
290         case 6:
291                 ip6 = (struct ip6_hdr *) ipo;
292                 nxt = ip6->ip6_nxt;
293                 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
294                 ip_ecn_egress(V_ip6_ipsec_ecn, &otos, &itos);
295                 ip6->ip6_flow &= ~htonl(0xff << 20);
296                 ip6->ip6_flow |= htonl((u_int32_t) itos << 20);
297                 break;
298 #endif
299         default:
300                 panic("ipip_input: unknown ip version %u (inner)", v>>4);
301         }
302 
303         /* Check for local address spoofing. */
304         if ((m->m_pkthdr.rcvif == NULL ||
305             !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
306             V_ipip_allow != 2) {
307                 IFNET_RLOCK();
308                 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
309                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
310 #ifdef INET
311                                 if (ipo) {
312                                         if (ifa->ifa_addr->sa_family !=
313                                             AF_INET)
314                                                 continue;
315 
316                                         sin = (struct sockaddr_in *) ifa->ifa_addr;
317 
318                                         if (sin->sin_addr.s_addr ==
319                                             ipo->ip_src.s_addr) {
320                                                 V_ipipstat.ipips_spoof++;
321                                                 m_freem(m);
322                                                 IFNET_RUNLOCK();
323                                                 return;
324                                         }
325                                 }
326 #endif /* INET */
327 
328 #ifdef INET6
329                                 if (ip6) {
330                                         if (ifa->ifa_addr->sa_family !=
331                                             AF_INET6)
332                                                 continue;
333 
334                                         sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
335 
336                                         if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
337                                                 V_ipipstat.ipips_spoof++;
338                                                 m_freem(m);
339                                                 IFNET_RUNLOCK();
340                                                 return;
341                                         }
342 
343                                 }
344 #endif /* INET6 */
345                         }
346                 }
347                 IFNET_RUNLOCK();
348         }
349 
350         /* Statistics */
351         V_ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
352 
353 #ifdef DEV_ENC
354         switch (v >> 4) {
355 #ifdef INET
356         case 4:
357                 ipsec_bpf(m, NULL, AF_INET, ENC_IN|ENC_AFTER);
358                 break;
359 #endif
360 #ifdef INET6
361         case 6:
362                 ipsec_bpf(m, NULL, AF_INET6, ENC_IN|ENC_AFTER);
363                 break;
364 #endif
365         default:
366                 panic("%s: bogus ip version %u", __func__, v>>4);
367         }
368         /* pass the mbuf to enc0 for packet filtering */
369         if (ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER) != 0)
370                 return;
371 #endif
372 
373         /*
374          * Interface pointer stays the same; if no IPsec processing has
375          * been done (or will be done), this will point to a normal
376          * interface. Otherwise, it'll point to an enc interface, which
377          * will allow a packet filter to distinguish between secure and
378          * untrusted packets.
379          */
380 
381         switch (v >> 4) {
382 #ifdef INET
383         case 4:
384                 isr = NETISR_IP;
385                 break;
386 #endif
387 #ifdef INET6
388         case 6:
389                 isr = NETISR_IPV6;
390                 break;
391 #endif
392         default:
393                 panic("%s: bogus ip version %u", __func__, v>>4);
394         }
395 
396         if (netisr_queue(isr, m)) {     /* (0) on success. */
397                 V_ipipstat.ipips_qfull++;
398                 DPRINTF(("%s: packet dropped because of full queue\n",
399                         __func__));
400         }
401 }
402 
403 int
404 ipip_output(
405         struct mbuf *m,
406         struct ipsecrequest *isr,
407         struct mbuf **mp,
408         int skip,
409         int protoff
410 )
411 {
412         INIT_VNET_IPSEC(curvnet);
413 #ifdef INET
414         INIT_VNET_INET(curvnet);
415 #endif /* INET */
416         struct secasvar *sav;
417         u_int8_t tp, otos;
418         struct secasindex *saidx;
419         int error;
420 #ifdef INET
421         u_int8_t itos;
422         struct ip *ipo;
423 #endif /* INET */
424 #ifdef INET6
425         struct ip6_hdr *ip6, *ip6o;
426 #endif /* INET6 */
427 
428         sav = isr->sav;
429         IPSEC_ASSERT(sav != NULL, ("null SA"));
430         IPSEC_ASSERT(sav->sah != NULL, ("null SAH"));
431 
432         /* XXX Deal with empty TDB source/destination addresses. */
433 
434         m_copydata(m, 0, 1, &tp);
435         tp = (tp >> 4) & 0xff;  /* Get the IP version number. */
436 
437         saidx = &sav->sah->saidx;
438         switch (saidx->dst.sa.sa_family) {
439 #ifdef INET
440         case AF_INET:
441                 if (saidx->src.sa.sa_family != AF_INET ||
442                     saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
443                     saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) {
444                         DPRINTF(("%s: unspecified tunnel endpoint "
445                             "address in SA %s/%08lx\n", __func__,
446                             ipsec_address(&saidx->dst),
447                             (u_long) ntohl(sav->spi)));
448                         V_ipipstat.ipips_unspec++;
449                         error = EINVAL;
450                         goto bad;
451                 }
452 
453                 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
454                 if (m == 0) {
455                         DPRINTF(("%s: M_PREPEND failed\n", __func__));
456                         V_ipipstat.ipips_hdrops++;
457                         error = ENOBUFS;
458                         goto bad;
459                 }
460 
461                 ipo = mtod(m, struct ip *);
462 
463                 ipo->ip_v = IPVERSION;
464                 ipo->ip_hl = 5;
465                 ipo->ip_len = htons(m->m_pkthdr.len);
466                 ipo->ip_ttl = V_ip_defttl;
467                 ipo->ip_sum = 0;
468                 ipo->ip_src = saidx->src.sin.sin_addr;
469                 ipo->ip_dst = saidx->dst.sin.sin_addr;
470 
471                 ipo->ip_id = ip_newid();
472 
473                 /* If the inner protocol is IP... */
474                 if (tp == IPVERSION) {
475                         /* Save ECN notification */
476                         m_copydata(m, sizeof(struct ip) +
477                             offsetof(struct ip, ip_tos),
478                             sizeof(u_int8_t), (caddr_t) &itos);
479 
480                         ipo->ip_p = IPPROTO_IPIP;
481 
482                         /*
483                          * We should be keeping tunnel soft-state and
484                          * send back ICMPs if needed.
485                          */
486                         m_copydata(m, sizeof(struct ip) +
487                             offsetof(struct ip, ip_off),
488                             sizeof(u_int16_t), (caddr_t) &ipo->ip_off);
489                         ipo->ip_off = ntohs(ipo->ip_off);
490                         ipo->ip_off &= ~(IP_DF | IP_MF | IP_OFFMASK);
491                         ipo->ip_off = htons(ipo->ip_off);
492                 }
493 #ifdef INET6
494                 else if (tp == (IPV6_VERSION >> 4)) {
495                         u_int32_t itos32;
496 
497                         /* Save ECN notification. */
498                         m_copydata(m, sizeof(struct ip) +
499                             offsetof(struct ip6_hdr, ip6_flow),
500                             sizeof(u_int32_t), (caddr_t) &itos32);
501                         itos = ntohl(itos32) >> 20;
502                         ipo->ip_p = IPPROTO_IPV6;
503                         ipo->ip_off = 0;
504                 }
505 #endif /* INET6 */
506                 else {
507                         goto nofamily;
508                 }
509 
510                 otos = 0;
511                 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
512                 ipo->ip_tos = otos;
513                 break;
514 #endif /* INET */
515 
516 #ifdef INET6
517         case AF_INET6:
518                 if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) ||
519                     saidx->src.sa.sa_family != AF_INET6 ||
520                     IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) {
521                         DPRINTF(("%s: unspecified tunnel endpoint "
522                             "address in SA %s/%08lx\n", __func__,
523                             ipsec_address(&saidx->dst),
524                             (u_long) ntohl(sav->spi)));
525                         V_ipipstat.ipips_unspec++;
526                         error = ENOBUFS;
527                         goto bad;
528                 }
529 
530                 /* scoped address handling */
531                 ip6 = mtod(m, struct ip6_hdr *);
532                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
533                         ip6->ip6_src.s6_addr16[1] = 0;
534                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
535                         ip6->ip6_dst.s6_addr16[1] = 0;
536 
537                 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
538                 if (m == 0) {
539                         DPRINTF(("%s: M_PREPEND failed\n", __func__));
540                         V_ipipstat.ipips_hdrops++;
541                         error = ENOBUFS;
542                         goto bad;
543                 }
544 
545                 /* Initialize IPv6 header */
546                 ip6o = mtod(m, struct ip6_hdr *);
547                 ip6o->ip6_flow = 0;
548                 ip6o->ip6_vfc &= ~IPV6_VERSION_MASK;
549                 ip6o->ip6_vfc |= IPV6_VERSION;
550                 ip6o->ip6_plen = htons(m->m_pkthdr.len);
551                 ip6o->ip6_hlim = V_ip_defttl;
552                 ip6o->ip6_dst = saidx->dst.sin6.sin6_addr;
553                 ip6o->ip6_src = saidx->src.sin6.sin6_addr;
554 
555 #ifdef INET
556                 if (tp == IPVERSION) {
557                         /* Save ECN notification */
558                         m_copydata(m, sizeof(struct ip6_hdr) +
559                             offsetof(struct ip, ip_tos), sizeof(u_int8_t),
560                             (caddr_t) &itos);
561 
562                         /* This is really IPVERSION. */
563                         ip6o->ip6_nxt = IPPROTO_IPIP;
564                 } else
565 #endif /* INET */
566                         if (tp == (IPV6_VERSION >> 4)) {
567                                 u_int32_t itos32;
568 
569                                 /* Save ECN notification. */
570                                 m_copydata(m, sizeof(struct ip6_hdr) +
571                                     offsetof(struct ip6_hdr, ip6_flow),
572                                     sizeof(u_int32_t), (caddr_t) &itos32);
573                                 itos = ntohl(itos32) >> 20;
574 
575                                 ip6o->ip6_nxt = IPPROTO_IPV6;
576                         } else {
577                                 goto nofamily;
578                         }
579 
580                 otos = 0;
581                 ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
582                 ip6o->ip6_flow |= htonl((u_int32_t) otos << 20);
583                 break;
584 #endif /* INET6 */
585 
586         default:
587 nofamily:
588                 DPRINTF(("%s: unsupported protocol family %u\n", __func__,
589                     saidx->dst.sa.sa_family));
590                 V_ipipstat.ipips_family++;
591                 error = EAFNOSUPPORT;           /* XXX diffs from openbsd */
592                 goto bad;
593         }
594 
595         V_ipipstat.ipips_opackets++;
596         *mp = m;
597 
598 #ifdef INET
599         if (saidx->dst.sa.sa_family == AF_INET) {
600 #if 0
601                 if (sav->tdb_xform->xf_type == XF_IP4)
602                         tdb->tdb_cur_bytes +=
603                             m->m_pkthdr.len - sizeof(struct ip);
604 #endif
605                 V_ipipstat.ipips_obytes += m->m_pkthdr.len - sizeof(struct ip);
606         }
607 #endif /* INET */
608 
609 #ifdef INET6
610         if (saidx->dst.sa.sa_family == AF_INET6) {
611 #if 0
612                 if (sav->tdb_xform->xf_type == XF_IP4)
613                         tdb->tdb_cur_bytes +=
614                             m->m_pkthdr.len - sizeof(struct ip6_hdr);
615 #endif
616                 V_ipipstat.ipips_obytes +=
617                     m->m_pkthdr.len - sizeof(struct ip6_hdr);
618         }
619 #endif /* INET6 */
620 
621         return 0;
622 bad:
623         if (m)
624                 m_freem(m);
625         *mp = NULL;
626         return (error);
627 }
628 
629 #ifdef IPSEC
630 static int
631 ipe4_init(struct secasvar *sav, struct xformsw *xsp)
632 {
633         sav->tdb_xform = xsp;
634         return 0;
635 }
636 
637 static int
638 ipe4_zeroize(struct secasvar *sav)
639 {
640         sav->tdb_xform = NULL;
641         return 0;
642 }
643 
644 static int
645 ipe4_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
646 {
647         /* This is a rather serious mistake, so no conditional printing. */
648         printf("%s: should never be called\n", __func__);
649         if (m)
650                 m_freem(m);
651         return EOPNOTSUPP;
652 }
653 
654 static struct xformsw ipe4_xformsw = {
655         XF_IP4,         0,              "IPv4 Simple Encapsulation",
656         ipe4_init,      ipe4_zeroize,   ipe4_input,     ipip_output,
657 };
658 
659 extern struct domain inetdomain;
660 static struct protosw ipe4_protosw =
661 { SOCK_RAW,     &inetdomain,    IPPROTO_IPV4,   PR_ATOMIC|PR_ADDR|PR_LASTHDR,
662   ip4_input,
663                 0,              0,              rip_ctloutput,
664   0,
665   0,            0,              0,              0,
666   &rip_usrreqs
667 };
668 #ifdef INET6
669 static struct ip6protosw ipe6_protosw =
670 { SOCK_RAW,     &inetdomain,    IPPROTO_IPV6,   PR_ATOMIC|PR_ADDR|PR_LASTHDR,
671   ip4_input6,
672                 0,              0,              rip_ctloutput,
673   0,
674   0,            0,              0,              0,
675   &rip_usrreqs
676 };
677 #endif
678 
679 /*
680  * Check the encapsulated packet to see if we want it
681  */
682 static int
683 ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
684 {
685         /*
686          * Only take packets coming from IPSEC tunnels; the rest
687          * must be handled by the gif tunnel code.  Note that we
688          * also return a minimum priority when we want the packet
689          * so any explicit gif tunnels take precedence.
690          */
691         return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0);
692 }
693 
694 static void
695 ipe4_attach(void)
696 {
697         xform_register(&ipe4_xformsw);
698         /* attach to encapsulation framework */
699         /* XXX save return cookie for detach on module remove */
700         (void) encap_attach_func(AF_INET, -1,
701                 ipe4_encapcheck, &ipe4_protosw, NULL);
702 #ifdef INET6
703         (void) encap_attach_func(AF_INET6, -1,
704                 ipe4_encapcheck, (struct protosw *)&ipe6_protosw, NULL);
705 #endif
706 }
707 SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
708 #endif  /* IPSEC */
709 

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.