const EVP_CIPHER * EVP_aes_ ## keylen ## _ ## mode ( void ) \ {
 return & aes_ ## keylen ## _ ## mode ;
 }
 # endif # if defined ( OPENSSL_CPUID_OBJ ) && ( defined ( __arm__ ) || defined ( __arm ) || defined ( __aarch64__ ) ) # include "arm_arch.h" # if __ARM_MAX_ARCH__ >= 7 # if defined ( BSAES_ASM ) # define BSAES_CAPABLE ( OPENSSL_armcap_P & ARMV7_NEON ) # endif # if defined ( VPAES_ASM ) # define VPAES_CAPABLE ( OPENSSL_armcap_P & ARMV7_NEON ) # endif # define HWAES_CAPABLE ( OPENSSL_armcap_P & ARMV8_AES ) # define HWAES_set_encrypt_key aes_v8_set_encrypt_key # define HWAES_set_decrypt_key aes_v8_set_decrypt_key # define HWAES_encrypt aes_v8_encrypt # define HWAES_decrypt aes_v8_decrypt # define HWAES_cbc_encrypt aes_v8_cbc_encrypt # define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks # endif # endif # if defined ( HWAES_CAPABLE ) int HWAES_set_encrypt_key ( const unsigned char * userKey , const int bits , AES_KEY * key ) ;
 int HWAES_set_decrypt_key ( const unsigned char * userKey , const int bits , AES_KEY * key ) ;
 void HWAES_encrypt ( const unsigned char * in , unsigned char * out , const AES_KEY * key ) ;
 void HWAES_decrypt ( const unsigned char * in , unsigned char * out , const AES_KEY * key ) ;
 void HWAES_cbc_encrypt ( const unsigned char * in , unsigned char * out , size_t length , const AES_KEY * key , unsigned char * ivec , const int enc ) ;
 void HWAES_ctr32_encrypt_blocks ( const unsigned char * in , unsigned char * out , size_t len , const AES_KEY * key , const unsigned char ivec [ 16 ] ) ;
 void HWAES_xts_encrypt ( const unsigned char * inp , unsigned char * out , size_t len , const AES_KEY * key1 , const AES_KEY * key2 , const unsigned char iv [ 16 ] ) ;
 void HWAES_xts_decrypt ( const unsigned char * inp , unsigned char * out , size_t len , const AES_KEY * key1 , const AES_KEY * key2 , const unsigned char iv [ 16 ] ) ;
 # endif # define BLOCK_CIPHER_generic_pack ( nid , keylen , flags ) \ BLOCK_CIPHER_generic ( nid , keylen , 16 , 16 , cbc , cbc , CBC , flags | EVP_CIPH_FLAG_DEFAULT_ASN1 ) \ BLOCK_CIPHER_generic ( nid , keylen , 16 , 0 , ecb , ecb , ECB , flags | EVP_CIPH_FLAG_DEFAULT_ASN1 ) \ BLOCK_CIPHER_generic ( nid , keylen , 1 , 16 , ofb128 , ofb , OFB , flags | EVP_CIPH_FLAG_DEFAULT_ASN1 ) \ BLOCK_CIPHER_generic ( nid , keylen , 1 , 16 , cfb128 , cfb , CFB , flags | EVP_CIPH_FLAG_DEFAULT_ASN1 ) \ BLOCK_CIPHER_generic ( nid , keylen , 1 , 16 , cfb1 , cfb1 , CFB , flags ) \ BLOCK_CIPHER_generic ( nid , keylen , 1 , 16 , cfb8 , cfb8 , CFB , flags ) \ BLOCK_CIPHER_generic ( nid , keylen , 1 , 16 , ctr , ctr , CTR , flags ) static int aes_init_key ( EVP_CIPHER_CTX * ctx , const unsigned char * key , const unsigned char * iv , int enc ) {
 int ret , mode ;
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 mode = EVP_CIPHER_CTX_mode ( ctx ) ;
 if ( ( mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE ) && ! enc ) {
 # ifdef HWAES_CAPABLE if ( HWAES_CAPABLE ) {
 ret = HWAES_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) HWAES_decrypt ;
 dat -> stream . cbc = NULL ;
 # ifdef HWAES_cbc_encrypt if ( mode == EVP_CIPH_CBC_MODE ) dat -> stream . cbc = ( cbc128_f ) HWAES_cbc_encrypt ;
 # endif }
 else # endif # ifdef BSAES_CAPABLE if ( BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE ) {
 ret = AES_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) AES_decrypt ;
 dat -> stream . cbc = ( cbc128_f ) bsaes_cbc_encrypt ;
 }
 else # endif # ifdef VPAES_CAPABLE if ( VPAES_CAPABLE ) {
 ret = vpaes_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) vpaes_decrypt ;
 dat -> stream . cbc = mode == EVP_CIPH_CBC_MODE ? ( cbc128_f ) vpaes_cbc_encrypt : NULL ;
 }
 else # endif {
 ret = AES_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) AES_decrypt ;
 dat -> stream . cbc = mode == EVP_CIPH_CBC_MODE ? ( cbc128_f ) AES_cbc_encrypt : NULL ;
 }
 }
 else # ifdef HWAES_CAPABLE if ( HWAES_CAPABLE ) {
 ret = HWAES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) HWAES_encrypt ;
 dat -> stream . cbc = NULL ;
 # ifdef HWAES_cbc_encrypt if ( mode == EVP_CIPH_CBC_MODE ) dat -> stream . cbc = ( cbc128_f ) HWAES_cbc_encrypt ;
 else # endif # ifdef HWAES_ctr32_encrypt_blocks if ( mode == EVP_CIPH_CTR_MODE ) dat -> stream . ctr = ( ctr128_f ) HWAES_ctr32_encrypt_blocks ;
 else # endif ( void ) 0 ;
 }
 else # endif # ifdef BSAES_CAPABLE if ( BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE ) {
 ret = AES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) AES_encrypt ;
 dat -> stream . ctr = ( ctr128_f ) bsaes_ctr32_encrypt_blocks ;
 }
 else # endif # ifdef VPAES_CAPABLE if ( VPAES_CAPABLE ) {
 ret = vpaes_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) vpaes_encrypt ;
 dat -> stream . cbc = mode == EVP_CIPH_CBC_MODE ? ( cbc128_f ) vpaes_cbc_encrypt : NULL ;
 }
 else # endif {
 ret = AES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & dat -> ks . ks ) ;
 dat -> block = ( block128_f ) AES_encrypt ;
 dat -> stream . cbc = mode == EVP_CIPH_CBC_MODE ? ( cbc128_f ) AES_cbc_encrypt : NULL ;
 # ifdef AES_CTR_ASM if ( mode == EVP_CIPH_CTR_MODE ) dat -> stream . ctr = ( ctr128_f ) AES_ctr32_encrypt ;
 # endif }
 if ( ret < 0 ) {
 EVPerr ( EVP_F_AES_INIT_KEY , EVP_R_AES_KEY_SETUP_FAILED ) ;
 return 0 ;
 }
 return 1 ;
 }
 static int aes_cbc_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 if ( dat -> stream . cbc ) ( * dat -> stream . cbc ) ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , EVP_CIPHER_CTX_encrypting ( ctx ) ) ;
 else if ( EVP_CIPHER_CTX_encrypting ( ctx ) ) CRYPTO_cbc128_encrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , dat -> block ) ;
 else CRYPTO_cbc128_decrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , dat -> block ) ;
 return 1 ;
 }
 static int aes_ecb_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 size_t bl = EVP_CIPHER_CTX_block_size ( ctx ) ;
 size_t i ;
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 if ( len < bl ) return 1 ;
 for ( i = 0 , len -= bl ;
 i <= len ;
 i += bl ) ( * dat -> block ) ( in + i , out + i , & dat -> ks ) ;
 return 1 ;
 }
 static int aes_ofb_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 int num = EVP_CIPHER_CTX_num ( ctx ) ;
 CRYPTO_ofb128_encrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , & num , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 return 1 ;
 }
 static int aes_cfb_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 int num = EVP_CIPHER_CTX_num ( ctx ) ;
 CRYPTO_cfb128_encrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , & num , EVP_CIPHER_CTX_encrypting ( ctx ) , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 return 1 ;
 }
 static int aes_cfb8_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 int num = EVP_CIPHER_CTX_num ( ctx ) ;
 CRYPTO_cfb128_8_encrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , & num , EVP_CIPHER_CTX_encrypting ( ctx ) , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 return 1 ;
 }
 static int aes_cfb1_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 if ( EVP_CIPHER_CTX_test_flags ( ctx , EVP_CIPH_FLAG_LENGTH_BITS ) ) {
 int num = EVP_CIPHER_CTX_num ( ctx ) ;
 CRYPTO_cfb128_1_encrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , & num , EVP_CIPHER_CTX_encrypting ( ctx ) , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 return 1 ;
 }
 while ( len >= MAXBITCHUNK ) {
 int num = EVP_CIPHER_CTX_num ( ctx ) ;
 CRYPTO_cfb128_1_encrypt ( in , out , MAXBITCHUNK * 8 , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , & num , EVP_CIPHER_CTX_encrypting ( ctx ) , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 len -= MAXBITCHUNK ;
 }
 if ( len ) {
 int num = EVP_CIPHER_CTX_num ( ctx ) ;
 CRYPTO_cfb128_1_encrypt ( in , out , len * 8 , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , & num , EVP_CIPHER_CTX_encrypting ( ctx ) , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 }
 return 1 ;
 }
 static int aes_ctr_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 unsigned int num = EVP_CIPHER_CTX_num ( ctx ) ;
 EVP_AES_KEY * dat = EVP_C_DATA ( EVP_AES_KEY , ctx ) ;
 if ( dat -> stream . ctr ) CRYPTO_ctr128_encrypt_ctr32 ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , EVP_CIPHER_CTX_buf_noconst ( ctx ) , & num , dat -> stream . ctr ) ;
 else CRYPTO_ctr128_encrypt ( in , out , len , & dat -> ks , EVP_CIPHER_CTX_iv_noconst ( ctx ) , EVP_CIPHER_CTX_buf_noconst ( ctx ) , & num , dat -> block ) ;
 EVP_CIPHER_CTX_set_num ( ctx , num ) ;
 return 1 ;
 }
 BLOCK_CIPHER_generic_pack ( NID_aes , 128 , 0 ) BLOCK_CIPHER_generic_pack ( NID_aes , 192 , 0 ) BLOCK_CIPHER_generic_pack ( NID_aes , 256 , 0 ) static int aes_gcm_cleanup ( EVP_CIPHER_CTX * c ) {
 EVP_AES_GCM_CTX * gctx = EVP_C_DATA ( EVP_AES_GCM_CTX , c ) ;
 OPENSSL_cleanse ( & gctx -> gcm , sizeof ( gctx -> gcm ) ) ;
 if ( gctx -> iv != EVP_CIPHER_CTX_iv_noconst ( c ) ) OPENSSL_free ( gctx -> iv ) ;
 return 1 ;
 }
 static void ctr64_inc ( unsigned char * counter ) {
 int n = 8 ;
 unsigned char c ;
 do {
 -- n ;
 c = counter [ n ] ;
 ++ c ;
 counter [ n ] = c ;
 if ( c ) return ;
 }
 while ( n ) ;
 }
 static int aes_gcm_ctrl ( EVP_CIPHER_CTX * c , int type , int arg , void * ptr ) {
 EVP_AES_GCM_CTX * gctx = EVP_C_DATA ( EVP_AES_GCM_CTX , c ) ;
 switch ( type ) {
 case EVP_CTRL_INIT : gctx -> key_set = 0 ;
 gctx -> iv_set = 0 ;
 gctx -> ivlen = EVP_CIPHER_CTX_iv_length ( c ) ;
 gctx -> iv = EVP_CIPHER_CTX_iv_noconst ( c ) ;
 gctx -> taglen = - 1 ;
 gctx -> iv_gen = 0 ;
 gctx -> tls_aad_len = - 1 ;
 return 1 ;
 case EVP_CTRL_AEAD_SET_IVLEN : if ( arg <= 0 ) return 0 ;
 if ( ( arg > EVP_MAX_IV_LENGTH ) && ( arg > gctx -> ivlen ) ) {
 if ( gctx -> iv != EVP_CIPHER_CTX_iv_noconst ( c ) ) OPENSSL_free ( gctx -> iv ) ;
 gctx -> iv = OPENSSL_malloc ( arg ) ;
 if ( gctx -> iv == NULL ) return 0 ;
 }
 gctx -> ivlen = arg ;
 return 1 ;
 case EVP_CTRL_AEAD_SET_TAG : if ( arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting ( c ) ) return 0 ;
 memcpy ( EVP_CIPHER_CTX_buf_noconst ( c ) , ptr , arg ) ;
 gctx -> taglen = arg ;
 return 1 ;
 case EVP_CTRL_AEAD_GET_TAG : if ( arg <= 0 || arg > 16 || ! EVP_CIPHER_CTX_encrypting ( c ) || gctx -> taglen < 0 ) return 0 ;
 memcpy ( ptr , EVP_CIPHER_CTX_buf_noconst ( c ) , arg ) ;
 return 1 ;
 case EVP_CTRL_GCM_SET_IV_FIXED : if ( arg == - 1 ) {
 memcpy ( gctx -> iv , ptr , gctx -> ivlen ) ;
 gctx -> iv_gen = 1 ;
 return 1 ;
 }
 if ( ( arg < 4 ) || ( gctx -> ivlen - arg ) < 8 ) return 0 ;
 if ( arg ) memcpy ( gctx -> iv , ptr , arg ) ;
 if ( EVP_CIPHER_CTX_encrypting ( c ) && RAND_bytes ( gctx -> iv + arg , gctx -> ivlen - arg ) <= 0 ) return 0 ;
 gctx -> iv_gen = 1 ;
 return 1 ;
 case EVP_CTRL_GCM_IV_GEN : if ( gctx -> iv_gen == 0 || gctx -> key_set == 0 ) return 0 ;
 CRYPTO_gcm128_setiv ( & gctx -> gcm , gctx -> iv , gctx -> ivlen ) ;
 if ( arg <= 0 || arg > gctx -> ivlen ) arg = gctx -> ivlen ;
 memcpy ( ptr , gctx -> iv + gctx -> ivlen - arg , arg ) ;
 ctr64_inc ( gctx -> iv + gctx -> ivlen - 8 ) ;
 gctx -> iv_set = 1 ;
 return 1 ;
 case EVP_CTRL_GCM_SET_IV_INV : if ( gctx -> iv_gen == 0 || gctx -> key_set == 0 || EVP_CIPHER_CTX_encrypting ( c ) ) return 0 ;
 memcpy ( gctx -> iv + gctx -> ivlen - arg , ptr , arg ) ;
 CRYPTO_gcm128_setiv ( & gctx -> gcm , gctx -> iv , gctx -> ivlen ) ;
 gctx -> iv_set = 1 ;
 return 1 ;
 case EVP_CTRL_AEAD_TLS1_AAD : if ( arg != EVP_AEAD_TLS1_AAD_LEN ) return 0 ;
 memcpy ( EVP_CIPHER_CTX_buf_noconst ( c ) , ptr , arg ) ;
 gctx -> tls_aad_len = arg ;
 {
 unsigned int len = EVP_CIPHER_CTX_buf_noconst ( c ) [ arg - 2 ] << 8 | EVP_CIPHER_CTX_buf_noconst ( c ) [ arg - 1 ] ;
 len -= EVP_GCM_TLS_EXPLICIT_IV_LEN ;
 if ( ! EVP_CIPHER_CTX_encrypting ( c ) ) len -= EVP_GCM_TLS_TAG_LEN ;
 EVP_CIPHER_CTX_buf_noconst ( c ) [ arg - 2 ] = len >> 8 ;
 EVP_CIPHER_CTX_buf_noconst ( c ) [ arg - 1 ] = len & 0xff ;
 }
 return EVP_GCM_TLS_TAG_LEN ;
 case EVP_CTRL_COPY : {
 EVP_CIPHER_CTX * out = ptr ;
 EVP_AES_GCM_CTX * gctx_out = EVP_C_DATA ( EVP_AES_GCM_CTX , out ) ;
 if ( gctx -> gcm . key ) {
 if ( gctx -> gcm . key != & gctx -> ks ) return 0 ;
 gctx_out -> gcm . key = & gctx_out -> ks ;
 }
 if ( gctx -> iv == EVP_CIPHER_CTX_iv_noconst ( c ) ) gctx_out -> iv = EVP_CIPHER_CTX_iv_noconst ( out ) ;
 else {
 gctx_out -> iv = OPENSSL_malloc ( gctx -> ivlen ) ;
 if ( gctx_out -> iv == NULL ) return 0 ;
 memcpy ( gctx_out -> iv , gctx -> iv , gctx -> ivlen ) ;
 }
 return 1 ;
 }
 default : return - 1 ;
 }
 }
 static int aes_gcm_init_key ( EVP_CIPHER_CTX * ctx , const unsigned char * key , const unsigned char * iv , int enc ) {
 EVP_AES_GCM_CTX * gctx = EVP_C_DATA ( EVP_AES_GCM_CTX , ctx ) ;
 if ( ! iv && ! key ) return 1 ;
 if ( key ) {
 do {
 # ifdef HWAES_CAPABLE if ( HWAES_CAPABLE ) {
 HWAES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & gctx -> ks . ks ) ;
 CRYPTO_gcm128_init ( & gctx -> gcm , & gctx -> ks , ( block128_f ) HWAES_encrypt ) ;
 # ifdef HWAES_ctr32_encrypt_blocks gctx -> ctr = ( ctr128_f ) HWAES_ctr32_encrypt_blocks ;
 # else gctx -> ctr = NULL ;
 # endif break ;
 }
 else # endif # ifdef BSAES_CAPABLE if ( BSAES_CAPABLE ) {
 AES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & gctx -> ks . ks ) ;
 CRYPTO_gcm128_init ( & gctx -> gcm , & gctx -> ks , ( block128_f ) AES_encrypt ) ;
 gctx -> ctr = ( ctr128_f ) bsaes_ctr32_encrypt_blocks ;
 break ;
 }
 else # endif # ifdef VPAES_CAPABLE if ( VPAES_CAPABLE ) {
 vpaes_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & gctx -> ks . ks ) ;
 CRYPTO_gcm128_init ( & gctx -> gcm , & gctx -> ks , ( block128_f ) vpaes_encrypt ) ;
 gctx -> ctr = NULL ;
 break ;
 }
 else # endif ( void ) 0 ;
 AES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 8 , & gctx -> ks . ks ) ;
 CRYPTO_gcm128_init ( & gctx -> gcm , & gctx -> ks , ( block128_f ) AES_encrypt ) ;
 # ifdef AES_CTR_ASM gctx -> ctr = ( ctr128_f ) AES_ctr32_encrypt ;
 # else gctx -> ctr = NULL ;
 # endif }
 while ( 0 ) ;
 if ( iv == NULL && gctx -> iv_set ) iv = gctx -> iv ;
 if ( iv ) {
 CRYPTO_gcm128_setiv ( & gctx -> gcm , iv , gctx -> ivlen ) ;
 gctx -> iv_set = 1 ;
 }
 gctx -> key_set = 1 ;
 }
 else {
 if ( gctx -> key_set ) CRYPTO_gcm128_setiv ( & gctx -> gcm , iv , gctx -> ivlen ) ;
 else memcpy ( gctx -> iv , iv , gctx -> ivlen ) ;
 gctx -> iv_set = 1 ;
 gctx -> iv_gen = 0 ;
 }
 return 1 ;
 }
 static int aes_gcm_tls_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_GCM_CTX * gctx = EVP_C_DATA ( EVP_AES_GCM_CTX , ctx ) ;
 int rv = - 1 ;
 if ( out != in || len < ( EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN ) ) return - 1 ;
 if ( EVP_CIPHER_CTX_ctrl ( ctx , EVP_CIPHER_CTX_encrypting ( ctx ) ? EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV , EVP_GCM_TLS_EXPLICIT_IV_LEN , out ) <= 0 ) goto err ;
 if ( CRYPTO_gcm128_aad ( & gctx -> gcm , EVP_CIPHER_CTX_buf_noconst ( ctx ) , gctx -> tls_aad_len ) ) goto err ;
 in += EVP_GCM_TLS_EXPLICIT_IV_LEN ;
 out += EVP_GCM_TLS_EXPLICIT_IV_LEN ;
 len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN ;
 if ( EVP_CIPHER_CTX_encrypting ( ctx ) ) {
 if ( gctx -> ctr ) {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM ) if ( len >= 32 && AES_GCM_ASM ( gctx ) ) {
 if ( CRYPTO_gcm128_encrypt ( & gctx -> gcm , NULL , NULL , 0 ) ) return - 1 ;
 bulk = AES_gcm_encrypt ( in , out , len , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 }
 # endif if ( CRYPTO_gcm128_encrypt_ctr32 ( & gctx -> gcm , in + bulk , out + bulk , len - bulk , gctx -> ctr ) ) goto err ;
 }
 else {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM2 ) if ( len >= 32 && AES_GCM_ASM2 ( gctx ) ) {
 if ( CRYPTO_gcm128_encrypt ( & gctx -> gcm , NULL , NULL , 0 ) ) return - 1 ;
 bulk = AES_gcm_encrypt ( in , out , len , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 }
 # endif if ( CRYPTO_gcm128_encrypt ( & gctx -> gcm , in + bulk , out + bulk , len - bulk ) ) goto err ;
 }
 out += len ;
 CRYPTO_gcm128_tag ( & gctx -> gcm , out , EVP_GCM_TLS_TAG_LEN ) ;
 rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN ;
 }
 else {
 if ( gctx -> ctr ) {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM ) if ( len >= 16 && AES_GCM_ASM ( gctx ) ) {
 if ( CRYPTO_gcm128_decrypt ( & gctx -> gcm , NULL , NULL , 0 ) ) return - 1 ;
 bulk = AES_gcm_decrypt ( in , out , len , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 }
 # endif if ( CRYPTO_gcm128_decrypt_ctr32 ( & gctx -> gcm , in + bulk , out + bulk , len - bulk , gctx -> ctr ) ) goto err ;
 }
 else {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM2 ) if ( len >= 16 && AES_GCM_ASM2 ( gctx ) ) {
 if ( CRYPTO_gcm128_decrypt ( & gctx -> gcm , NULL , NULL , 0 ) ) return - 1 ;
 bulk = AES_gcm_decrypt ( in , out , len , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 }
 # endif if ( CRYPTO_gcm128_decrypt ( & gctx -> gcm , in + bulk , out + bulk , len - bulk ) ) goto err ;
 }
 CRYPTO_gcm128_tag ( & gctx -> gcm , EVP_CIPHER_CTX_buf_noconst ( ctx ) , EVP_GCM_TLS_TAG_LEN ) ;
 if ( CRYPTO_memcmp ( EVP_CIPHER_CTX_buf_noconst ( ctx ) , in + len , EVP_GCM_TLS_TAG_LEN ) ) {
 OPENSSL_cleanse ( out , len ) ;
 goto err ;
 }
 rv = len ;
 }
 err : gctx -> iv_set = 0 ;
 gctx -> tls_aad_len = - 1 ;
 return rv ;
 }
 static int aes_gcm_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_GCM_CTX * gctx = EVP_C_DATA ( EVP_AES_GCM_CTX , ctx ) ;
 if ( ! gctx -> key_set ) return - 1 ;
 if ( gctx -> tls_aad_len >= 0 ) return aes_gcm_tls_cipher ( ctx , out , in , len ) ;
 if ( ! gctx -> iv_set ) return - 1 ;
 if ( in ) {
 if ( out == NULL ) {
 if ( CRYPTO_gcm128_aad ( & gctx -> gcm , in , len ) ) return - 1 ;
 }
 else if ( EVP_CIPHER_CTX_encrypting ( ctx ) ) {
 if ( gctx -> ctr ) {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM ) if ( len >= 32 && AES_GCM_ASM ( gctx ) ) {
 size_t res = ( 16 - gctx -> gcm . mres ) % 16 ;
 if ( CRYPTO_gcm128_encrypt ( & gctx -> gcm , in , out , res ) ) return - 1 ;
 bulk = AES_gcm_encrypt ( in + res , out + res , len - res , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 bulk += res ;
 }
 # endif if ( CRYPTO_gcm128_encrypt_ctr32 ( & gctx -> gcm , in + bulk , out + bulk , len - bulk , gctx -> ctr ) ) return - 1 ;
 }
 else {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM2 ) if ( len >= 32 && AES_GCM_ASM2 ( gctx ) ) {
 size_t res = ( 16 - gctx -> gcm . mres ) % 16 ;
 if ( CRYPTO_gcm128_encrypt ( & gctx -> gcm , in , out , res ) ) return - 1 ;
 bulk = AES_gcm_encrypt ( in + res , out + res , len - res , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 bulk += res ;
 }
 # endif if ( CRYPTO_gcm128_encrypt ( & gctx -> gcm , in + bulk , out + bulk , len - bulk ) ) return - 1 ;
 }
 }
 else {
 if ( gctx -> ctr ) {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM ) if ( len >= 16 && AES_GCM_ASM ( gctx ) ) {
 size_t res = ( 16 - gctx -> gcm . mres ) % 16 ;
 if ( CRYPTO_gcm128_decrypt ( & gctx -> gcm , in , out , res ) ) return - 1 ;
 bulk = AES_gcm_decrypt ( in + res , out + res , len - res , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 bulk += res ;
 }
 # endif if ( CRYPTO_gcm128_decrypt_ctr32 ( & gctx -> gcm , in + bulk , out + bulk , len - bulk , gctx -> ctr ) ) return - 1 ;
 }
 else {
 size_t bulk = 0 ;
 # if defined ( AES_GCM_ASM2 ) if ( len >= 16 && AES_GCM_ASM2 ( gctx ) ) {
 size_t res = ( 16 - gctx -> gcm . mres ) % 16 ;
 if ( CRYPTO_gcm128_decrypt ( & gctx -> gcm , in , out , res ) ) return - 1 ;
 bulk = AES_gcm_decrypt ( in + res , out + res , len - res , gctx -> gcm . key , gctx -> gcm . Yi . c , gctx -> gcm . Xi . u ) ;
 gctx -> gcm . len . u [ 1 ] += bulk ;
 bulk += res ;
 }
 # endif if ( CRYPTO_gcm128_decrypt ( & gctx -> gcm , in + bulk , out + bulk , len - bulk ) ) return - 1 ;
 }
 }
 return len ;
 }
 else {
 if ( ! EVP_CIPHER_CTX_encrypting ( ctx ) ) {
 if ( gctx -> taglen < 0 ) return - 1 ;
 if ( CRYPTO_gcm128_finish ( & gctx -> gcm , EVP_CIPHER_CTX_buf_noconst ( ctx ) , gctx -> taglen ) != 0 ) return - 1 ;
 gctx -> iv_set = 0 ;
 return 0 ;
 }
 CRYPTO_gcm128_tag ( & gctx -> gcm , EVP_CIPHER_CTX_buf_noconst ( ctx ) , 16 ) ;
 gctx -> taglen = 16 ;
 gctx -> iv_set = 0 ;
 return 0 ;
 }
 }
 # define CUSTOM_FLAGS ( EVP_CIPH_FLAG_DEFAULT_ASN1 \ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ | EVP_CIPH_CUSTOM_COPY ) BLOCK_CIPHER_custom ( NID_aes , 128 , 1 , 12 , gcm , GCM , EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS ) BLOCK_CIPHER_custom ( NID_aes , 192 , 1 , 12 , gcm , GCM , EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS ) BLOCK_CIPHER_custom ( NID_aes , 256 , 1 , 12 , gcm , GCM , EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS ) static int aes_xts_ctrl ( EVP_CIPHER_CTX * c , int type , int arg , void * ptr ) {
 EVP_AES_XTS_CTX * xctx = EVP_C_DATA ( EVP_AES_XTS_CTX , c ) ;
 if ( type == EVP_CTRL_COPY ) {
 EVP_CIPHER_CTX * out = ptr ;
 EVP_AES_XTS_CTX * xctx_out = EVP_C_DATA ( EVP_AES_XTS_CTX , out ) ;
 if ( xctx -> xts . key1 ) {
 if ( xctx -> xts . key1 != & xctx -> ks1 ) return 0 ;
 xctx_out -> xts . key1 = & xctx_out -> ks1 ;
 }
 if ( xctx -> xts . key2 ) {
 if ( xctx -> xts . key2 != & xctx -> ks2 ) return 0 ;
 xctx_out -> xts . key2 = & xctx_out -> ks2 ;
 }
 return 1 ;
 }
 else if ( type != EVP_CTRL_INIT ) return - 1 ;
 xctx -> xts . key1 = NULL ;
 xctx -> xts . key2 = NULL ;
 return 1 ;
 }
 static int aes_xts_init_key ( EVP_CIPHER_CTX * ctx , const unsigned char * key , const unsigned char * iv , int enc ) {
 EVP_AES_XTS_CTX * xctx = EVP_C_DATA ( EVP_AES_XTS_CTX , ctx ) ;
 if ( ! iv && ! key ) return 1 ;
 if ( key ) do {
 # ifdef AES_XTS_ASM xctx -> stream = enc ? AES_xts_encrypt : AES_xts_decrypt ;
 # else xctx -> stream = NULL ;
 # endif # ifdef HWAES_CAPABLE if ( HWAES_CAPABLE ) {
 if ( enc ) {
 HWAES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks1 . ks ) ;
 xctx -> xts . block1 = ( block128_f ) HWAES_encrypt ;
 # ifdef HWAES_xts_encrypt xctx -> stream = HWAES_xts_encrypt ;
 # endif }
 else {
 HWAES_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks1 . ks ) ;
 xctx -> xts . block1 = ( block128_f ) HWAES_decrypt ;
 # ifdef HWAES_xts_decrypt xctx -> stream = HWAES_xts_decrypt ;
 # endif }
 HWAES_set_encrypt_key ( key + EVP_CIPHER_CTX_key_length ( ctx ) / 2 , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks2 . ks ) ;
 xctx -> xts . block2 = ( block128_f ) HWAES_encrypt ;
 xctx -> xts . key1 = & xctx -> ks1 ;
 break ;
 }
 else # endif # ifdef BSAES_CAPABLE if ( BSAES_CAPABLE ) xctx -> stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt ;
 else # endif # ifdef VPAES_CAPABLE if ( VPAES_CAPABLE ) {
 if ( enc ) {
 vpaes_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks1 . ks ) ;
 xctx -> xts . block1 = ( block128_f ) vpaes_encrypt ;
 }
 else {
 vpaes_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks1 . ks ) ;
 xctx -> xts . block1 = ( block128_f ) vpaes_decrypt ;
 }
 vpaes_set_encrypt_key ( key + EVP_CIPHER_CTX_key_length ( ctx ) / 2 , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks2 . ks ) ;
 xctx -> xts . block2 = ( block128_f ) vpaes_encrypt ;
 xctx -> xts . key1 = & xctx -> ks1 ;
 break ;
 }
 else # endif ( void ) 0 ;
 if ( enc ) {
 AES_set_encrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks1 . ks ) ;
 xctx -> xts . block1 = ( block128_f ) AES_encrypt ;
 }
 else {
 AES_set_decrypt_key ( key , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks1 . ks ) ;
 xctx -> xts . block1 = ( block128_f ) AES_decrypt ;
 }
 AES_set_encrypt_key ( key + EVP_CIPHER_CTX_key_length ( ctx ) / 2 , EVP_CIPHER_CTX_key_length ( ctx ) * 4 , & xctx -> ks2 . ks ) ;
 xctx -> xts . block2 = ( block128_f ) AES_encrypt ;
 xctx -> xts . key1 = & xctx -> ks1 ;
 }
 while ( 0 ) ;
 if ( iv ) {
 xctx -> xts . key2 = & xctx -> ks2 ;
 memcpy ( EVP_CIPHER_CTX_iv_noconst ( ctx ) , iv , 16 ) ;
 }
 return 1 ;
 }
 static int aes_xts_cipher ( EVP_CIPHER_CTX * ctx , unsigned char * out , const unsigned char * in , size_t len ) {
 EVP_AES_XTS_CTX * xctx = EVP_C_DATA ( EVP_AES_XTS_CTX , ctx ) ;
 if ( ! xctx -> xts . key1 || ! xctx -> xts . key2 ) return 0 ;
 if ( ! out || ! in || len < AES_BLOCK_SIZE ) return 0 ;
 if ( xctx -> stream ) ( * xctx -> stream ) ( in , out , len , xctx -> xts . key1 , xctx -> xts . key2 , EVP_CIPHER_CTX_iv_noconst ( ctx ) ) ;
 else if ( CRYPTO_xts128_encrypt ( & xctx -> xts , EVP_CIPHER_CTX_iv_noconst ( ctx ) , in , out , len , EVP_CIPHER_CTX_encrypting ( ctx ) ) ) return 0 ;
 return 1 ;
 }
 # define aes_xts_cleanup NULL # define XTS_FLAGS ( EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ | EVP_CIPH_CUSTOM_COPY ) BLOCK_CIPHER_custom ( NID_aes , 128 , 1 , 16 , xts , XTS , XTS_FLAGS ) BLOCK_CIPHER_custom ( NID_aes , 256 , 1 , 16 , xts , XTS , XTS_FLAGS )


struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
					   const union sctp_addr *addr,
					   const gfp_t gfp,
					   const int peer_state)
{
	struct sctp_transport *peer;
	struct sctp_sock *sp;
	unsigned short port;

	sp = sctp_sk(asoc->base.sk);

	/* AF_INET and AF_INET6 share common port field. */
	port = ntohs(addr->v4.sin_port);

	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
				 " port: %d state:%d\n",
				 asoc,
				 addr,
				 port,
				 peer_state);

	/* Set the port if it has not been set yet.  */
	if (0 == asoc->peer.port)
		asoc->peer.port = port;

	/* Check to see if this is a duplicate. */
	peer = sctp_assoc_lookup_paddr(asoc, addr);
	if (peer) {
		/* An UNKNOWN state is only set on transports added by
		 * user in sctp_connectx() call.  Such transports should be
		 * considered CONFIRMED per RFC 4960, Section 5.4.
		 */
		if (peer->state == SCTP_UNKNOWN) {
			peer->state = SCTP_ACTIVE;
		}
		return peer;
	}

	peer = sctp_transport_new(addr, gfp);
	if (!peer)
		return NULL;

	sctp_transport_set_owner(peer, asoc);

	/* Initialize the peer's heartbeat interval based on the
	 * association configured value.
	 */
	peer->hbinterval = asoc->hbinterval;

	/* Set the path max_retrans.  */
	peer->pathmaxrxt = asoc->pathmaxrxt;

	/* Initialize the peer's SACK delay timeout based on the
	 * association configured value.
	 */
	peer->sackdelay = asoc->sackdelay;
	peer->sackfreq = asoc->sackfreq;

	/* Enable/disable heartbeat, SACK delay, and path MTU discovery
	 * based on association setting.
	 */
	peer->param_flags = asoc->param_flags;

	/* Initialize the pmtu of the transport. */
	if (peer->param_flags & SPP_PMTUD_ENABLE)
		sctp_transport_pmtu(peer);
	else if (asoc->pathmtu)
		peer->pathmtu = asoc->pathmtu;
	else
		peer->pathmtu = SCTP_DEFAULT_MAXSEGMENT;

	/* If this is the first transport addr on this association,
	 * initialize the association PMTU to the peer's PMTU.
	 * If not and the current association PMTU is higher than the new
	 * peer's PMTU, reset the association PMTU to the new peer's PMTU.
	 */
	if (asoc->pathmtu)
		asoc->pathmtu = min_t(int, peer->pathmtu, asoc->pathmtu);
	else
		asoc->pathmtu = peer->pathmtu;

	SCTP_DEBUG_PRINTK("sctp_assoc_add_peer:association %p PMTU set to "
			  "%d\n", asoc, asoc->pathmtu);
	peer->pmtu_pending = 0;

	asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);

	/* The asoc->peer.port might not be meaningful yet, but
	 * initialize the packet structure anyway.
	 */
	sctp_packet_init(&peer->packet, peer, asoc->base.bind_addr.port,
			 asoc->peer.port);

	/* 7.2.1 Slow-Start
	 *
	 * o The initial cwnd before DATA transmission or after a sufficiently
	 *   long idle period MUST be set to
	 *      min(4*MTU, max(2*MTU, 4380 bytes))
	 *
	 * o The initial value of ssthresh MAY be arbitrarily high
	 *   (for example, implementations MAY use the size of the
	 *   receiver advertised window).
	 */
	peer->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));

	/* At this point, we may not have the receiver's advertised window,
	 * so initialize ssthresh to the default value and it will be set
	 * later when we process the INIT.
	 */
	peer->ssthresh = SCTP_DEFAULT_MAXWINDOW;

	peer->partial_bytes_acked = 0;
	peer->flight_size = 0;

	/* Set the transport's RTO.initial value */
	peer->rto = asoc->rto_initial;

	/* Set the peer's active state. */
	peer->state = peer_state;

	/* Attach the remote transport to our asoc.  */
	list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
	asoc->peer.transport_count++;

	/* If we do not yet have a primary path, set one.  */
	if (!asoc->peer.primary_path) {
		sctp_assoc_set_primary(asoc, peer);
		asoc->peer.retran_path = peer;
	}

	if (asoc->peer.active_path == asoc->peer.retran_path) {
		asoc->peer.retran_path = peer;
	}

	return peer;
}


static my_bool test_if_special_chars ( const char * str ) {
 # if MYSQL_VERSION_ID >= 32300 for ( ;
 * str ;
 str ++ ) if ( ! my_isvar ( charset_info , * str ) && * str != '$' ) return 1 ;
 # endif return 0 ;
 }


void sctp_assoc_del_nonprimary_peers(struct sctp_association *asoc,
				     struct sctp_transport *primary)
{
	struct sctp_transport	*temp;
	struct sctp_transport	*t;

	list_for_each_entry_safe(t, temp, &asoc->peer.transport_addr_list,
				 transports) {
		/* if the current transport is not the primary one, delete it */
		if (t != primary)
			sctp_assoc_rm_peer(asoc, t);
	}

	return;
}


static void sctp_association_destroy(struct sctp_association *asoc)
{
	SCTP_ASSERT(asoc->base.dead, "Assoc is not dead", return);

	sctp_endpoint_put(asoc->ep);
	sock_put(asoc->base.sk);

	if (asoc->assoc_id != 0) {
		spin_lock_bh(&sctp_assocs_id_lock);
		idr_remove(&sctp_assocs_id, asoc->assoc_id);
		spin_unlock_bh(&sctp_assocs_id_lock);
	}

	WARN_ON(atomic_read(&asoc->rmem_alloc));

	if (asoc->base.malloced) {
		kfree(asoc);
		SCTP_DBG_OBJCNT_DEC(assoc);
	}
}


void sctp_assoc_del_peer(struct sctp_association *asoc,
			 const union sctp_addr *addr)
{
	struct list_head	*pos;
	struct list_head	*temp;
	struct sctp_transport	*transport;

	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
		transport = list_entry(pos, struct sctp_transport, transports);
		if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) {
			/* Do book keeping for removing the peer and free it. */
			sctp_assoc_rm_peer(asoc, transport);
			break;
		}
	}
}


void sctp_assoc_control_transport(struct sctp_association *asoc,
				  struct sctp_transport *transport,
				  sctp_transport_cmd_t command,
				  sctp_sn_error_t error)
{
	struct sctp_transport *t = NULL;
	struct sctp_transport *first;
	struct sctp_transport *second;
	struct sctp_ulpevent *event;
	struct sockaddr_storage addr;
	int spc_state = 0;

	/* Record the transition on the transport.  */
	switch (command) {
	case SCTP_TRANSPORT_UP:
		/* If we are moving from UNCONFIRMED state due
		 * to heartbeat success, report the SCTP_ADDR_CONFIRMED
		 * state to the user, otherwise report SCTP_ADDR_AVAILABLE.
		 */
		if (SCTP_UNCONFIRMED == transport->state &&
		    SCTP_HEARTBEAT_SUCCESS == error)
			spc_state = SCTP_ADDR_CONFIRMED;
		else
			spc_state = SCTP_ADDR_AVAILABLE;
		transport->state = SCTP_ACTIVE;
		break;

	case SCTP_TRANSPORT_DOWN:
		/* if the transort was never confirmed, do not transition it
		 * to inactive state.
		 */
		if (transport->state != SCTP_UNCONFIRMED)
			transport->state = SCTP_INACTIVE;

		spc_state = SCTP_ADDR_UNREACHABLE;
		break;

	default:
		return;
	}

	/* Generate and send a SCTP_PEER_ADDR_CHANGE notification to the
	 * user.
	 */
	memset(&addr, 0, sizeof(struct sockaddr_storage));
	memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len);
	event = sctp_ulpevent_make_peer_addr_change(asoc, &addr,
				0, spc_state, error, GFP_ATOMIC);
	if (event)
		sctp_ulpq_tail_event(&asoc->ulpq, event);

	/* Select new active and retran paths. */

	/* Look for the two most recently used active transports.
	 *
	 * This code produces the wrong ordering whenever jiffies
	 * rolls over, but we still get usable transports, so we don't
	 * worry about it.
	 */
	first = NULL; second = NULL;

	list_for_each_entry(t, &asoc->peer.transport_addr_list,
			transports) {

		if ((t->state == SCTP_INACTIVE) ||
		    (t->state == SCTP_UNCONFIRMED))
			continue;
		if (!first || t->last_time_heard > first->last_time_heard) {
			second = first;
			first = t;
		}
		if (!second || t->last_time_heard > second->last_time_heard)
			second = t;
	}

	/* RFC 2960 6.4 Multi-Homed SCTP Endpoints
	 *
	 * By default, an endpoint should always transmit to the
	 * primary path, unless the SCTP user explicitly specifies the
	 * destination transport address (and possibly source
	 * transport address) to use.
	 *
	 * [If the primary is active but not most recent, bump the most
	 * recently used transport.]
	 */
	if (((asoc->peer.primary_path->state == SCTP_ACTIVE) ||
	     (asoc->peer.primary_path->state == SCTP_UNKNOWN)) &&
	    first != asoc->peer.primary_path) {
		second = first;
		first = asoc->peer.primary_path;
	}

	/* If we failed to find a usable transport, just camp on the
	 * primary, even if it is inactive.
	 */
	if (!first) {
		first = asoc->peer.primary_path;
		second = asoc->peer.primary_path;
	}

	/* Set the active and retran transports.  */
	asoc->peer.active_path = first;
	asoc->peer.retran_path = second;
}


static struct sctp_association *sctp_association_init(struct sctp_association *asoc,
					  const struct sctp_endpoint *ep,
					  const struct sock *sk,
					  sctp_scope_t scope,
					  gfp_t gfp)
{
	struct sctp_sock *sp;
	int i;
	sctp_paramhdr_t *p;
	int err;

	/* Retrieve the SCTP per socket area.  */
	sp = sctp_sk((struct sock *)sk);

	/* Init all variables to a known value.  */
	memset(asoc, 0, sizeof(struct sctp_association));

	/* Discarding const is appropriate here.  */
	asoc->ep = (struct sctp_endpoint *)ep;
	sctp_endpoint_hold(asoc->ep);

	/* Hold the sock.  */
	asoc->base.sk = (struct sock *)sk;
	sock_hold(asoc->base.sk);

	/* Initialize the common base substructure.  */
	asoc->base.type = SCTP_EP_TYPE_ASSOCIATION;

	/* Initialize the object handling fields.  */
	atomic_set(&asoc->base.refcnt, 1);
	asoc->base.dead = 0;
	asoc->base.malloced = 0;

	/* Initialize the bind addr area.  */
	sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);

	asoc->state = SCTP_STATE_CLOSED;

	/* Set these values from the socket values, a conversion between
	 * millsecons to seconds/microseconds must also be done.
	 */
	asoc->cookie_life.tv_sec = sp->assocparams.sasoc_cookie_life / 1000;
	asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
					* 1000;
	asoc->frag_point = 0;

	/* Set the association max_retrans and RTO values from the
	 * socket values.
	 */
	asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
	asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial);
	asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
	asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min);

	asoc->overall_error_count = 0;

	/* Initialize the association's heartbeat interval based on the
	 * sock configured value.
	 */
	asoc->hbinterval = msecs_to_jiffies(sp->hbinterval);

	/* Initialize path max retrans value. */
	asoc->pathmaxrxt = sp->pathmaxrxt;

	/* Initialize default path MTU. */
	asoc->pathmtu = sp->pathmtu;

	/* Set association default SACK delay */
	asoc->sackdelay = msecs_to_jiffies(sp->sackdelay);
	asoc->sackfreq = sp->sackfreq;

	/* Set the association default flags controlling
	 * Heartbeat, SACK delay, and Path MTU Discovery.
	 */
	asoc->param_flags = sp->param_flags;

	/* Initialize the maximum mumber of new data packets that can be sent
	 * in a burst.
	 */
	asoc->max_burst = sp->max_burst;

	/* initialize association timers */
	asoc->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = asoc->rto_initial;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = asoc->rto_initial;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = asoc->rto_initial;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;

	/* sctpimpguide Section 2.12.2
	 * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
	 * recommended value of 5 times 'RTO.Max'.
	 */
	asoc->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
		= 5 * asoc->rto_max;

	asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
	asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
		sp->autoclose * HZ;

	/* Initilizes the timers */
	for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
		setup_timer(&asoc->timers[i], sctp_timer_events[i],
				(unsigned long)asoc);

	/* Pull default initialization values from the sock options.
	 * Note: This assumes that the values have already been
	 * validated in the sock.
	 */
	asoc->c.sinit_max_instreams = sp->initmsg.sinit_max_instreams;
	asoc->c.sinit_num_ostreams  = sp->initmsg.sinit_num_ostreams;
	asoc->max_init_attempts	= sp->initmsg.sinit_max_attempts;

	asoc->max_init_timeo =
		 msecs_to_jiffies(sp->initmsg.sinit_max_init_timeo);

	/* Allocate storage for the ssnmap after the inbound and outbound
	 * streams have been negotiated during Init.
	 */
	asoc->ssnmap = NULL;

	/* Set the local window size for receive.
	 * This is also the rcvbuf space per association.
	 * RFC 6 - A SCTP receiver MUST be able to receive a minimum of
	 * 1500 bytes in one SCTP packet.
	 */
	if ((sk->sk_rcvbuf/2) < SCTP_DEFAULT_MINWINDOW)
		asoc->rwnd = SCTP_DEFAULT_MINWINDOW;
	else
		asoc->rwnd = sk->sk_rcvbuf/2;

	asoc->a_rwnd = asoc->rwnd;

	asoc->rwnd_over = 0;

	/* Use my own max window until I learn something better.  */
	asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW;

	/* Set the sndbuf size for transmit.  */
	asoc->sndbuf_used = 0;

	/* Initialize the receive memory counter */
	atomic_set(&asoc->rmem_alloc, 0);

	init_waitqueue_head(&asoc->wait);

	asoc->c.my_vtag = sctp_generate_tag(ep);
	asoc->peer.i.init_tag = 0;     /* INIT needs a vtag of 0. */
	asoc->c.peer_vtag = 0;
	asoc->c.my_ttag   = 0;
	asoc->c.peer_ttag = 0;
	asoc->c.my_port = ep->base.bind_addr.port;

	asoc->c.initial_tsn = sctp_generate_tsn(ep);

	asoc->next_tsn = asoc->c.initial_tsn;

	asoc->ctsn_ack_point = asoc->next_tsn - 1;
	asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
	asoc->highest_sacked = asoc->ctsn_ack_point;
	asoc->last_cwr_tsn = asoc->ctsn_ack_point;
	asoc->unack_data = 0;

	/* ADDIP Section 4.1 Asconf Chunk Procedures
	 *
	 * When an endpoint has an ASCONF signaled change to be sent to the
	 * remote endpoint it should do the following:
	 * ...
	 * A2) a serial number should be assigned to the chunk. The serial
	 * number SHOULD be a monotonically increasing number. The serial
	 * numbers SHOULD be initialized at the start of the
	 * association to the same value as the initial TSN.
	 */
	asoc->addip_serial = asoc->c.initial_tsn;

	INIT_LIST_HEAD(&asoc->addip_chunk_list);
	INIT_LIST_HEAD(&asoc->asconf_ack_list);

	/* Make an empty list of remote transport addresses.  */
	INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
	asoc->peer.transport_count = 0;

	/* RFC 2960 5.1 Normal Establishment of an Association
	 *
	 * After the reception of the first data chunk in an
	 * association the endpoint must immediately respond with a
	 * sack to acknowledge the data chunk.  Subsequent
	 * acknowledgements should be done as described in Section
	 * 6.2.
	 *
	 * [We implement this by telling a new association that it
	 * already received one packet.]
	 */
	asoc->peer.sack_needed = 1;
	asoc->peer.sack_cnt = 0;

	/* Assume that the peer will tell us if he recognizes ASCONF
	 * as part of INIT exchange.
	 * The sctp_addip_noauth option is there for backward compatibilty
	 * and will revert old behavior.
	 */
	asoc->peer.asconf_capable = 0;
	if (sctp_addip_noauth)
		asoc->peer.asconf_capable = 1;

	/* Create an input queue.  */
	sctp_inq_init(&asoc->base.inqueue);
	sctp_inq_set_th_handler(&asoc->base.inqueue, sctp_assoc_bh_rcv);

	/* Create an output queue.  */
	sctp_outq_init(asoc, &asoc->outqueue);

	if (!sctp_ulpq_init(&asoc->ulpq, asoc))
		goto fail_init;

	/* Set up the tsn tracking. */
	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, 0);

	asoc->need_ecne = 0;

	asoc->assoc_id = 0;

	/* Assume that peer would support both address types unless we are
	 * told otherwise.
	 */
	asoc->peer.ipv4_address = 1;
	asoc->peer.ipv6_address = 1;
	INIT_LIST_HEAD(&asoc->asocs);

	asoc->autoclose = sp->autoclose;

	asoc->default_stream = sp->default_stream;
	asoc->default_ppid = sp->default_ppid;
	asoc->default_flags = sp->default_flags;
	asoc->default_context = sp->default_context;
	asoc->default_timetolive = sp->default_timetolive;
	asoc->default_rcv_context = sp->default_rcv_context;

	/* AUTH related initializations */
	INIT_LIST_HEAD(&asoc->endpoint_shared_keys);
	err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp);
	if (err)
		goto fail_init;

	asoc->active_key_id = ep->active_key_id;
	asoc->asoc_shared_key = NULL;

	asoc->default_hmac_id = 0;
	/* Save the hmacs and chunks list into this association */
	if (ep->auth_hmacs_list)
		memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list,
			ntohs(ep->auth_hmacs_list->param_hdr.length));
	if (ep->auth_chunk_list)
		memcpy(asoc->c.auth_chunks, ep->auth_chunk_list,
			ntohs(ep->auth_chunk_list->param_hdr.length));

	/* Get the AUTH random number for this association */
	p = (sctp_paramhdr_t *)asoc->c.auth_random;
	p->type = SCTP_PARAM_RANDOM;
	p->length = htons(sizeof(sctp_paramhdr_t) + SCTP_AUTH_RANDOM_LENGTH);
	get_random_bytes(p+1, SCTP_AUTH_RANDOM_LENGTH);

	return asoc;

fail_init:
	sctp_endpoint_put(asoc->ep);
	sock_put(asoc->base.sk);
	return NULL;
}


static inline int handle_cpu_signal ( uintptr_t pc , unsigned long address , int is_write , sigset_t * old_set , void * puc ) {
 int ret ;
 # if defined ( DEBUG_SIGNAL ) qemu_printf ( "qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n" , pc , address , is_write , * ( unsigned long * ) old_set ) ;
 # endif if ( is_write && h2g_valid ( address ) && page_unprotect ( h2g ( address ) , pc , puc ) ) {
 return 1 ;
 }
 ret = cpu_handle_mmu_fault ( cpu_single_env , address , is_write , MMU_USER_IDX ) ;
 if ( ret < 0 ) {
 return 0 ;
 }
 if ( ret == 0 ) {
 return 1 ;
 }
 cpu_restore_state ( cpu_single_env , pc ) ;
 sigprocmask ( SIG_SETMASK , old_set , NULL ) ;
 exception_action ( cpu_single_env ) ;
 return 1 ;
 }


static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,
				     struct pipe_buffer *buf)
{
	struct page *page = buf->page;
	struct address_space *mapping;

	lock_page(page);

	mapping = page_mapping(page);
	if (mapping) {
		WARN_ON(!PageUptodate(page));

		/*
		 * At least for ext2 with nobh option, we need to wait on
		 * writeback completing on this page, since we'll remove it
		 * from the pagecache.  Otherwise truncate wont wait on the
		 * page, allowing the disk blocks to be reused by someone else
		 * before we actually wrote our data to them. fs corruption
		 * ensues.
		 */
		wait_on_page_writeback(page);

		if (PagePrivate(page) && !try_to_release_page(page, GFP_KERNEL))
			goto out_unlock;

		/*
		 * If we succeeded in removing the mapping, set LRU flag
		 * and return good.
		 */
		if (remove_mapping(mapping, page)) {
			buf->flags |= PIPE_BUF_FLAG_LRU;
			return 0;
		}
	}

	/*
	 * Raced with truncate or failed to remove page from current
	 * address space, unlock and return failure.
	 */
out_unlock:
	unlock_page(page);
	return 1;
}


int evbuffer_write ( struct evbuffer * buffer , int fd ) {
 int n ;
 # ifndef WIN32 n = write ( fd , buffer -> buffer , buffer -> off ) ;
 # else n = send ( fd , buffer -> buffer , buffer -> off , 0 ) ;
 # endif if ( n == - 1 ) return ( - 1 ) ;
 if ( n == 0 ) return ( 0 ) ;
 evbuffer_drain ( buffer , n ) ;
 return ( n ) ;
 }


void TSFetchUserDataSet ( TSFetchSM fetch_sm , void * data ) {
 sdk_assert ( sdk_sanity_check_fetch_sm ( fetch_sm ) == TS_SUCCESS ) ;
 ( ( FetchSM * ) fetch_sm ) -> ext_set_user_data ( data ) ;
 }


int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
{
	struct super_block *sb;
	struct hfs_find_data fd;
	struct hfsplus_fork_raw fork;
	struct list_head *pos;
	int err, off;
	u16 type;

	dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
	sb = dir->i_sb;
	hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);

	if (!str) {
		int len;

		hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
		err = hfs_brec_find(&fd);
		if (err)
			goto out;

		off = fd.entryoffset + offsetof(struct hfsplus_cat_thread, nodeName);
		fd.search_key->cat.parent = cpu_to_be32(dir->i_ino);
		hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.length, off, 2);
		len = be16_to_cpu(fd.search_key->cat.name.length) * 2;
		hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.unicode, off + 2, len);
		fd.search_key->key_len = cpu_to_be16(6 + len);
	} else
		hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);

	err = hfs_brec_find(&fd);
	if (err)
		goto out;

	type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset);
	if (type == HFSPLUS_FILE) {
#if 0
		off = fd.entryoffset + offsetof(hfsplus_cat_file, data_fork);
		hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork));
		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_DATA);
#endif

		off = fd.entryoffset + offsetof(struct hfsplus_cat_file, rsrc_fork);
		hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork));
		hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC);
	}

	list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) {
		struct hfsplus_readdir_data *rd =
			list_entry(pos, struct hfsplus_readdir_data, list);
		if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
			rd->file->f_pos--;
	}

	err = hfs_brec_remove(&fd);
	if (err)
		goto out;

	hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
	err = hfs_brec_find(&fd);
	if (err)
		goto out;

	err = hfs_brec_remove(&fd);
	if (err)
		goto out;

	dir->i_size--;
	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(dir);
out:
	hfs_find_exit(&fd);

	return err;
}


int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
{
	struct page *page;
	struct address_space *mapping;
	__be32 *pptr, *curr, *end;
	u32 mask, len, pnr;
	int i;

	/* is there any actual work to be done? */
	if (!count)
		return 0;

	dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
	/* are all of the bits in range? */
	if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
		return -2;

	mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
	pnr = offset / PAGE_CACHE_BITS;
	page = read_mapping_page(mapping, pnr, NULL);
	pptr = kmap(page);
	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
	end = pptr + PAGE_CACHE_BITS / 32;
	len = count;

	/* do any partial u32 at the start */
	i = offset % 32;
	if (i) {
		int j = 32 - i;
		mask = 0xffffffffU << j;
		if (j > count) {
			mask |= 0xffffffffU >> (i + count);
			*curr++ &= cpu_to_be32(mask);
			goto out;
		}
		*curr++ &= cpu_to_be32(mask);
		count -= j;
	}

	/* do full u32s */
	while (1) {
		while (curr < end) {
			if (count < 32)
				goto done;
			*curr++ = 0;
			count -= 32;
		}
		if (!count)
			break;
		set_page_dirty(page);
		kunmap(page);
		page = read_mapping_page(mapping, ++pnr, NULL);
		pptr = kmap(page);
		curr = pptr;
		end = pptr + PAGE_CACHE_BITS / 32;
	}
done:
	/* do any partial u32 at end */
	if (count) {
		mask = 0xffffffffU >> count;
		*curr &= cpu_to_be32(mask);
	}
out:
	set_page_dirty(page);
	kunmap(page);
	HFSPLUS_SB(sb).free_blocks += len;
	sb->s_dirt = 1;
	mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);

	return 0;
}


static gcry_err_code_t pss_encode ( gcry_mpi_t * r_result , unsigned int nbits , int algo , const unsigned char * value , size_t valuelen , int saltlen , const void * random_override , size_t random_override_len ) {
 gcry_err_code_t rc = 0 ;
 gcry_error_t err ;
 size_t hlen ;
 unsigned char * em = NULL ;
 size_t emlen = ( nbits + 7 ) / 8 ;
 unsigned char * h ;
 unsigned char * buf = NULL ;
 size_t buflen ;
 unsigned char * mhash ;
 unsigned char * salt ;
 unsigned char * dbmask ;
 unsigned char * p ;
 size_t n ;
 hlen = gcry_md_get_algo_dlen ( algo ) ;
 gcry_assert ( hlen ) ;
 buflen = 8 + hlen + saltlen + ( emlen - hlen - 1 ) ;
 buf = gcry_malloc ( buflen ) ;
 if ( ! buf ) {
 rc = gpg_err_code_from_syserror ( ) ;
 goto leave ;
 }
 mhash = buf + 8 ;
 salt = mhash + hlen ;
 dbmask = salt + saltlen ;
 if ( valuelen != hlen ) {
 rc = GPG_ERR_INV_LENGTH ;
 goto leave ;
 }
 memcpy ( mhash , value , hlen ) ;
 if ( emlen < hlen + saltlen + 2 ) {
 rc = GPG_ERR_TOO_SHORT ;
 goto leave ;
 }
 em = gcry_malloc ( emlen ) ;
 if ( ! em ) {
 rc = gpg_err_code_from_syserror ( ) ;
 goto leave ;
 }
 h = em + emlen - 1 - hlen ;
 if ( saltlen ) {
 if ( random_override ) {
 if ( random_override_len != saltlen ) {
 rc = GPG_ERR_INV_ARG ;
 goto leave ;
 }
 memcpy ( salt , random_override , saltlen ) ;
 }
 else gcry_randomize ( salt , saltlen , GCRY_STRONG_RANDOM ) ;
 }
 memset ( buf , 0 , 8 ) ;
 gcry_md_hash_buffer ( algo , h , buf , 8 + hlen + saltlen ) ;
 p = em + emlen - 1 - hlen - saltlen - 1 ;
 memset ( em , 0 , p - em ) ;
 * p ++ = 0x01 ;
 memcpy ( p , salt , saltlen ) ;
 mgf1 ( dbmask , emlen - hlen - 1 , h , hlen , algo ) ;
 for ( n = 0 , p = dbmask ;
 n < emlen - hlen - 1 ;
 n ++ , p ++ ) em [ n ] ^= * p ;
 em [ 0 ] &= 0xFF >> ( 8 * emlen - nbits ) ;
 em [ emlen - 1 ] = 0xbc ;
 err = gcry_mpi_scan ( r_result , GCRYMPI_FMT_USG , em , emlen , NULL ) ;
 if ( err ) rc = gcry_err_code ( err ) ;
 else if ( DBG_CIPHER ) log_mpidump ( "PSS encoded data" , * r_result ) ;
 leave : if ( em ) {
 wipememory ( em , emlen ) ;
 gcry_free ( em ) ;
 }
 if ( buf ) {
 wipememory ( buf , buflen ) ;
 gcry_free ( buf ) ;
 }
 return rc ;
 }


struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
{
	struct scm_fp_list *new_fpl;
	int i;

	if (!fpl)
		return NULL;

	new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
	if (new_fpl) {
		INIT_LIST_HEAD(&new_fpl->list);
		for (i=fpl->count-1; i>=0; i--)
			get_file(fpl->fp[i]);
		memcpy(new_fpl, fpl, sizeof(*fpl));
	}
	return new_fpl;
}


static void _slurm_rpc_composite_msg ( slurm_msg_t * msg ) {
 static time_t config_update = 0 ;
 static bool defer_sched = false ;
 static int sched_timeout = 0 ;
 static int active_rpc_cnt = 0 ;
 struct timeval start_tv ;
 bool run_scheduler = false ;
 composite_msg_t * comp_msg , comp_resp_msg ;
 slurmctld_lock_t job_write_lock = {
 READ_LOCK , WRITE_LOCK , WRITE_LOCK , NO_LOCK , READ_LOCK }
 ;
 memset ( & comp_resp_msg , 0 , sizeof ( composite_msg_t ) ) ;
 comp_resp_msg . msg_list = list_create ( _slurmctld_free_comp_msg_list ) ;
 comp_msg = ( composite_msg_t * ) msg -> data ;
 if ( slurmctld_conf . debug_flags & DEBUG_FLAG_ROUTE ) info ( "Processing RPC: MESSAGE_COMPOSITE msg with %d messages" , comp_msg -> msg_list ? list_count ( comp_msg -> msg_list ) : 0 ) ;
 if ( config_update != slurmctld_conf . last_update ) {
 char * sched_params = slurm_get_sched_params ( ) ;
 int time_limit ;
 char * tmp_ptr ;
 defer_sched = ( sched_params && strstr ( sched_params , "defer" ) ) ;
 time_limit = slurm_get_msg_timeout ( ) / 2 ;
 if ( sched_params && ( tmp_ptr = strstr ( sched_params , "max_sched_time=" ) ) ) {
 sched_timeout = atoi ( tmp_ptr + 15 ) ;
 if ( ( sched_timeout <= 0 ) || ( sched_timeout > time_limit ) ) {
 error ( "Invalid max_sched_time: %d" , sched_timeout ) ;
 sched_timeout = 0 ;
 }
 }
 if ( sched_timeout == 0 ) {
 sched_timeout = MAX ( time_limit , 1 ) ;
 sched_timeout = MIN ( sched_timeout , 2 ) ;
 sched_timeout *= 1000000 ;
 }
 xfree ( sched_params ) ;
 config_update = slurmctld_conf . last_update ;
 }
 _throttle_start ( & active_rpc_cnt ) ;
 lock_slurmctld ( job_write_lock ) ;
 gettimeofday ( & start_tv , NULL ) ;
 _slurm_rpc_comp_msg_list ( comp_msg , & run_scheduler , comp_resp_msg . msg_list , & start_tv , sched_timeout ) ;
 unlock_slurmctld ( job_write_lock ) ;
 _throttle_fini ( & active_rpc_cnt ) ;
 if ( list_count ( comp_resp_msg . msg_list ) ) {
 slurm_msg_t resp_msg ;
 slurm_msg_t_init ( & resp_msg ) ;
 resp_msg . flags = msg -> flags ;
 resp_msg . protocol_version = msg -> protocol_version ;
 memcpy ( & resp_msg . address , & comp_msg -> sender , sizeof ( slurm_addr_t ) ) ;
 resp_msg . msg_type = RESPONSE_MESSAGE_COMPOSITE ;
 resp_msg . data = & comp_resp_msg ;
 slurm_send_only_node_msg ( & resp_msg ) ;
 }
 FREE_NULL_LIST ( comp_resp_msg . msg_list ) ;
 if ( run_scheduler ) {
 if ( ! LOTS_OF_AGENTS && ! defer_sched ) ( void ) schedule ( 0 ) ;
 schedule_node_save ( ) ;
 schedule_job_save ( ) ;
 }
 }


static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
{
	struct sock *sk = sock->sk;
	struct sock *tsk;
	struct sk_buff *skb;
	int err;

	err = -EOPNOTSUPP;
	if (sock->type!=SOCK_STREAM && sock->type!=SOCK_SEQPACKET)
		goto out;

	err = -EINVAL;
	if (sk->sk_state != TCP_LISTEN)
		goto out;

	/* If socket state is TCP_LISTEN it cannot change (for now...),
	 * so that no locks are necessary.
	 */

	skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
	if (!skb) {
		/* This means receive shutdown. */
		if (err == 0)
			err = -EINVAL;
		goto out;
	}

	tsk = skb->sk;
	skb_free_datagram(sk, skb);
	wake_up_interruptible(&unix_sk(sk)->peer_wait);

	/* attach accepted sock to socket */
	unix_state_lock(tsk);
	newsock->state = SS_CONNECTED;
	sock_graft(tsk, newsock);
	unix_state_unlock(tsk);
	return 0;

out:
	return err;
}


static unsigned int unix_poll(struct file * file, struct socket *sock, poll_table *wait)
{
	struct sock *sk = sock->sk;
	unsigned int mask;

	poll_wait(file, sk->sk_sleep, wait);
	mask = 0;

	/* exceptional events? */
	if (sk->sk_err)
		mask |= POLLERR;
	if (sk->sk_shutdown == SHUTDOWN_MASK)
		mask |= POLLHUP;
	if (sk->sk_shutdown & RCV_SHUTDOWN)
		mask |= POLLRDHUP;

	/* readable? */
	if (!skb_queue_empty(&sk->sk_receive_queue) ||
	    (sk->sk_shutdown & RCV_SHUTDOWN))
		mask |= POLLIN | POLLRDNORM;

	/* Connection-based need to check for termination and startup */
	if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && sk->sk_state == TCP_CLOSE)
		mask |= POLLHUP;

	/*
	 * we set writable also when the other side has shut down the
	 * connection. This prevents stuck sockets.
	 */
	if (unix_writable(sk))
		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;

	return mask;
}


void fe_ircnet_deinit ( void ) {
 command_unbind ( "ircnet" , ( SIGNAL_FUNC ) cmd_network ) ;
 command_unbind ( "network" , ( SIGNAL_FUNC ) cmd_network ) ;
 command_unbind ( "network list" , ( SIGNAL_FUNC ) cmd_network_list ) ;
 command_unbind ( "network add" , ( SIGNAL_FUNC ) cmd_network_add ) ;
 command_unbind ( "network modify" , ( SIGNAL_FUNC ) cmd_network_modify ) ;
 command_unbind ( "network remove" , ( SIGNAL_FUNC ) cmd_network_remove ) ;
 }


static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
{
	WARN_ON(!sk_unhashed(sk));
	sk_add_node(sk, list);
}


static struct sock *__unix_find_socket_byname(struct net *net,
					      struct sockaddr_un *sunname,
					      int len, int type, unsigned hash)
{
	struct sock *s;
	struct hlist_node *node;

	sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
		struct unix_sock *u = unix_sk(s);

		if (!net_eq(sock_net(s), net))
			continue;

		if (u->addr->len == len &&
		    !memcmp(u->addr->name, sunname, len))
			goto found;
	}
	s = NULL;
found:
	return s;
}


IN_PROC_BROWSER_TEST_F ( SitePerProcessInteractivePDFTest , ContextMenuPositionForEmbeddedPDFInCrossOriginFrame ) {
 GURL main_url ( embedded_test_server ( ) -> GetURL ( "a.com" , "/iframe.html" ) ) ;
 ui_test_utils : : NavigateToURL ( browser ( ) , main_url ) ;
 EXPECT_EQ ( 0U , test_guest_view_manager ( ) -> num_guests_created ( ) ) ;
 content : : WebContents * active_web_contents = browser ( ) -> tab_strip_model ( ) -> GetActiveWebContents ( ) ;
 EXPECT_TRUE ( ExecuteScript ( active_web_contents , "document.querySelector('iframe').style =" " 'margin-left: 100px;
 margin-top: 100px;
';
" ) ) ;
 GURL frame_url = embedded_test_server ( ) -> GetURL ( "b.com" , "/page_with_embedded_pdf.html" ) ;
 EXPECT_TRUE ( NavigateIframeToURL ( active_web_contents , "test" , frame_url ) ) ;
 content : : WebContents * guest_contents = test_guest_view_manager ( ) -> WaitForSingleGuestCreated ( ) ;
 NavigationToExtensionSchemeObserver navigation_observer ( guest_contents ) ;
 navigation_observer . Wait ( ) ;
 content : : RenderWidgetHostView * child_view = ChildFrameAt ( active_web_contents -> GetMainFrame ( ) , 0 ) -> GetView ( ) ;
 ContextMenuWaiter menu_waiter ( content : : NotificationService : : AllSources ( ) ) ;
 auto send_right_mouse_event = [ ] ( content : : RenderWidgetHost * host , int x , int y , blink : : WebInputEvent : : Type type ) {
 blink : : WebMouseEvent event ;
 event . x = x ;
 event . y = y ;
 event . button = blink : : WebMouseEvent : : Button : : Right ;
 event . setType ( type ) ;
 host -> ForwardMouseEvent ( event ) ;
 }
 ;
 send_right_mouse_event ( child_view -> GetRenderWidgetHost ( ) , 10 , 20 , blink : : WebInputEvent : : MouseDown ) ;
 send_right_mouse_event ( child_view -> GetRenderWidgetHost ( ) , 10 , 20 , blink : : WebInputEvent : : MouseUp ) ;
 menu_waiter . WaitForMenuOpenAndClose ( ) ;
 gfx : : Point point_in_root_window = child_view -> TransformPointToRootCoordSpace ( gfx : : Point ( 10 , 20 ) ) ;
 EXPECT_EQ ( point_in_root_window . x ( ) , menu_waiter . params ( ) . x ) ;
 EXPECT_EQ ( point_in_root_window . y ( ) , menu_waiter . params ( ) . y ) ;
 }


uint get_errcode_from_name ( const char * error_name , const char * error_end ) {
 uint tmp ;
 if ( ( tmp = get_errcode_from_name ( error_name , error_end , global_error_names ) ) ) return tmp ;
 if ( ( tmp = get_errcode_from_name ( error_name , error_end , handler_error_names ) ) ) return tmp ;
 die ( "Unknown SQL error name '%s'" , error_name ) ;
 }


static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct unix_iter_state *iter = seq->private;
	struct sock *sk = v;
	++*pos;

	if (v == SEQ_START_TOKEN)
		sk = first_unix_socket(&iter->i);
	else
		sk = next_unix_socket(&iter->i, sk);
	while (sk && (sock_net(sk) != seq_file_net(seq)))
		sk = next_unix_socket(&iter->i, sk);
	return sk;
}


static void http_terminate_chunked_test ( void ) {
 struct bufferevent * bev = NULL ;
 struct timeval tv ;
 const char * http_request ;
 short port = - 1 ;
 int fd = - 1 ;
 test_ok = 0 ;
 fprintf ( stdout , "Testing Terminated Chunked Connection: " ) ;
 http = http_setup ( & port , NULL ) ;
 evhttp_del_cb ( http , "/test" ) ;
 evhttp_set_cb ( http , "/test" , terminate_chunked_cb , & terminate_state ) ;
 fd = http_connect ( "127.0.0.1" , port ) ;
 bev = bufferevent_new ( fd , terminate_readcb , http_writecb , http_errorcb , NULL ) ;
 terminate_state . fd = fd ;
 terminate_state . bev = bev ;
 http_request = "GET /test HTTP/1.1\r\n" "Host: some\r\n\r\n" ;
 bufferevent_write ( bev , http_request , strlen ( http_request ) ) ;
 evutil_timerclear ( & tv ) ;
 tv . tv_usec = 10000 ;
 event_once ( - 1 , EV_TIMEOUT , terminate_chunked_client , & terminate_state , & tv ) ;
 event_dispatch ( ) ;
 if ( test_ok != 1 ) {
 fprintf ( stdout , "FAILED\n" ) ;
 exit ( 1 ) ;
 }
 fprintf ( stdout , "OK\n" ) ;
 if ( fd >= 0 ) EVUTIL_CLOSESOCKET ( fd ) ;
 if ( http ) evhttp_free ( http ) ;
 }


static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
					      int len, int type, unsigned hash)
{
	struct sock *s;
	struct hlist_node *node;

	sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
		struct unix_sock *u = unix_sk(s);

		if (u->addr->len == len &&
		    !memcmp(u->addr->name, sunname, len))
			goto found;
	}
	s = NULL;
found:
	return s;
}


static int unix_autobind(struct socket *sock)
{
	struct sock *sk = sock->sk;
	struct unix_sock *u = unix_sk(sk);
	static u32 ordernum = 1;
	struct unix_address * addr;
	int err;

	mutex_lock(&u->readlock);

	err = 0;
	if (u->addr)
		goto out;

	err = -ENOMEM;
	addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
	if (!addr)
		goto out;

	addr->name->sun_family = AF_UNIX;
	atomic_set(&addr->refcnt, 1);

retry:
	addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
	addr->hash = unix_hash_fold(csum_partial((void*)addr->name, addr->len, 0));

	spin_lock(&unix_table_lock);
	ordernum = (ordernum+1)&0xFFFFF;

	if (__unix_find_socket_byname(addr->name, addr->len, sock->type,
				      addr->hash)) {
		spin_unlock(&unix_table_lock);
		/* Sanity yield. It is unusual case, but yet... */
		if (!(ordernum&0xFF))
			yield();
		goto retry;
	}
	addr->hash ^= sk->sk_type;

	__unix_remove_socket(sk);
	u->addr = addr;
	__unix_insert_socket(&unix_socket_table[addr->hash], sk);
	spin_unlock(&unix_table_lock);
	err = 0;

out:	mutex_unlock(&u->readlock);
	return err;
}


static int unix_shutdown(struct socket *sock, int mode)
{
	struct sock *sk = sock->sk;
	struct sock *other;

	mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);

	if (mode) {
		unix_state_lock(sk);
		sk->sk_shutdown |= mode;
		other=unix_peer(sk);
		if (other)
			sock_hold(other);
		unix_state_unlock(sk);
		sk->sk_state_change(sk);

		if (other &&
			(sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {

			int peer_mode = 0;

			if (mode&RCV_SHUTDOWN)
				peer_mode |= SEND_SHUTDOWN;
			if (mode&SEND_SHUTDOWN)
				peer_mode |= RCV_SHUTDOWN;
			unix_state_lock(other);
			other->sk_shutdown |= peer_mode;
			unix_state_unlock(other);
			other->sk_state_change(other);
			read_lock(&other->sk_callback_lock);
			if (peer_mode == SHUTDOWN_MASK)
				sk_wake_async(other,1,POLL_HUP);
			else if (peer_mode & RCV_SHUTDOWN)
				sk_wake_async(other,1,POLL_IN);
			read_unlock(&other->sk_callback_lock);
		}
		if (other)
			sock_put(other);
	}
	return 0;
}


static void __exit af_unix_exit(void)
{
	sock_unregister(PF_UNIX);
	unix_sysctl_unregister();
	proc_net_remove("unix");
	proto_unregister(&unix_proto);
}


static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
{
	BUG_TRAP(sk_unhashed(sk));
	sk_add_node(sk, list);
}


static void __exit uvc_cleanup(void)
{
	usb_deregister(&uvc_driver.driver);
}


static int uvc_resume(struct usb_interface *intf)
{
	struct uvc_device *dev = usb_get_intfdata(intf);
	int ret;

	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
		intf->cur_altsetting->desc.bInterfaceNumber);

	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
		if ((ret = uvc_ctrl_resume_device(dev)) < 0)
			return ret;

		return uvc_status_resume(dev);
	}

	if (dev->video.streaming->intf != intf) {
		uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB "
				"interface mismatch.\n");
		return -EINVAL;
	}

	return uvc_video_resume(&dev->video);
}


static __u32 uvc_colorspace(const __u8 primaries)
{
	static const __u8 colorprimaries[] = {
		0,
		V4L2_COLORSPACE_SRGB,
		V4L2_COLORSPACE_470_SYSTEM_M,
		V4L2_COLORSPACE_470_SYSTEM_BG,
		V4L2_COLORSPACE_SMPTE170M,
		V4L2_COLORSPACE_SMPTE240M,
	};

	if (primaries < ARRAY_SIZE(colorprimaries))
		return colorprimaries[primaries];

	return 0;
}


int cap_bprm_set_security (struct linux_binprm *bprm)
{
	int ret;

	ret = get_file_caps(bprm);

	if (!issecure(SECURE_NOROOT)) {
		/*
		 * To support inheritance of root-permissions and suid-root
		 * executables under compatibility mode, we override the
		 * capability sets for the file.
		 *
		 * If only the real uid is 0, we do not set the effective
		 * bit.
		 */
		if (bprm->e_uid == 0 || current->uid == 0) {
			/* pP' = (cap_bset & ~0) | (pI & ~0) */
			bprm->cap_post_exec_permitted = cap_combine(
				current->cap_bset, current->cap_inheritable
				);
			bprm->cap_effective = (bprm->e_uid == 0);
			ret = 0;
		}
	}

	return ret;
}


static int cap_safe_nice(struct task_struct *p)
{
	if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
	    !capable(CAP_SYS_NICE))
		return -EPERM;
	return 0;
}


int cap_capable (struct task_struct *tsk, int cap)
{
	/* Derived from include/linux/sched.h:capable. */
	if (cap_raised(tsk->cap_effective, cap))
		return 0;
	return -EPERM;
}


int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
		 union iwreq_data *wrqu, char *extra)
{
	struct lbs_private *priv = dev->priv;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_WEXT);

	if (!priv->radio_on) {
		ret = -EINVAL;
		goto out;
	}

	if (!netif_running(dev)) {
		ret = -ENETDOWN;
		goto out;
	}

	/* mac80211 does this:
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->type != IEEE80211_IF_TYPE_xxx) {
		ret = -EOPNOTSUPP;
		goto out;
	}
	*/

	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
		struct iw_scan_req *req = (struct iw_scan_req *)extra;
		priv->scan_ssid_len = req->essid_len;
		memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
		lbs_deb_wext("set_scan, essid '%s'\n",
			escape_essid(priv->scan_ssid, priv->scan_ssid_len));
	} else {
		priv->scan_ssid_len = 0;
	}

	if (!delayed_work_pending(&priv->scan_work))
		queue_delayed_work(priv->work_thread, &priv->scan_work,
				   msecs_to_jiffies(50));
	/* set marker that currently a scan is taking place */
	priv->scan_channel = -1;

	if (priv->surpriseremoved)
		ret = -EIO;

out:
	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
	return ret;
}


static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
{
	int i;

	for (i = 0; i < len; i++)
		rates[i] &= 0x7f;
}


int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
		 uint8_t ssid2_len)
{
	if (ssid1_len != ssid2_len)
		return -1;

	return memcmp(ssid1, ssid2, ssid1_len);
}


static int lbs_scan_add_rates_tlv(uint8_t *tlv)
{
	int i;
	struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;

	rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
	tlv += sizeof(rate_tlv->header);
	for (i = 0; i < MAX_RATES; i++) {
		*tlv = lbs_bg_rates[i];
		if (*tlv == 0)
			break;
		/* This code makes sure that the 802.11b rates (1 MBit/s, 2
		   MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
		   Note that the values are MBit/s * 2, to mark them as
		   basic rates so that the firmware likes it better */
		if (*tlv == 0x02 || *tlv == 0x04 ||
		    *tlv == 0x0b || *tlv == 0x16)
			*tlv |= 0x80;
		tlv++;
	}
	rate_tlv->header.len = cpu_to_le16(i);
	return sizeof(rate_tlv->header) + i;
}


static int tda9840_checkit(struct CHIPSTATE *chip)
{
	int rc;
	rc = chip_read(chip);
	/* lower 5 bits should be 0 */
	return ((rc & 0x1f) == 0) ? 1 : 0;
}


s32 inotify_find_update_watch(struct inotify_handle *ih, struct inode *inode,
			      u32 mask)
{
	struct inotify_watch *old;
	int mask_add = 0;
	int ret;

	if (mask & IN_MASK_ADD)
		mask_add = 1;

	/* don't allow invalid bits: we don't want flags set */
	mask &= IN_ALL_EVENTS | IN_ONESHOT;
	if (unlikely(!mask))
		return -EINVAL;

	mutex_lock(&inode->inotify_mutex);
	mutex_lock(&ih->mutex);

	/*
	 * Handle the case of re-adding a watch on an (inode,ih) pair that we
	 * are already watching.  We just update the mask and return its wd.
	 */
	old = inode_find_handle(inode, ih);
	if (unlikely(!old)) {
		ret = -ENOENT;
		goto out;
	}

	if (mask_add)
		old->mask |= mask;
	else
		old->mask = mask;
	ret = old->wd;
out:
	mutex_unlock(&ih->mutex);
	mutex_unlock(&inode->inotify_mutex);
	return ret;
}


int audit_add_tree_rule(struct audit_krule *rule)
{
	struct audit_tree *seed = rule->tree, *tree;
	struct path path;
	struct vfsmount *mnt, *p;
	struct list_head list;
	int err;

	list_for_each_entry(tree, &tree_list, list) {
		if (!strcmp(seed->pathname, tree->pathname)) {
			put_tree(seed);
			rule->tree = tree;
			list_add(&rule->rlist, &tree->rules);
			return 0;
		}
	}
	tree = seed;
	list_add(&tree->list, &tree_list);
	list_add(&rule->rlist, &tree->rules);
	/* do not set rule->tree yet */
	mutex_unlock(&audit_filter_mutex);

	err = kern_path(tree->pathname, 0, &path);
	if (err)
		goto Err;
	mnt = collect_mounts(path.mnt, path.dentry);
	path_put(&path);
	if (!mnt) {
		err = -ENOMEM;
		goto Err;
	}
	list_add_tail(&list, &mnt->mnt_list);

	get_tree(tree);
	list_for_each_entry(p, &list, mnt_list) {
		err = tag_chunk(p->mnt_root->d_inode, tree);
		if (err)
			break;
	}

	list_del(&list);
	drop_collected_mounts(mnt);

	if (!err) {
		struct node *node;
		spin_lock(&hash_lock);
		list_for_each_entry(node, &tree->chunks, list)
			node->index &= ~(1U<<31);
		spin_unlock(&hash_lock);
	} else {
		trim_marked(tree);
		goto Err;
	}

	mutex_lock(&audit_filter_mutex);
	if (list_empty(&rule->rlist)) {
		put_tree(tree);
		return -ENOENT;
	}
	rule->tree = tree;
	put_tree(tree);

	return 0;
Err:
	mutex_lock(&audit_filter_mutex);
	list_del_init(&tree->list);
	list_del_init(&tree->rules);
	put_tree(tree);
	return err;
}


static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
{
	struct audit_rule_data *data;
	void *bufp;
	int i;

	data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
	if (unlikely(!data))
		return NULL;
	memset(data, 0, sizeof(*data));

	data->flags = krule->flags | krule->listnr;
	data->action = krule->action;
	data->field_count = krule->field_count;
	bufp = data->buf;
	for (i = 0; i < data->field_count; i++) {
		struct audit_field *f = &krule->fields[i];

		data->fields[i] = f->type;
		data->fieldflags[i] = f->op;
		switch(f->type) {
		case AUDIT_SUBJ_USER:
		case AUDIT_SUBJ_ROLE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			data->buflen += data->values[i] =
				audit_pack_string(&bufp, f->lsm_str);
			break;
		case AUDIT_WATCH:
			data->buflen += data->values[i] =
				audit_pack_string(&bufp, krule->watch->path);
			break;
		case AUDIT_DIR:
			data->buflen += data->values[i] =
				audit_pack_string(&bufp,
						  audit_tree_path(krule->tree));
			break;
		case AUDIT_FILTERKEY:
			data->buflen += data->values[i] =
				audit_pack_string(&bufp, krule->filterkey);
			break;
		default:
			data->values[i] = f->val;
		}
	}
	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) data->mask[i] = krule->mask[i];

	return data;
}


int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
{

	if (pathname[0] != '/' ||
	    rule->listnr != AUDIT_FILTER_EXIT ||
	    op & ~AUDIT_EQUAL ||
	    rule->inode_f || rule->watch || rule->tree)
		return -EINVAL;
	rule->tree = alloc_tree(pathname);
	if (!rule->tree)
		return -ENOMEM;
	return 0;
}


static inline void inotify_inode_is_dead(struct inode *inode)
{
}


int audit_filter_type(int type)
{
	struct audit_entry *e;
	int result = 0;

	rcu_read_lock();
	if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
		goto unlock_and_return;

	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
				list) {
		int i;
		for (i = 0; i < e->rule.field_count; i++) {
			struct audit_field *f = &e->rule.fields[i];
			if (f->type == AUDIT_MSGTYPE) {
				result = audit_comparator(type, f->op, f->val);
				if (!result)
					break;
			}
		}
		if (result)
			goto unlock_and_return;
	}
unlock_and_return:
	rcu_read_unlock();
	return result;
}


static void set_dentry_child_flags(struct inode *inode, int watched)
{
	struct dentry *alias;

	spin_lock(&dcache_lock);
	list_for_each_entry(alias, &inode->i_dentry, d_alias) {
		struct dentry *child;

		list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
			if (!child->d_inode)
				continue;

			spin_lock(&child->d_lock);
			if (watched)
				child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
			else
				child->d_flags &=~DCACHE_INOTIFY_PARENT_WATCHED;
			spin_unlock(&child->d_lock);
		}
	}
	spin_unlock(&dcache_lock);
}


int audit_update_lsm_rules(void)
{
	struct audit_entry *entry, *n, *nentry;
	struct audit_watch *watch;
	struct audit_tree *tree;
	int i, err = 0;

	/* audit_filter_mutex synchronizes the writers */
	mutex_lock(&audit_filter_mutex);

	for (i = 0; i < AUDIT_NR_FILTERS; i++) {
		list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
			if (!security_audit_rule_known(&entry->rule))
				continue;

			watch = entry->rule.watch;
			tree = entry->rule.tree;
			nentry = audit_dupe_rule(&entry->rule, watch);
			if (IS_ERR(nentry)) {
				/* save the first error encountered for the
				 * return value */
				if (!err)
					err = PTR_ERR(nentry);
				audit_panic("error updating LSM filters");
				if (watch)
					list_del(&entry->rule.rlist);
				list_del_rcu(&entry->list);
			} else {
				if (watch) {
					list_add(&nentry->rule.rlist,
						 &watch->rules);
					list_del(&entry->rule.rlist);
				} else if (tree)
					list_replace_init(&entry->rule.rlist,
						     &nentry->rule.rlist);
				list_replace_rcu(&entry->list, &nentry->list);
			}
			call_rcu(&entry->rcu, audit_free_rule_rcu);
		}
	}

	mutex_unlock(&audit_filter_mutex);

	return err;
}


static inline void inotify_init_watch(struct inotify_watch *watch)
{
}


int audit_filter_user(struct netlink_skb_parms *cb)
{
	enum audit_state state = AUDIT_DISABLED;
	struct audit_entry *e;
	int ret = 1;

	rcu_read_lock();
	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
		if (audit_filter_user_rules(cb, &e->rule, &state)) {
			if (state == AUDIT_DISABLED)
				ret = 0;
			break;
		}
	}
	rcu_read_unlock();

	return ret; /* Audit by default */
}


int audit_remove_tree_rule(struct audit_krule *rule)
{
	struct audit_tree *tree;
	tree = rule->tree;
	if (tree) {
		spin_lock(&hash_lock);
		list_del_init(&rule->rlist);
		if (list_empty(&tree->rules) && !tree->goner) {
			tree->root = NULL;
			list_del_init(&tree->same_root);
			tree->goner = 1;
			list_move(&tree->list, &prune_list);
			rule->tree = NULL;
			spin_unlock(&hash_lock);
			audit_schedule_prune();
			return 1;
		}
		rule->tree = NULL;
		spin_unlock(&hash_lock);
		return 1;
	}
	return 0;
}


static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
						     __u32 mask, __u32 cookie,
						     const char *filename)
{
}


static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
			int sockaddr_len, int flags)
{
	DEFINE_WAIT(wait);
	struct sock *sk = sock->sk;
	struct atm_vcc *vcc = ATM_SD(sock);
	int error;

	lock_sock(sk);
	set_bit(ATM_VF_WAITING, &vcc->flags);
	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
	sigd_enq(vcc, as_addparty, NULL, NULL,
		 (struct sockaddr_atmsvc *) sockaddr);
	if (flags & O_NONBLOCK) {
		finish_wait(sk->sk_sleep, &wait);
		error = -EINPROGRESS;
		goto out;
	}
	pr_debug("svc_addparty added wait queue\n");
	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
		schedule();
		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
	}
	finish_wait(sk->sk_sleep, &wait);
	error = xchg(&sk->sk_err_soft, 0);
out:
	release_sock(sk);
	return error;
}


static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct bsg_device *bd = file->private_data;
	int __user *uarg = (int __user *) arg;
	int ret;

	switch (cmd) {
		/*
		 * our own ioctls
		 */
	case SG_GET_COMMAND_Q:
		return put_user(bd->max_queue, uarg);
	case SG_SET_COMMAND_Q: {
		int queue;

		if (get_user(queue, uarg))
			return -EFAULT;
		if (queue < 1)
			return -EINVAL;

		spin_lock_irq(&bd->lock);
		bd->max_queue = queue;
		spin_unlock_irq(&bd->lock);
		return 0;
	}

	/*
	 * SCSI/sg ioctls
	 */
	case SG_GET_VERSION_NUM:
	case SCSI_IOCTL_GET_IDLUN:
	case SCSI_IOCTL_GET_BUS_NUMBER:
	case SG_SET_TIMEOUT:
	case SG_GET_TIMEOUT:
	case SG_GET_RESERVED_SIZE:
	case SG_SET_RESERVED_SIZE:
	case SG_EMULATED_HOST:
	case SCSI_IOCTL_SEND_COMMAND: {
		void __user *uarg = (void __user *) arg;
		return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
	}
	case SG_IO: {
		struct request *rq;
		struct bio *bio, *bidi_bio = NULL;
		struct sg_io_v4 hdr;

		if (copy_from_user(&hdr, uarg, sizeof(hdr)))
			return -EFAULT;

		rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE);
		if (IS_ERR(rq))
			return PTR_ERR(rq);

		bio = rq->bio;
		if (rq->next_rq)
			bidi_bio = rq->next_rq->bio;
		blk_execute_rq(bd->queue, NULL, rq, 0);
		ret = blk_complete_sgv4_hdr_rq(rq, &hdr, bio, bidi_bio);

		if (copy_to_user(uarg, &hdr, sizeof(hdr)))
			return -EFAULT;

		return ret;
	}
	/*
	 * block device ioctls
	 */
	default:
#if 0
		return ioctl_by_bdev(bd->bdev, cmd, arg);
#else
		return -ENOTTY;
#endif
	}
}


bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
{
	int ret = 0;

	if (hdr->guard != 'Q')
		return -EINVAL;
	if (hdr->dout_xfer_len > (q->max_sectors << 9) ||
	    hdr->din_xfer_len > (q->max_sectors << 9))
		return -EIO;

	switch (hdr->protocol) {
	case BSG_PROTOCOL_SCSI:
		switch (hdr->subprotocol) {
		case BSG_SUB_PROTOCOL_SCSI_CMD:
		case BSG_SUB_PROTOCOL_SCSI_TRANSPORT:
			break;
		default:
			ret = -EINVAL;
		}
		break;
	default:
		ret = -EINVAL;
	}

	*rw = hdr->dout_xfer_len ? WRITE : READ;
	return ret;
}


static int __init bsg_init(void)
{
	int ret, i;
	dev_t devid;

	bsg_cmd_cachep = kmem_cache_create("bsg_cmd",
				sizeof(struct bsg_command), 0, 0, NULL);
	if (!bsg_cmd_cachep) {
		printk(KERN_ERR "bsg: failed creating slab cache\n");
		return -ENOMEM;
	}

	for (i = 0; i < BSG_LIST_ARRAY_SIZE; i++)
		INIT_HLIST_HEAD(&bsg_device_list[i]);

	bsg_class = class_create(THIS_MODULE, "bsg");
	if (IS_ERR(bsg_class)) {
		ret = PTR_ERR(bsg_class);
		goto destroy_kmemcache;
	}

	ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
	if (ret)
		goto destroy_bsg_class;

	bsg_major = MAJOR(devid);

	cdev_init(&bsg_cdev, &bsg_fops);
	ret = cdev_add(&bsg_cdev, MKDEV(bsg_major, 0), BSG_MAX_DEVS);
	if (ret)
		goto unregister_chrdev;

	printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
	       " loaded (major %d)\n", bsg_major);
	return 0;
unregister_chrdev:
	unregister_chrdev_region(MKDEV(bsg_major, 0), BSG_MAX_DEVS);
destroy_bsg_class:
	class_destroy(bsg_class);
destroy_kmemcache:
	kmem_cache_destroy(bsg_cmd_cachep);
	return ret;
}


int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode,
		   unsigned int cmd, void __user *arg)
{
	int err;

	if (!q || blk_get_queue(q))
		return -ENXIO;

	switch (cmd) {
		/*
		 * new sgv3 interface
		 */
		case SG_GET_VERSION_NUM:
			err = sg_get_version(arg);
			break;
		case SCSI_IOCTL_GET_IDLUN:
			err = scsi_get_idlun(q, arg);
			break;
		case SCSI_IOCTL_GET_BUS_NUMBER:
			err = scsi_get_bus(q, arg);
			break;
		case SG_SET_TIMEOUT:
			err = sg_set_timeout(q, arg);
			break;
		case SG_GET_TIMEOUT:
			err = sg_get_timeout(q);
			break;
		case SG_GET_RESERVED_SIZE:
			err = sg_get_reserved_size(q, arg);
			break;
		case SG_SET_RESERVED_SIZE:
			err = sg_set_reserved_size(q, arg);
			break;
		case SG_EMULATED_HOST:
			err = sg_emulated_host(q, arg);
			break;
		case SG_IO: {
			struct sg_io_hdr hdr;

			err = -EFAULT;
			if (copy_from_user(&hdr, arg, sizeof(hdr)))
				break;
			err = sg_io(q, bd_disk, &hdr, mode);
			if (err == -EFAULT)
				break;

			if (copy_to_user(arg, &hdr, sizeof(hdr)))
				err = -EFAULT;
			break;
		}
		case CDROM_SEND_PACKET: {
			struct cdrom_generic_command cgc;
			struct sg_io_hdr hdr;

			err = -EFAULT;
			if (copy_from_user(&cgc, arg, sizeof(cgc)))
				break;
			cgc.timeout = clock_t_to_jiffies(cgc.timeout);
			memset(&hdr, 0, sizeof(hdr));
			hdr.interface_id = 'S';
			hdr.cmd_len = sizeof(cgc.cmd);
			hdr.dxfer_len = cgc.buflen;
			err = 0;
			switch (cgc.data_direction) {
				case CGC_DATA_UNKNOWN:
					hdr.dxfer_direction = SG_DXFER_UNKNOWN;
					break;
				case CGC_DATA_WRITE:
					hdr.dxfer_direction = SG_DXFER_TO_DEV;
					break;
				case CGC_DATA_READ:
					hdr.dxfer_direction = SG_DXFER_FROM_DEV;
					break;
				case CGC_DATA_NONE:
					hdr.dxfer_direction = SG_DXFER_NONE;
					break;
				default:
					err = -EINVAL;
			}
			if (err)
				break;

			hdr.dxferp = cgc.buffer;
			hdr.sbp = cgc.sense;
			if (hdr.sbp)
				hdr.mx_sb_len = sizeof(struct request_sense);
			hdr.timeout = jiffies_to_msecs(cgc.timeout);
			hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
			hdr.cmd_len = sizeof(cgc.cmd);

			err = sg_io(q, bd_disk, &hdr, mode);
			if (err == -EFAULT)
				break;

			if (hdr.status)
				err = -EIO;

			cgc.stat = err;
			cgc.buflen = hdr.resid;
			if (copy_to_user(arg, &cgc, sizeof(cgc)))
				err = -EFAULT;

			break;
		}

		/*
		 * old junk scsi send command ioctl
		 */
		case SCSI_IOCTL_SEND_COMMAND:
			printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
			err = -EINVAL;
			if (!arg)
				break;

			err = sg_scsi_ioctl(q, bd_disk, mode, arg);
			break;
		case CDROMCLOSETRAY:
			err = blk_send_start_stop(q, bd_disk, 0x03);
			break;
		case CDROMEJECT:
			err = blk_send_start_stop(q, bd_disk, 0x02);
			break;
		default:
			err = -ENOTTY;
	}

	blk_put_queue(q);
	return err;
}


static void bsg_kref_release_function(struct kref *kref)
{
	struct bsg_class_device *bcd =
		container_of(kref, struct bsg_class_device, ref);
	struct device *parent = bcd->parent;

	if (bcd->release)
		bcd->release(bcd->parent);

	put_device(parent);
}


static int sg_get_reserved_size(struct request_queue *q, int __user *p)
{
	unsigned val = min(q->sg_reserved_size, q->max_sectors << 9);

	return put_user(val, p);
}


static void ibwdt_shutdown(struct platform_device *dev)
{
	/* Turn the WDT off if we have a soft shutdown */
	ibwdt_disable();
}


int avahi_server_is_record_local(AvahiServer *s, AvahiIfIndex interface, AvahiProtocol protocol, AvahiRecord *record) {
    AvahiEntry *e;

    assert(s);
    assert(record);

    for (e = avahi_hashmap_lookup(s->entries_by_key, record->key); e; e = e->by_key_next)

        if ((e->interface == interface || e->interface <= 0 || interface <= 0) &&
            (e->protocol == protocol || e->protocol == AVAHI_PROTO_UNSPEC || protocol == AVAHI_PROTO_UNSPEC) &&
            (!e->group || e->group->state == AVAHI_ENTRY_GROUP_ESTABLISHED || e->group->state == AVAHI_ENTRY_GROUP_REGISTERING) &&
            avahi_record_equal_no_ttl(record, e->record))
            return 1;

    return 0;
}


int avahi_server_get_group_of_service(AvahiServer *s, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain, AvahiSEntryGroup** ret_group) {
    AvahiKey *key = NULL;
    AvahiEntry *e;
    int ret;
    char n[AVAHI_DOMAIN_NAME_MAX];

    assert(s);
    assert(name);
    assert(type);
    assert(ret_group);

    AVAHI_CHECK_VALIDITY(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE);
    AVAHI_CHECK_VALIDITY(s, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL);
    AVAHI_CHECK_VALIDITY(s, avahi_is_valid_service_name(name), AVAHI_ERR_INVALID_SERVICE_NAME);
    AVAHI_CHECK_VALIDITY(s, avahi_is_valid_service_type_strict(type), AVAHI_ERR_INVALID_SERVICE_TYPE);
    AVAHI_CHECK_VALIDITY(s, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME);

    if ((ret = avahi_service_name_join(n, sizeof(n), name, type, domain) < 0))
        return avahi_server_set_errno(s, ret);

    if (!(key = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV)))
        return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY);

    e = find_entry(s, interface, protocol, key);
    avahi_key_unref(key);

    if (e) {
        *ret_group = e->group;
        return AVAHI_OK;
    }

    return avahi_server_set_errno(s, AVAHI_ERR_NOT_FOUND);
}


static void* reflect_cache_walk_callback(AvahiCache *c, AvahiKey *pattern, AvahiCacheEntry *e, void* userdata) {
    AvahiServer *s = userdata;

    assert(c);
    assert(pattern);
    assert(e);
    assert(s);

    avahi_record_list_push(s->record_list, e->record, e->cache_flush, 0, 0);
    return NULL;
}


const char* avahi_server_get_host_name(AvahiServer *s) {
    assert(s);

    return s->host_name;
}


int avahi_server_set_host_name(AvahiServer *s, const char *host_name) {
    char *hn = NULL;
    assert(s);

    AVAHI_CHECK_VALIDITY(s, !host_name || avahi_is_valid_host_name(host_name), AVAHI_ERR_INVALID_HOST_NAME);

    if (!host_name) {
        hn = avahi_get_host_name_strdup();
        hn[strcspn(hn, ".")] = 0;
        host_name = hn;
    }

    if (avahi_domain_equal(s->host_name, host_name) && s->state != AVAHI_SERVER_COLLISION) {
        avahi_free(hn);
        return avahi_server_set_errno(s, AVAHI_ERR_NO_CHANGE);
    }

    withdraw_host_rrs(s);

    avahi_free(s->host_name);
    s->host_name = hn ? hn : avahi_strdup(host_name);

    update_fqdn(s);

    register_stuff(s);
    return AVAHI_OK;
}


void* avahi_server_get_data(AvahiServer *s) {
    assert(s);

    return s->userdata;
}


int avahi_server_set_errno(AvahiServer *s, int error) {
    assert(s);

    return s->error = error;
}


static AvahiLegacyUnicastReflectSlot* allocate_slot(AvahiServer *s) {
    unsigned n, idx = (unsigned) -1;
    AvahiLegacyUnicastReflectSlot *slot;

    assert(s);

    if (!s->legacy_unicast_reflect_slots)
        s->legacy_unicast_reflect_slots = avahi_new0(AvahiLegacyUnicastReflectSlot*, AVAHI_LEGACY_UNICAST_REFLECT_SLOTS_MAX);

    for (n = 0; n < AVAHI_LEGACY_UNICAST_REFLECT_SLOTS_MAX; n++, s->legacy_unicast_reflect_id++) {
        idx = s->legacy_unicast_reflect_id % AVAHI_LEGACY_UNICAST_REFLECT_SLOTS_MAX;

        if (!s->legacy_unicast_reflect_slots[idx])
            break;
    }

    if (idx == (unsigned) -1 || s->legacy_unicast_reflect_slots[idx])
        return NULL;

    if (!(slot = avahi_new(AvahiLegacyUnicastReflectSlot, 1)))
        return NULL; /* OOM */

    s->legacy_unicast_reflect_slots[idx] = slot;
    slot->id = s->legacy_unicast_reflect_id++;
    slot->server = s;

    return slot;
}


void avahi_server_prepare_response(AvahiServer *s, AvahiInterface *i, AvahiEntry *e, int unicast_response, int auxiliary) {
    assert(s);
    assert(i);
    assert(e);

    avahi_record_list_push(s->record_list, e->record, e->flags & AVAHI_PUBLISH_UNIQUE, unicast_response, auxiliary);
}


static AvahiEntry *find_entry(AvahiServer *s, AvahiIfIndex interface, AvahiProtocol protocol, AvahiKey *key) {
    AvahiEntry *e;

    assert(s);
    assert(key);

    for (e = avahi_hashmap_lookup(s->entries_by_key, key); e; e = e->by_key_next)

        if ((e->interface == interface || e->interface <= 0 || interface <= 0) &&
            (e->protocol == protocol || e->protocol == AVAHI_PROTO_UNSPEC || protocol == AVAHI_PROTO_UNSPEC) &&
            (!e->group || e->group->state == AVAHI_ENTRY_GROUP_ESTABLISHED || e->group->state == AVAHI_ENTRY_GROUP_REGISTERING))

            return e;

    return NULL;
}


static void withdraw_host_rrs(AvahiServer *s) {
    assert(s);

    if (s->hinfo_entry_group)
        avahi_s_entry_group_reset(s->hinfo_entry_group);

    if (s->browse_domain_entry_group)
        avahi_s_entry_group_reset(s->browse_domain_entry_group);

    avahi_interface_monitor_update_rrs(s->monitor, 1);
    s->n_host_rr_pending = 0;
}


static inline int qdisc_qlen(struct Qdisc *q)
{
	return q->q.qlen;
}


static inline int qdisc_restart(struct net_device *dev)
{
	struct Qdisc *q = dev->qdisc;
	struct sk_buff *skb;
	int ret = NETDEV_TX_BUSY;

	/* Dequeue packet */
	if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
		return 0;

	/* And release queue */
	spin_unlock(&dev->queue_lock);

	HARD_TX_LOCK(dev, smp_processor_id());
	if (!netif_subqueue_stopped(dev, skb))
		ret = dev_hard_start_xmit(skb, dev);
	HARD_TX_UNLOCK(dev);

	spin_lock(&dev->queue_lock);
	q = dev->qdisc;

	switch (ret) {
	case NETDEV_TX_OK:
		/* Driver sent out skb successfully */
		ret = qdisc_qlen(q);
		break;

	case NETDEV_TX_LOCKED:
		/* Driver try lock failed */
		ret = handle_dev_cpu_collision(skb, dev, q);
		break;

	default:
		/* Driver returned NETDEV_TX_BUSY - requeue skb */
		if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
			printk(KERN_WARNING "BUG %s code %d qlen %d\n",
			       dev->name, ret, q->q.qlen);

		ret = dev_requeue_skb(skb, dev, q);
		break;
	}

	return ret;
}


static struct sk_buff *noop_dequeue(struct Qdisc * qdisc)
{
	return NULL;
}


SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
{
	int err = 0;
	struct fs_struct *fs, *new_fs = NULL;
	struct sighand_struct *new_sigh = NULL;
	struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
	struct files_struct *fd, *new_fd = NULL;
	struct nsproxy *new_nsproxy = NULL;
	int do_sysvsem = 0;

	check_unshare_flags(&unshare_flags);

	/* Return -EINVAL for all unsupported flags */
	err = -EINVAL;
	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
		goto bad_unshare_out;

	/*
	 * CLONE_NEWIPC must also detach from the undolist: after switching
	 * to a new ipc namespace, the semaphore arrays from the old
	 * namespace are unreachable.
	 */
	if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
		do_sysvsem = 1;
	if ((err = unshare_thread(unshare_flags)))
		goto bad_unshare_out;
	if ((err = unshare_fs(unshare_flags, &new_fs)))
		goto bad_unshare_cleanup_thread;
	if ((err = unshare_sighand(unshare_flags, &new_sigh)))
		goto bad_unshare_cleanup_fs;
	if ((err = unshare_vm(unshare_flags, &new_mm)))
		goto bad_unshare_cleanup_sigh;
	if ((err = unshare_fd(unshare_flags, &new_fd)))
		goto bad_unshare_cleanup_vm;
	if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
			new_fs)))
		goto bad_unshare_cleanup_fd;

	if (new_fs ||  new_mm || new_fd || do_sysvsem || new_nsproxy) {
		if (do_sysvsem) {
			/*
			 * CLONE_SYSVSEM is equivalent to sys_exit().
			 */
			exit_sem(current);
		}

		if (new_nsproxy) {
			switch_task_namespaces(current, new_nsproxy);
			new_nsproxy = NULL;
		}

		task_lock(current);

		if (new_fs) {
			fs = current->fs;
			current->fs = new_fs;
			new_fs = fs;
		}

		if (new_mm) {
			mm = current->mm;
			active_mm = current->active_mm;
			current->mm = new_mm;
			current->active_mm = new_mm;
			activate_mm(active_mm, new_mm);
			new_mm = mm;
		}

		if (new_fd) {
			fd = current->files;
			current->files = new_fd;
			new_fd = fd;
		}

		task_unlock(current);
	}

	if (new_nsproxy)
		put_nsproxy(new_nsproxy);

bad_unshare_cleanup_fd:
	if (new_fd)
		put_files_struct(new_fd);

bad_unshare_cleanup_vm:
	if (new_mm)
		mmput(new_mm);

bad_unshare_cleanup_sigh:
	if (new_sigh)
		if (atomic_dec_and_test(&new_sigh->count))
			kmem_cache_free(sighand_cachep, new_sigh);

bad_unshare_cleanup_fs:
	if (new_fs)
		put_fs_struct(new_fs);

bad_unshare_cleanup_thread:
bad_unshare_out:
	return err;
}


void __init proc_caches_init(void)
{
	sighand_cachep = kmem_cache_create("sighand_cache",
			sizeof(struct sighand_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU,
			sighand_ctor);
	signal_cachep = kmem_cache_create("signal_cache",
			sizeof(struct signal_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	files_cachep = kmem_cache_create("files_cache",
			sizeof(struct files_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	fs_cachep = kmem_cache_create("fs_cache",
			sizeof(struct fs_struct), 0,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	mm_cachep = kmem_cache_create("mm_struct",
			sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
	mmap_init();
}