]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/ah_input.c
   1 /*      $FreeBSD: src/sys/netinet6/ah_input.c,v 1.1.2.6 2002/04/28 05:40:26 suz Exp $   */ 
   2 /*      $KAME: ah_input.c,v 1.67 2002/01/07 11:39:56 kjc Exp $  */ 
   5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 
   8  * Redistribution and use in source and binary forms, with or without 
   9  * modification, are permitted provided that the following conditions 
  11  * 1. Redistributions of source code must retain the above copyright 
  12  *    notice, this list of conditions and the following disclaimer. 
  13  * 2. Redistributions in binary form must reproduce the above copyright 
  14  *    notice, this list of conditions and the following disclaimer in the 
  15  *    documentation and/or other materials provided with the distribution. 
  16  * 3. Neither the name of the project nor the names of its contributors 
  17  *    may be used to endorse or promote products derived from this software 
  18  *    without specific prior written permission. 
  20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  34  * RFC1826/2402 authentication header. 
  37 #include <sys/param.h> 
  38 #include <sys/systm.h> 
  39 #include <sys/malloc.h> 
  41 #include <sys/domain.h> 
  42 #include <sys/protosw.h> 
  43 #include <sys/socket.h> 
  44 #include <sys/errno.h> 
  46 #include <sys/kernel.h> 
  47 #include <sys/syslog.h> 
  50 #include <net/route.h> 
  51 #include <kern/cpu_number.h> 
  52 #include <kern/locks.h> 
  54 #include <netinet/in.h> 
  55 #include <netinet/in_systm.h> 
  56 #include <netinet/in_var.h> 
  57 #include <netinet/ip.h> 
  58 #include <netinet/ip_var.h> 
  59 #include <netinet/ip_ecn.h> 
  60 #include <netinet/in_pcb.h> 
  62 #include <netinet6/ip6_ecn.h> 
  66 #include <netinet/ip6.h> 
  67 #include <netinet6/ip6_var.h> 
  68 #include <netinet6/in6_pcb.h> 
  69 #include <netinet/icmp6.h> 
  70 #include <netinet6/ip6protosw.h> 
  73 #include <netinet6/ipsec.h> 
  75 #include <netinet6/ipsec6.h> 
  77 #include <netinet6/ah.h> 
  79 #include <netinet6/ah6.h> 
  81 #include <netkey/key.h> 
  82 #include <netkey/keydb.h> 
  84 #include <netkey/key_debug.h> 
  86 #define KEYDEBUG(lev,arg) 
  90 #include <net/net_osdep.h> 
  94 extern lck_mtx_t 
*sadb_mutex
; 
  96 extern struct protosw inetsw
[]; 
  99 ah4_input(struct mbuf 
*m
, int off
) 
 104         const struct ah_algorithm 
*algo
; 
 108         struct secasvar 
*sav 
= NULL
; 
 114         lck_mtx_lock(sadb_mutex
); 
 116 #ifndef PULLDOWN_TEST 
 117         if (m
->m_len 
< off 
+ sizeof(struct newah
)) { 
 118                 m 
= m_pullup(m
, off 
+ sizeof(struct newah
)); 
 120                         ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup;" 
 121                                 "dropping the packet for simplicity\n")); 
 122                         ipsecstat
.in_inval
++; 
 127         ip 
= mtod(m
, struct ip 
*); 
 128         ah 
= (struct ah 
*)(((caddr_t
)ip
) + off
); 
 130         ip 
= mtod(m
, struct ip 
*); 
 131         IP6_EXTHDR_GET(ah
, struct ah 
*, m
, off
, sizeof(struct newah
)); 
 133                 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup;" 
 134                         "dropping the packet for simplicity\n")); 
 135                 ipsecstat
.in_inval
++; 
 141         hlen 
= IP_VHL_HL(ip
->ip_vhl
) << 2; 
 143         hlen 
= ip
->ip_hl 
<< 2; 
 146         /* find the sassoc. */ 
 149         if ((sav 
= key_allocsa(AF_INET
, 
 150                               (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
, 
 151                               IPPROTO_AH
, spi
)) == 0) { 
 152                 ipseclog((LOG_WARNING
, 
 153                     "IPv4 AH input: no key association found for spi %u\n", 
 154                     (u_int32_t
)ntohl(spi
))); 
 158         KEYDEBUG(KEYDEBUG_IPSEC_STAMP
, 
 159                 printf("DP ah4_input called to allocate SA:%p\n", sav
)); 
 160         if (sav
->state 
!= SADB_SASTATE_MATURE
 
 161          && sav
->state 
!= SADB_SASTATE_DYING
) { 
 163                     "IPv4 AH input: non-mature/dying SA found for spi %u\n", 
 164                     (u_int32_t
)ntohl(spi
))); 
 165                 ipsecstat
.in_badspi
++; 
 169         algo 
= ah_algorithm_lookup(sav
->alg_auth
); 
 171                 ipseclog((LOG_DEBUG
, "IPv4 AH input: " 
 172                     "unsupported authentication algorithm for spi %u\n", 
 173                     (u_int32_t
)ntohl(spi
))); 
 174                 ipsecstat
.in_badspi
++; 
 178         siz 
= (*algo
->sumsiz
)(sav
); 
 179         siz1 
= ((siz 
+ 3) & ~(4 - 1)); 
 182          * sanity checks for header, 1. 
 187         sizoff 
= (sav
->flags 
& SADB_X_EXT_OLD
) ? 0 : 4; 
 190          * Here, we do not do "siz1 == siz".  This is because the way 
 191          * RFC240[34] section 2 is written.  They do not require truncation 
 193          * For example, Microsoft IPsec stack attaches 160 bits of 
 194          * authentication data for both hmac-md5 and hmac-sha1.  For hmac-sha1, 
 195          * 32 bits of padding is attached. 
 197          * There are two downsides to this specification. 
 198          * They have no real harm, however, they leave us fuzzy feeling. 
 199          * - if we attach more than 96 bits of authentication data onto AH, 
 200          *   we will never notice about possible modification by rogue 
 201          *   intermediate nodes. 
 202          *   Since extra bits in AH checksum is never used, this constitutes 
 203          *   no real issue, however, it is wacky. 
 204          * - even if the peer attaches big authentication data, we will never 
 205          *   notice the difference, since longer authentication data will just 
 208          * We may need some clarification in the spec. 
 211                 ipseclog((LOG_NOTICE
, "sum length too short in IPv4 AH input " 
 212                     "(%lu, should be at least %lu): %s\n", 
 213                     (u_long
)siz1
, (u_long
)siz
, 
 214                     ipsec4_logpacketstr(ip
, spi
))); 
 215                 ipsecstat
.in_inval
++; 
 218         if ((ah
->ah_len 
<< 2) - sizoff 
!= siz1
) { 
 219                 ipseclog((LOG_NOTICE
, "sum length mismatch in IPv4 AH input " 
 220                     "(%d should be %lu): %s\n", 
 221                     (ah
->ah_len 
<< 2) - sizoff
, (u_long
)siz1
, 
 222                     ipsec4_logpacketstr(ip
, spi
))); 
 223                 ipsecstat
.in_inval
++; 
 227 #ifndef PULLDOWN_TEST 
 228         if (m
->m_len 
< off 
+ sizeof(struct ah
) + sizoff 
+ siz1
) { 
 229                 m 
= m_pullup(m
, off 
+ sizeof(struct ah
) + sizoff 
+ siz1
); 
 231                         ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup\n")); 
 232                         ipsecstat
.in_inval
++; 
 236                 ip 
= mtod(m
, struct ip 
*); 
 237                 ah 
= (struct ah 
*)(((caddr_t
)ip
) + off
); 
 240         IP6_EXTHDR_GET(ah
, struct ah 
*, m
, off
, 
 241                 sizeof(struct ah
) + sizoff 
+ siz1
); 
 243                 ipseclog((LOG_DEBUG
, "IPv4 AH input: can't pullup\n")); 
 244                 ipsecstat
.in_inval
++; 
 251          * check for sequence number. 
 253         if ((sav
->flags 
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) { 
 254                 if (ipsec_chkreplay(ntohl(((struct newah 
*)ah
)->ah_seq
), sav
)) 
 257                         ipsecstat
.in_ahreplay
++; 
 258                         ipseclog((LOG_WARNING
, 
 259                             "replay packet in IPv4 AH input: %s %s\n", 
 260                             ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
))); 
 266          * alright, it seems sane.  now we are going to check the 
 267          * cryptographic checksum. 
 269         cksum 
= _MALLOC(siz1
, M_TEMP
, M_NOWAIT
); 
 271                 ipseclog((LOG_DEBUG
, "IPv4 AH input: " 
 272                     "couldn't alloc temporary region for cksum\n")); 
 273                 ipsecstat
.in_inval
++; 
 278          * some of IP header fields are flipped to the host endian. 
 279          * convert them back to network endian.  VERY stupid. 
 281         ip
->ip_len 
= htons(ip
->ip_len 
+ hlen
); 
 282         ip
->ip_off 
= htons(ip
->ip_off
); 
 283         if (ah4_calccksum(m
, (caddr_t
)cksum
, siz1
, algo
, sav
)) { 
 285                 ipsecstat
.in_inval
++; 
 288         ipsecstat
.in_ahhist
[sav
->alg_auth
]++; 
 292         ip
->ip_len 
= ntohs(ip
->ip_len
) - hlen
; 
 293         ip
->ip_off 
= ntohs(ip
->ip_off
); 
 296         caddr_t sumpos 
= NULL
; 
 298         if (sav
->flags 
& SADB_X_EXT_OLD
) { 
 300                 sumpos 
= (caddr_t
)(ah 
+ 1); 
 303                 sumpos 
= (caddr_t
)(((struct newah 
*)ah
) + 1); 
 306         if (bcmp(sumpos
, cksum
, siz
) != 0) { 
 307                 ipseclog((LOG_WARNING
, 
 308                     "checksum mismatch in IPv4 AH input: %s %s\n", 
 309                     ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
))); 
 311                 ipsecstat
.in_ahauthfail
++; 
 318         m
->m_flags 
|= M_AUTHIPHDR
; 
 319         m
->m_flags 
|= M_AUTHIPDGM
; 
 323          * looks okey, but we need more sanity check. 
 324          * XXX should elaborate. 
 326         if (ah
->ah_nxt 
== IPPROTO_IPIP 
|| ah
->ah_nxt 
== IPPROTO_IP
) { 
 330                 sizoff 
= (sav
->flags 
& SADB_X_EXT_OLD
) ? 0 : 4; 
 332                 if (m
->m_len 
< off 
+ sizeof(struct ah
) + sizoff 
+ siz1 
+ hlen
) { 
 333                         m 
= m_pullup(m
, off 
+ sizeof(struct ah
) 
 334                                         + sizoff 
+ siz1 
+ hlen
); 
 337                                     "IPv4 AH input: can't pullup\n")); 
 338                                 ipsecstat
.in_inval
++; 
 343                 nip 
= (struct ip 
*)((u_char 
*)(ah 
+ 1) + sizoff 
+ siz1
); 
 344                 if (nip
->ip_src
.s_addr 
!= ip
->ip_src
.s_addr
 
 345                  || nip
->ip_dst
.s_addr 
!= ip
->ip_dst
.s_addr
) { 
 346                         m
->m_flags 
&= ~M_AUTHIPHDR
; 
 347                         m
->m_flags 
&= ~M_AUTHIPDGM
; 
 351         else if (ah
->ah_nxt 
== IPPROTO_IPV6
) { 
 352                 m
->m_flags 
&= ~M_AUTHIPHDR
; 
 353                 m
->m_flags 
&= ~M_AUTHIPDGM
; 
 358         if (m
->m_flags 
& M_AUTHIPHDR
 
 359          && m
->m_flags 
& M_AUTHIPDGM
) { 
 362                     "IPv4 AH input: authentication succeess\n")); 
 364                 ipsecstat
.in_ahauthsucc
++; 
 366                 ipseclog((LOG_WARNING
, 
 367                     "authentication failed in IPv4 AH input: %s %s\n", 
 368                     ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
))); 
 369                 ipsecstat
.in_ahauthfail
++; 
 374          * update sequence number. 
 376         if ((sav
->flags 
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) { 
 377                 if (ipsec_updatereplay(ntohl(((struct newah 
*)ah
)->ah_seq
), sav
)) { 
 378                         ipsecstat
.in_ahreplay
++; 
 383         /* was it transmitted over the IPsec tunnel SA? */ 
 384         if (sav
->flags 
& SADB_X_EXT_OLD
) { 
 386                 stripsiz 
= sizeof(struct ah
) + siz1
; 
 389                 stripsiz 
= sizeof(struct newah
) + siz1
; 
 391         if (ipsec4_tunnel_validate(m
, off 
+ stripsiz
, nxt
, sav
)) { 
 393                  * strip off all the headers that precedes AH. 
 394                  *      IP xx AH IP' payload -> IP' payload 
 396                  * XXX more sanity checks 
 397                  * XXX relationship with gif? 
 402                 m_adj(m
, off 
+ stripsiz
); 
 403                 if (m
->m_len 
< sizeof(*ip
)) { 
 404                         m 
= m_pullup(m
, sizeof(*ip
)); 
 406                                 ipsecstat
.in_inval
++; 
 410                 ip 
= mtod(m
, struct ip 
*); 
 411                 /* ECN consideration. */ 
 412                 ip_ecn_egress(ip4_ipsec_ecn
, &tos
, &ip
->ip_tos
); 
 413                 if (!key_checktunnelsanity(sav
, AF_INET
, 
 414                             (caddr_t
)&ip
->ip_src
, (caddr_t
)&ip
->ip_dst
)) { 
 415                         ipseclog((LOG_NOTICE
, "ipsec tunnel address mismatch " 
 416                             "in IPv4 AH input: %s %s\n", 
 417                             ipsec4_logpacketstr(ip
, spi
), ipsec_logsastr(sav
))); 
 418                         ipsecstat
.in_inval
++; 
 424                  * Should the inner packet be considered authentic? 
 425                  * My current answer is: NO. 
 427                  * host1 -- gw1 === gw2 -- host2 
 428                  *      In this case, gw2 can trust the authenticity of the 
 429                  *      outer packet, but NOT inner.  Packet may be altered 
 430                  *      between host1 and gw1. 
 432                  * host1 -- gw1 === host2 
 433                  *      This case falls into the same scenario as above. 
 436                  *      This case is the only case when we may be able to leave 
 437                  *      M_AUTHIPHDR and M_AUTHIPDGM set. 
 438                  *      However, if host1 is wrongly configured, and allows 
 439                  *      attacker to inject some packet with src=host1 and 
 440                  *      dst=host2, you are in risk. 
 442                 m
->m_flags 
&= ~M_AUTHIPHDR
; 
 443                 m
->m_flags 
&= ~M_AUTHIPDGM
; 
 446                 key_sa_recordxfer(sav
, m
); 
 447                 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0 || 
 448                     ipsec_addhist(m
, IPPROTO_IPV4
, 0) != 0) { 
 449                         ipsecstat
.in_nomem
++; 
 452                 lck_mtx_unlock(sadb_mutex
); 
 453                 proto_input(PF_INET
, m
); 
 454                 lck_mtx_lock(sadb_mutex
); 
 461                 ip 
= mtod(m
, struct ip 
*); 
 462 #ifndef PULLDOWN_TEST 
 464                  * We do deep-copy since KAME requires that 
 465                  * the packet is placed in a single external mbuf. 
 467                 ovbcopy((caddr_t
)ip
, (caddr_t
)(((u_char 
*)ip
) + stripsiz
), off
); 
 468                 m
->m_data 
+= stripsiz
; 
 469                 m
->m_len 
-= stripsiz
; 
 470                 m
->m_pkthdr
.len 
-= stripsiz
; 
 473                  * even in m_pulldown case, we need to strip off AH so that 
 474                  * we can compute checksum for multiple AH correctly. 
 476                 if (m
->m_len 
>= stripsiz 
+ off
) { 
 477                         ovbcopy((caddr_t
)ip
, ((caddr_t
)ip
) + stripsiz
, off
); 
 478                         m
->m_data 
+= stripsiz
; 
 479                         m
->m_len 
-= stripsiz
; 
 480                         m
->m_pkthdr
.len 
-= stripsiz
; 
 483                          * this comes with no copy if the boundary is on 
 488                         n 
= m_split(m
, off
, M_DONTWAIT
); 
 490                                 /* m is retained by m_split */ 
 494                         /* m_cat does not update m_pkthdr.len */ 
 495                         m
->m_pkthdr
.len 
+= n
->m_pkthdr
.len
; 
 500                 if (m
->m_len 
< sizeof(*ip
)) { 
 501                         m 
= m_pullup(m
, sizeof(*ip
)); 
 503                                 ipsecstat
.in_inval
++; 
 507                 ip 
= mtod(m
, struct ip 
*); 
 509                 ip
->ip_len 
= ip
->ip_len 
- stripsiz
; 
 511                 ip
->ip_len 
= htons(ntohs(ip
->ip_len
) - stripsiz
); 
 514                 /* forget about IP hdr checksum, the check has already been passed */ 
 516                 key_sa_recordxfer(sav
, m
); 
 517                 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0) { 
 518                         ipsecstat
.in_nomem
++; 
 522                 if (nxt 
!= IPPROTO_DONE
) { 
 523                         if ((ip_protox
[nxt
]->pr_flags 
& PR_LASTHDR
) != 0 && 
 524                             ipsec4_in_reject(m
, NULL
)) { 
 525                                 ipsecstat
.in_polvio
++; 
 528                         lck_mtx_unlock(sadb_mutex
); 
 529                         ip_proto_dispatch_in(m
, off
, nxt
, 0); 
 530                         lck_mtx_lock(sadb_mutex
); 
 537                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
, 
 538                         printf("DP ah4_input call free SA:%p\n", sav
)); 
 541         ipsecstat
.in_success
++; 
 542         lck_mtx_unlock(sadb_mutex
); 
 547                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
, 
 548                         printf("DP ah4_input call free SA:%p\n", sav
)); 
 551         lck_mtx_unlock(sadb_mutex
); 
 564         struct mbuf 
*m 
= *mp
; 
 569         const struct ah_algorithm 
*algo
; 
 573         struct secasvar 
*sav 
= NULL
; 
 578         lck_mtx_lock(sadb_mutex
); 
 580 #ifndef PULLDOWN_TEST 
 581         IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
), {lck_mtx_unlock(sadb_mutex
);return IPPROTO_DONE
;}); 
 582         ah 
= (struct ah 
*)(mtod(m
, caddr_t
) + off
); 
 584         IP6_EXTHDR_GET(ah
, struct ah 
*, m
, off
, sizeof(struct newah
)); 
 586                 ipseclog((LOG_DEBUG
, "IPv6 AH input: can't pullup\n")); 
 587                 ipsec6stat
.in_inval
++; 
 588                 lck_mtx_unlock(sadb_mutex
); 
 592         ip6 
= mtod(m
, struct ip6_hdr 
*); 
 595         /* find the sassoc.  */ 
 598         if (ntohs(ip6
->ip6_plen
) == 0) { 
 599                 ipseclog((LOG_ERR
, "IPv6 AH input: " 
 600                     "AH with IPv6 jumbogram is not supported.\n")); 
 601                 ipsec6stat
.in_inval
++; 
 605         if ((sav 
= key_allocsa(AF_INET6
, 
 606                               (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
, 
 607                               IPPROTO_AH
, spi
)) == 0) { 
 608                 ipseclog((LOG_WARNING
, 
 609                     "IPv6 AH input: no key association found for spi %u\n", 
 610                     (u_int32_t
)ntohl(spi
))); 
 611                 ipsec6stat
.in_nosa
++; 
 614         KEYDEBUG(KEYDEBUG_IPSEC_STAMP
, 
 615                 printf("DP ah6_input called to allocate SA:%p\n", sav
)); 
 616         if (sav
->state 
!= SADB_SASTATE_MATURE
 
 617          && sav
->state 
!= SADB_SASTATE_DYING
) { 
 619                     "IPv6 AH input: non-mature/dying SA found for spi %u; ", 
 620                     (u_int32_t
)ntohl(spi
))); 
 621                 ipsec6stat
.in_badspi
++; 
 625         algo 
= ah_algorithm_lookup(sav
->alg_auth
); 
 627                 ipseclog((LOG_DEBUG
, "IPv6 AH input: " 
 628                     "unsupported authentication algorithm for spi %u\n", 
 629                     (u_int32_t
)ntohl(spi
))); 
 630                 ipsec6stat
.in_badspi
++; 
 634         siz 
= (*algo
->sumsiz
)(sav
); 
 635         siz1 
= ((siz 
+ 3) & ~(4 - 1)); 
 638          * sanity checks for header, 1. 
 643         sizoff 
= (sav
->flags 
& SADB_X_EXT_OLD
) ? 0 : 4; 
 646          * Here, we do not do "siz1 == siz".  See ah4_input() for complete 
 650                 ipseclog((LOG_NOTICE
, "sum length too short in IPv6 AH input " 
 651                     "(%lu, should be at least %lu): %s\n", 
 652                     (u_long
)siz1
, (u_long
)siz
, 
 653                     ipsec6_logpacketstr(ip6
, spi
))); 
 654                 ipsec6stat
.in_inval
++; 
 657         if ((ah
->ah_len 
<< 2) - sizoff 
!= siz1
) { 
 658                 ipseclog((LOG_NOTICE
, "sum length mismatch in IPv6 AH input " 
 659                     "(%d should be %lu): %s\n", 
 660                     (ah
->ah_len 
<< 2) - sizoff
, (u_long
)siz1
, 
 661                     ipsec6_logpacketstr(ip6
, spi
))); 
 662                 ipsec6stat
.in_inval
++; 
 665 #ifndef PULLDOWN_TEST 
 666         IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
) + sizoff 
+ siz1
,  
 667                 {lck_mtx_unlock(sadb_mutex
);return IPPROTO_DONE
;}); 
 669         IP6_EXTHDR_GET(ah
, struct ah 
*, m
, off
, 
 670                 sizeof(struct ah
) + sizoff 
+ siz1
); 
 672                 ipseclog((LOG_NOTICE
, "couldn't pullup gather IPv6 AH checksum part")); 
 673                 ipsec6stat
.in_inval
++; 
 681          * check for sequence number. 
 683         if ((sav
->flags 
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) { 
 684                 if (ipsec_chkreplay(ntohl(((struct newah 
*)ah
)->ah_seq
), sav
)) 
 687                         ipsec6stat
.in_ahreplay
++; 
 688                         ipseclog((LOG_WARNING
, 
 689                             "replay packet in IPv6 AH input: %s %s\n", 
 690                             ipsec6_logpacketstr(ip6
, spi
), 
 691                             ipsec_logsastr(sav
))); 
 697          * alright, it seems sane.  now we are going to check the 
 698          * cryptographic checksum. 
 700         cksum 
= _MALLOC(siz1
, M_TEMP
, M_NOWAIT
); 
 702                 ipseclog((LOG_DEBUG
, "IPv6 AH input: " 
 703                     "couldn't alloc temporary region for cksum\n")); 
 704                 ipsec6stat
.in_inval
++; 
 708         if (ah6_calccksum(m
, (caddr_t
)cksum
, siz1
, algo
, sav
)) { 
 710                 ipsec6stat
.in_inval
++; 
 713         ipsec6stat
.in_ahhist
[sav
->alg_auth
]++; 
 716         caddr_t sumpos 
= NULL
; 
 718         if (sav
->flags 
& SADB_X_EXT_OLD
) { 
 720                 sumpos 
= (caddr_t
)(ah 
+ 1); 
 723                 sumpos 
= (caddr_t
)(((struct newah 
*)ah
) + 1); 
 726         if (bcmp(sumpos
, cksum
, siz
) != 0) { 
 727                 ipseclog((LOG_WARNING
, 
 728                     "checksum mismatch in IPv6 AH input: %s %s\n", 
 729                     ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
))); 
 731                 ipsec6stat
.in_ahauthfail
++; 
 738         m
->m_flags 
|= M_AUTHIPHDR
; 
 739         m
->m_flags 
|= M_AUTHIPDGM
; 
 743          * looks okey, but we need more sanity check. 
 744          * XXX should elaborate. 
 746         if (ah
->ah_nxt 
== IPPROTO_IPV6
) { 
 747                 struct ip6_hdr 
*nip6
; 
 750                 sizoff 
= (sav
->flags 
& SADB_X_EXT_OLD
) ? 0 : 4; 
 752                 IP6_EXTHDR_CHECK(m
, off
, sizeof(struct ah
) + sizoff 
+ siz1
 
 753                                 + sizeof(struct ip6_hdr
),  
 754                                 {lck_mtx_unlock(sadb_mutex
);return IPPROTO_DONE
;}); 
 756                 nip6 
= (struct ip6_hdr 
*)((u_char 
*)(ah 
+ 1) + sizoff 
+ siz1
); 
 757                 if (!IN6_ARE_ADDR_EQUAL(&nip6
->ip6_src
, &ip6
->ip6_src
) 
 758                  || !IN6_ARE_ADDR_EQUAL(&nip6
->ip6_dst
, &ip6
->ip6_dst
)) { 
 759                         m
->m_flags 
&= ~M_AUTHIPHDR
; 
 760                         m
->m_flags 
&= ~M_AUTHIPDGM
; 
 762         } else if (ah
->ah_nxt 
== IPPROTO_IPIP
) { 
 763                 m
->m_flags 
&= ~M_AUTHIPHDR
; 
 764                 m
->m_flags 
&= ~M_AUTHIPDGM
; 
 765         } else if (ah
->ah_nxt 
== IPPROTO_IP
) { 
 766                 m
->m_flags 
&= ~M_AUTHIPHDR
; 
 767                 m
->m_flags 
&= ~M_AUTHIPDGM
; 
 771         if (m
->m_flags 
& M_AUTHIPHDR
 
 772          && m
->m_flags 
& M_AUTHIPDGM
) { 
 775                     "IPv6 AH input: authentication succeess\n")); 
 777                 ipsec6stat
.in_ahauthsucc
++; 
 779                 ipseclog((LOG_WARNING
, 
 780                     "authentication failed in IPv6 AH input: %s %s\n", 
 781                     ipsec6_logpacketstr(ip6
, spi
), ipsec_logsastr(sav
))); 
 782                 ipsec6stat
.in_ahauthfail
++; 
 787          * update sequence number. 
 789         if ((sav
->flags 
& SADB_X_EXT_OLD
) == 0 && sav
->replay
) { 
 790                 if (ipsec_updatereplay(ntohl(((struct newah 
*)ah
)->ah_seq
), sav
)) { 
 791                         ipsec6stat
.in_ahreplay
++; 
 796         /* was it transmitted over the IPsec tunnel SA? */ 
 797         if (sav
->flags 
& SADB_X_EXT_OLD
) { 
 799                 stripsiz 
= sizeof(struct ah
) + siz1
; 
 802                 stripsiz 
= sizeof(struct newah
) + siz1
; 
 804         if (ipsec6_tunnel_validate(m
, off 
+ stripsiz
, nxt
, sav
)) { 
 806                  * strip off all the headers that precedes AH. 
 807                  *      IP6 xx AH IP6' payload -> IP6' payload 
 809                  * XXX more sanity checks 
 810                  * XXX relationship with gif? 
 812                 u_int32_t flowinfo
;     /*net endian*/ 
 814                 flowinfo 
= ip6
->ip6_flow
; 
 815                 m_adj(m
, off 
+ stripsiz
); 
 816                 if (m
->m_len 
< sizeof(*ip6
)) { 
 818                          * m_pullup is prohibited in KAME IPv6 input processing 
 819                          * but there's no other way! 
 821                         m 
= m_pullup(m
, sizeof(*ip6
)); 
 823                                 ipsec6stat
.in_inval
++; 
 827                 ip6 
= mtod(m
, struct ip6_hdr 
*); 
 828                 /* ECN consideration. */ 
 829                 ip6_ecn_egress(ip6_ipsec_ecn
, &flowinfo
, &ip6
->ip6_flow
); 
 830                 if (!key_checktunnelsanity(sav
, AF_INET6
, 
 831                             (caddr_t
)&ip6
->ip6_src
, (caddr_t
)&ip6
->ip6_dst
)) { 
 832                         ipseclog((LOG_NOTICE
, "ipsec tunnel address mismatch " 
 833                             "in IPv6 AH input: %s %s\n", 
 834                             ipsec6_logpacketstr(ip6
, spi
), 
 835                             ipsec_logsastr(sav
))); 
 836                         ipsec6stat
.in_inval
++; 
 842                  * should the inner packet be considered authentic? 
 843                  * see comment in ah4_input(). 
 845                 m
->m_flags 
&= ~M_AUTHIPHDR
; 
 846                 m
->m_flags 
&= ~M_AUTHIPDGM
; 
 849                 key_sa_recordxfer(sav
, m
); 
 850                 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0 || 
 851                     ipsec_addhist(m
, IPPROTO_IPV6
, 0) != 0) { 
 852                         ipsec6stat
.in_nomem
++; 
 855                 lck_mtx_unlock(sadb_mutex
); 
 856                 proto_input(PF_INET6
, m
); 
 857                 lck_mtx_lock(sadb_mutex
); 
 866                  * Copy the value of the next header field of AH to the 
 867                  * next header field of the previous header. 
 868                  * This is necessary because AH will be stripped off below. 
 870                 prvnxtp 
= ip6_get_prevhdr(m
, off
); /* XXX */ 
 873                 ip6 
= mtod(m
, struct ip6_hdr 
*); 
 874 #ifndef PULLDOWN_TEST 
 876                  * We do deep-copy since KAME requires that 
 877                  * the packet is placed in a single mbuf. 
 879                 ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
); 
 880                 m
->m_data 
+= stripsiz
; 
 881                 m
->m_len 
-= stripsiz
; 
 882                 m
->m_pkthdr
.len 
-= stripsiz
; 
 885                  * even in m_pulldown case, we need to strip off AH so that 
 886                  * we can compute checksum for multiple AH correctly. 
 888                 if (m
->m_len 
>= stripsiz 
+ off
) { 
 889                         ovbcopy((caddr_t
)ip6
, ((caddr_t
)ip6
) + stripsiz
, off
); 
 890                         m
->m_data 
+= stripsiz
; 
 891                         m
->m_len 
-= stripsiz
; 
 892                         m
->m_pkthdr
.len 
-= stripsiz
; 
 895                          * this comes with no copy if the boundary is on 
 900                         n 
= m_split(m
, off
, M_DONTWAIT
); 
 902                                 /* m is retained by m_split */ 
 906                         /* m_cat does not update m_pkthdr.len */ 
 907                         m
->m_pkthdr
.len 
+= n
->m_pkthdr
.len
; 
 911                 ip6 
= mtod(m
, struct ip6_hdr 
*); 
 913                 ip6
->ip6_plen 
= htons(ntohs(ip6
->ip6_plen
) - stripsiz
); 
 915                 key_sa_recordxfer(sav
, m
); 
 916                 if (ipsec_addhist(m
, IPPROTO_AH
, spi
) != 0) { 
 917                         ipsec6stat
.in_nomem
++; 
 926                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
, 
 927                         printf("DP ah6_input call free SA:%p\n", sav
)); 
 930         ipsec6stat
.in_success
++; 
 931         lck_mtx_unlock(sadb_mutex
); 
 936                 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
, 
 937                         printf("DP ah6_input call free SA:%p\n", sav
)); 
 940         lck_mtx_unlock(sadb_mutex
); 
 947 ah6_ctlinput(cmd
, sa
, d
) 
 952         const struct newah 
*ahp
; 
 954         struct secasvar 
*sav
; 
 957         struct ip6ctlparam 
*ip6cp 
= NULL
; 
 959         struct sockaddr_in6 
*sa6_src
, *sa6_dst
; 
 961         if (sa
->sa_family 
!= AF_INET6 
|| 
 962             sa
->sa_len 
!= sizeof(struct sockaddr_in6
)) 
 964         if ((unsigned)cmd 
>= PRC_NCMDS
) 
 967         /* if the parameter is from icmp6, decode it. */ 
 969                 ip6cp 
= (struct ip6ctlparam 
*)d
; 
 971                 ip6 
= ip6cp
->ip6c_ip6
; 
 972                 off 
= ip6cp
->ip6c_off
; 
 980                  * XXX: We assume that when ip6 is non NULL, 
 981                  * M and OFF are valid. 
 984                 /* check if we can safely examine src and dst ports */ 
 985                 if (m
->m_pkthdr
.len 
< off 
+ sizeof(ah
)) 
 988                 if (m
->m_len 
< off 
+ sizeof(ah
)) { 
 990                          * this should be rare case, 
 991                          * so we compromise on this copy... 
 993                         m_copydata(m
, off
, sizeof(ah
), (caddr_t
)&ah
); 
 996                         ahp 
= (struct newah 
*)(mtod(m
, caddr_t
) + off
); 
 998                 if (cmd 
== PRC_MSGSIZE
) { 
1002                          * Check to see if we have a valid SA corresponding to 
1003                          * the address in the ICMP message payload. 
1005                         sa6_src 
= ip6cp
->ip6c_src
; 
1006                         sa6_dst 
= (struct sockaddr_in6 
*)sa
; 
1007                         lck_mtx_lock(sadb_mutex
); 
1008                         sav 
= key_allocsa(AF_INET6
, 
1009                                           (caddr_t
)&sa6_src
->sin6_addr
, 
1010                                           (caddr_t
)&sa6_dst
->sin6_addr
, 
1011                                           IPPROTO_AH
, ahp
->ah_spi
); 
1013                                 if (sav
->state 
== SADB_SASTATE_MATURE 
|| 
1014                                     sav
->state 
== SADB_SASTATE_DYING
) 
1018                         lck_mtx_unlock(sadb_mutex
); 
1020                         /* XXX Further validation? */ 
1023                          * Depending on the value of "valid" and routing table 
1024                          * size (mtudisc_{hi,lo}wat), we will: 
1025                          * - recalcurate the new MTU and create the 
1026                          *   corresponding routing entry, or 
1027                          * - ignore the MTU change notification. 
1029                         icmp6_mtudisc_update((struct ip6ctlparam 
*)d
, valid
); 
1032                 /* we normally notify single pcb here */ 
1034                 /* we normally notify any pcb here */