[BACK]Return to ipsec_output.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netipsec

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/netipsec/ipsec_output.c between version 1.23.2.1 and 1.24

version 1.23.2.1, 2008/02/18 21:07:13 version 1.24, 2007/12/09 18:27:39
Line 94  __KERNEL_RCSID(0, "$NetBSD$");
Line 94  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <net/net_osdep.h>              /* ovbcopy() in ipsec6_encapsulate() */  #include <net/net_osdep.h>              /* ovbcopy() in ipsec6_encapsulate() */
   
   
 /*  
  * Add a IPSEC_OUT_DONE tag to mark that we have finished the ipsec processing  
  * It will be used by ip{,6}_output to check if we have already or not  
  * processed this packet.  
  */  
 static int  
 ipsec_register_done(struct mbuf *m, int * error)  
 {  
         struct m_tag *mtag;  
   
         mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, 0, M_NOWAIT);  
         if (mtag == NULL) {  
                 DPRINTF(("ipsec_register_done: could not get packet tag\n"));  
                 *error = ENOMEM;  
                 return -1;  
         }  
   
         m_tag_prepend(m, mtag);  
         return 0;  
 }  
   
 static int  
 ipsec_reinject_ipstack(struct mbuf *m, int af)  
 {  
 #ifdef INET  
         struct ip * ip;  
 #endif /* INET */  
   
         switch (af) {  
 #ifdef INET  
         case AF_INET:  
                 ip = mtod(m, struct ip *);  
 #ifdef __FreeBSD__  
                 /* FreeBSD ip_output() expects ip_len, ip_off in host endian */  
                 ip->ip_len = ntohs(ip->ip_len);  
                 ip->ip_off = ntohs(ip->ip_off);  
 #endif /* __FreeBSD_ */  
                 return ip_output(m, NULL, NULL, IP_RAWOUTPUT,  
                     (struct ip_moptions *)NULL, (struct socket *)NULL);  
   
 #endif /* INET */  
 #ifdef INET6  
         case AF_INET6:  
                 /*  
                  * We don't need massage, IPv6 header fields are always in  
                  * net endian.  
                  */  
                 return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);  
 #endif /* INET6 */  
         }  
   
         panic("ipsec_reinject_ipstack : iunknown protocol family %u\n", af);  
         return -1; /* NOTREACHED */  
 }  
   
 int  int
 ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)  ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
 {  {
           struct tdb_ident *tdbi;
           struct m_tag *mtag;
         struct secasvar *sav;          struct secasvar *sav;
         struct secasindex *saidx;          struct secasindex *saidx;
         int error;          int error;
Line 210  ipsec_process_done(struct mbuf *m, struc
Line 156  ipsec_process_done(struct mbuf *m, struc
   
                 udp->uh_dport = key_portfromsaddr(&saidx->dst);                  udp->uh_dport = key_portfromsaddr(&saidx->dst);
                 udp->uh_sum = 0;                  udp->uh_sum = 0;
 #ifdef _IP_VHL          udp->uh_ulen = htons(m->m_pkthdr.len - (ip->ip_hl << 2));
                 udp->uh_ulen = htons(m->m_pkthdr.len -  
                                     (IP_VHL_HL(ip->ip_vhl) << 2));  
 #else  
                 udp->uh_ulen = htons(m->m_pkthdr.len - (ip->ip_hl << 2));  
 #endif  
         }          }
 #endif /* IPSEC_NAT_T */  #endif /* IPSEC_NAT_T */
   
Line 259  ipsec_process_done(struct mbuf *m, struc
Line 200  ipsec_process_done(struct mbuf *m, struc
         }          }
   
         /*          /*
            * Add a record of what we've done or what needs to be done to the
            * packet.
            */
           mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE,
                           sizeof(struct tdb_ident), M_NOWAIT);
           if (mtag == NULL) {
                   DPRINTF(("ipsec_process_done: could not get packet tag\n"));
                   error = ENOMEM;
                   goto bad;
           }
   
           tdbi = (struct tdb_ident *)(mtag + 1);
           tdbi->dst = saidx->dst;
           tdbi->proto = saidx->proto;
           tdbi->spi = sav->spi;
           m_tag_prepend(m, mtag);
   
           /*
          * If there's another (bundled) SA to apply, do so.           * If there's another (bundled) SA to apply, do so.
          * Note that this puts a burden on the kernel stack size.           * Note that this puts a burden on the kernel stack size.
          * If this is a problem we'll need to introduce a queue           * If this is a problem we'll need to introduce a queue
Line 285  ipsec_process_done(struct mbuf *m, struc
Line 244  ipsec_process_done(struct mbuf *m, struc
         }          }
   
         /*          /*
          * We're done with IPsec processing,           * We're done with IPsec processing, transmit the packet using the
          * mark that we have already processed the packet           * appropriate network protocol (IP or IPv6). SPD lookup will be
          * transmit it packet using the appropriate network protocol (IP or IPv6).           * performed again there.
          */           */
           switch (saidx->dst.sa.sa_family) {
   #ifdef INET
           case AF_INET:
                   ip = mtod(m, struct ip *);
   #ifdef __FreeBSD__
                   /* FreeBSD ip_output() expects ip_len, ip_off in host endian */
                   ip->ip_len = ntohs(ip->ip_len);
                   ip->ip_off = ntohs(ip->ip_off);
   #endif /* __FreeBSD_ */
                   return ip_output(m, NULL, NULL, IP_RAWOUTPUT,
                       (struct ip_moptions *)NULL, (struct socket *)NULL);
   
         if (ipsec_register_done(m, &error) < 0)  #endif /* INET */
                 goto bad;  #ifdef INET6
           case AF_INET6:
         return ipsec_reinject_ipstack(m, saidx->dst.sa.sa_family);                  /*
                    * We don't need massage, IPv6 header fields are always in
                    * net endian.
                    */
                   return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
   #endif /* INET6 */
           }
           panic("ipsec_process_done");
 bad:  bad:
         m_freem(m);          m_freem(m);
         KEY_FREESAV(&sav);          KEY_FREESAV(&sav);
         return (error);          return (error);
 }  }
   
 /*  
  * ipsec_nextisr can return :  
  * - isr == NULL and error != 0 => something is bad : the packet must be  
  *   discarded  
  * - isr == NULL and error == 0 => no more rules to apply, ipsec processing  
  *   is done, reinject it in ip stack  
  * - isr != NULL (error == 0) => we need to apply one rule to the packet  
  */  
 static struct ipsecrequest *  static struct ipsecrequest *
 ipsec_nextisr(  ipsec_nextisr(
         struct mbuf *m,          struct mbuf *m,
Line 400  again:
Line 369  again:
                 goto bad;                  goto bad;
         }          }
         sav = isr->sav;          sav = isr->sav;
         /* sav may be NULL here if we have an USE rule */          if (sav == NULL) {              /* XXX valid return */
         if (sav == NULL) {  
                 IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,                  IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
                         ("ipsec_nextisr: no SA found, but required; level %u",                          ("ipsec_nextisr: no SA found, but required; level %u",
                         ipsec_get_reqlevel(isr)));                          ipsec_get_reqlevel(isr)));
                 isr = isr->next;                  isr = isr->next;
                 /*  
                  * No more rules to apply, return NULL isr and no error  
                  * It can happen when the last rules are USE rules  
                  * */  
                 if (isr == NULL) {                  if (isr == NULL) {
                         *error = 0;                          /*XXXstatistic??*/
                           *error = EINVAL;                /*XXX*/
                         return isr;                          return isr;
                 }                  }
                 goto again;                  goto again;
Line 472  ipsec4_process_packet(
Line 437  ipsec4_process_packet(
         s = splsoftnet();                       /* insure SA contents don't change */          s = splsoftnet();                       /* insure SA contents don't change */
   
         isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);          isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
         if (isr == NULL) {          if (isr == NULL)
                 if (error != 0) {                  goto bad;
                         goto bad;  
                 } else {  
                         if (ipsec_register_done(m, &error) < 0)  
                                 goto bad;  
   
                         splx(s);  
                         return ipsec_reinject_ipstack(m, AF_INET);  
                 }  
         }  
   
         sav = isr->sav;          sav = isr->sav;
         if (!tunalready) {          if (!tunalready) {
Line 539  ipsec4_process_packet(
Line 495  ipsec4_process_packet(
                         ip = mtod(m, struct ip *);                          ip = mtod(m, struct ip *);
                         ip->ip_len = htons(m->m_pkthdr.len);                          ip->ip_len = htons(m->m_pkthdr.len);
                         ip->ip_sum = 0;                          ip->ip_sum = 0;
 #ifdef _IP_VHL  
                         if (ip->ip_vhl == IP_VHL_BORING)  
                                 ip->ip_sum = in_cksum_hdr(ip);  
                         else  
                                 ip->ip_sum = in_cksum(m,  
                                         _IP_VHL_HL(ip->ip_vhl) << 2);  
 #else  
                         ip->ip_sum = in_cksum(m, ip->ip_hl << 2);                          ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
 #endif  
   
                         /* Encapsulate the packet */                          /* Encapsulate the packet */
                         error = ipip_output(m, isr, &mp, 0, 0);                          error = ipip_output(m, isr, &mp, 0, 0);
Line 631  ipsec6_process_packet(
Line 579  ipsec6_process_packet(
         s = splsoftnet();   /* insure SA contents don't change */          s = splsoftnet();   /* insure SA contents don't change */
         isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);          isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
         if (isr == NULL) {          if (isr == NULL) {
                 if (error != 0) {                  // XXX Should we send a notification ?
                         // XXX Should we send a notification ?                  goto bad;
                         goto bad;  
                 } else {  
                         if (ipsec_register_done(m, &error) < 0)  
                                 goto bad;  
   
                         splx(s);  
                         return ipsec_reinject_ipstack(m, AF_INET);  
                 }  
         }          }
   
         sav = isr->sav;          sav = isr->sav;

Legend:
Removed from v.1.23.2.1  
changed lines
  Added in v.1.24

CVSweb <webmaster@jp.NetBSD.org>