基於openswan klips的IPsec實現分析(八)內核SADB維護(2)

基於openswan klips的IPsec實現分析(七)內核SADB維護2

轉載請註明出處:http://blog.csdn.net/rosetta

內核完整的消息處理過程,以隧道模式ESP協議增加SA情況爲例

接收消息和發送消息的知識涉及到Linux內核了,所以不關注它是怎麼收發,而是關注收到消息後對消息本身的處理過程。但爲了保證代碼的完整性,就把接收和發送的代碼全部帖上來了(但省略部分比較長的調試信息)。

 

其接收發送函數調用關係如下:

pfkey_recvmsg()接收消息

pfkey_sendmsg()發送消息

 -> pfkey_msg_interp()解釋消息後執行msg_parsers[]數組裏相應函數(增加、刪除SA等)。

         ->satype2proto()通過查表獲取內核支持的協議號

         ->pfkey_msg_parse()解析並處理消息是否有錯,判斷相應的協議是否有算法支持等。

          ->ext_processors[]()處理消息中具體的數據結構,如SA,密鑰,地址,週期等。

                   ->msg_parsers[]()調用最終的SA處理函數。

 

在msg_parsers[]處理函數數組中的每個函數,如果需要,都會在處理完後通過pfkey_upmsg()函數把消息發到PF_KEY密鑰套接字傳遞給應用層。

從應用層接收到消息

pfkey_recvmsg()函數

/*

 *     Receive PF_KEY data up.

 */

DEBUG_NO_STATIC int

#ifdef NET_26

pfkey_recvmsg(struct kiocb *kiocb

               , struct socket *sock

               , struct msghdr *msg

               , size_t size

               , int flags)

#else

pfkey_recvmsg(struct socket *sock

               , struct msghdr *msg

               , int size, int flags

               , struct scm_cookie *scm)

#endif

{

         structsock *sk;

         intnoblock = flags & MSG_DONTWAIT;

         structsk_buff *skb;

         interror;

 

         if(sock== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_recvmsg: "

                                "Null socket passed in.\n");

                   return-EINVAL;

         }

 

         sk= sock->sk; 

 

         if(sk== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_recvmsg: "

                                "Null sock passed in forsock=0p%p.\n", sock);

                   return-EINVAL;

         }

 

         if(msg== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_recvmsg: "

                                "Null msghdr passed in for sock=0p%p,sk=0p%p.\n",

                                sock, sk);

                   return-EINVAL;

         }

 

         if(flags& ~MSG_PEEK) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "flags (%d) other than MSG_PEEK notsupported.\n",

                                flags);

                   return-EOPNOTSUPP;

         }

                  

         msg->msg_namelen= 0; /* sizeof(*ska); */

                  

         if(sk->sk_err){

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "sk->sk_err=%d.\n", sk->sk_err);

                   returnsock_error(sk);

         }

 

         if((skb= skb_recv_datagram(sk, flags, noblock, &error) )== NULL) {

                return error;

         }

 

         if(size> skb->len) {

                   size= skb->len;

         }

         elseif(size <skb->len) {

                   msg->msg_flags|= MSG_TRUNC;

         }

 

         skb_copy_datagram_iovec(skb,0, msg->msg_iov, size);

#ifdef HAVE_TSTAMP

         sk->sk_stamp.tv_sec  = skb->tstamp.off_sec;

         sk->sk_stamp.tv_usec= skb->tstamp.off_usec;

#else

       sk->sk_stamp=skb->stamp;

#endif

 

         skb_free_datagram(sk,skb);

         returnsize;

}

處理消息後發送給應用層

pfkey_sendmsg()函數

/*

 *     Send PF_KEY data down.

 */

DEBUG_NO_STATIC int

#ifdef NET_26

pfkey_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_tlen)

#else

pfkey_sendmsg(struct socket *sock, structmsghdr *msg, int len, struct scm_cookie *scm)

#endif

{

         structsock *sk;

         interror = 0;

         //pfkey_msg用於存放來至應用層的數據.

struct sadb_msg*pfkey_msg = NULL, *pfkey_reply = NULL;

        

        

         if(sock== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "Null socket passed in.\n");

                   SENDERR(EINVAL);

         }

        

         sk= sock->sk;

 

         if(sk== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "Null sock passed in.\n");

                   SENDERR(EINVAL);

         }

        

         if(msg== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "Null msghdr passed in.\n");

                   SENDERR(EINVAL);

         }

 

         KLIPS_PRINT(debug_pfkey,

                       "klips_debug:pfkey_sendmsg:.\n");

         if(sk->sk_err){

                   error= sock_error(sk);

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "sk->err is non-zero, returns%d.\n",

                                error);

                   SENDERR(-error);

         }

 

         if((current->uid!= 0)) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "must be root to send messages topfkey sockets.\n");

                   SENDERR(EACCES);

         }

 

         if(msg->msg_control)

         {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "can't set flags or setmsg_control.\n");

                   SENDERR(EINVAL);

         }

                  

         if(sk->sk_shutdown& SEND_SHUTDOWN) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "shutdown.\n");

                   send_sig(SIGPIPE,current, 0);

                   SENDERR(EPIPE);

         }

        

         if(len< sizeof(struct sadb_msg)) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "bogus msg len of %d, toosmall.\n", (int)len);

                   SENDERR(EMSGSIZE);

         }

 

         KLIPS_PRINT(debug_pfkey,

                       "klips_debug:pfkey_sendmsg: "

                       "allocating %d bytes for downwardmessage.\n",

                       (int)len);

         //爲pfkey_msg分配空間

         if((pfkey_msg= (struct sadb_msg*)kmalloc(len, GFP_KERNEL)) == NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "memory allocation error.\n");

                   SENDERR(ENOBUFS);

         }

        

//拷貝待處理消息至pfkey_msg指向的緩衝區中

memcpy_fromiovec((void*)pfkey_msg, msg->msg_iov, len);

        

         //一些字段的正確性判斷,比如版本,長度,是否是發向自己的消息等。

         if(pfkey_msg->sadb_msg_version!= PF_KEY_V2) {

                   KLIPS_PRINT(1|| debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "not PF_KEY_V2 msg, found %d, shouldbe %d.\n",

                                pfkey_msg->sadb_msg_version,

                                PF_KEY_V2);

                   kfree((void*)pfkey_msg);

                   return-EINVAL;

         }

 

         if(len!= pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "bogus msg len of %d, not %d bytealigned.\n",

                                (int)len, (int)IPSEC_PFKEYv2_ALIGN);

                   SENDERR(EMSGSIZE);

         }

 

         if(pfkey_msg->sadb_msg_reserved){

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "reserved field must be zero, set to%d.\n",

                                pfkey_msg->sadb_msg_reserved);

                   SENDERR(EINVAL);

         }

        

         if((pfkey_msg->sadb_msg_type> SADB_MAX) || (!pfkey_msg->sadb_msg_type)){

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_sendmsg: "

                                "msg type too large orsmall:%d.\n",

                                pfkey_msg->sadb_msg_type);

                   SENDERR(EINVAL);

         }

        

         KLIPS_PRINT(debug_pfkey,

                       "klips_debug:pfkey_sendmsg: "

                       "msg sent for parsing.\n");

 

         //解釋應用層發過來的消息pfkey_msg.pfkey_reply在此函數中沒有實際作用。

         if((error= pfkey_msg_interp(sk, pfkey_msg, &pfkey_reply))){

                  //出錯處理,省略

                  

                   SENDERR(-error);

         }

 

 errlab:

         if(pfkey_msg) {

                   kfree((void*)pfkey_msg);

         }

        

         if(error){

                   returnerror;

         }else {

                   returnlen;

         }

}

 

pfkey_msg_interp()函數

int

pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg,

                                     structsadb_msg **pfkey_reply)

{

         interror = 0;

         inti;

         structsadb_ext *extensions[SADB_EXT_MAX+1];//臨時使用。

         structpfkey_extracted_data extr = {NULL, NULL, NULL};

        

         pfkey_extensions_init(extensions);//初始化指針數據extensions成員爲NULL

         //分配structipsec_sa大小內存。

         extr.ips= ipsec_sa_alloc(&error); /* pass in error var by pointer */

         if(extr.ips== NULL) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_msg_interp: "

                                "memory allocation error.\n");

                   SENDERR(-error);

         }

 

         if(pfkey_msg->sadb_msg_satype> SADB_SATYPE_MAX) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_msg_interp: "

                                "satype %d > max %d\n",

                                pfkey_msg->sadb_msg_satype,

                                SADB_SATYPE_MAX);

                   SENDERR(EINVAL);

         }

        

         switch(pfkey_msg->sadb_msg_type){

         caseSADB_GETSPI:

         caseSADB_UPDATE:

         caseSADB_ADD:

         caseSADB_DELETE:

         caseSADB_X_GRPSA:

         caseSADB_X_ADDFLOW:

                   //通過查表獲取內核支持的協議號

                   if(!(extr.ips->ips_said.proto= satype2proto(pfkey_msg->sadb_msg_satype))) {

                            KLIPS_PRINT(debug_pfkey,

                                         "klips_debug:pfkey_msg_interp: "

                                         "satype %d lookup failed.\n",

                                         pfkey_msg->sadb_msg_satype);

                            SENDERR(EINVAL);

                   }else {

                   }

                   break;

         default:

                   break;

         }

        

         /*The NULL below causes the default extension parsers to be used */

         /*Parse the extensions */

         //pfkey_msg是從應用層收到的消息數據。

//這裏解析數據,extensions爲臨時使用存放的指針數組。

//解析pfkey_msg完畢後的內容都放在extensions中。

         if((error= pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_IN)))

         {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_msg_interp: "

                                "message parsing failed with error%d.\n",

                                error);

                   SENDERR(-error);

         }

        

         /*Process the extensions */

         for(i=1;i <= SADB_EXT_MAX;i++)    {

                   if(extensions[i]!= NULL) {

                            //對相關SA,密鑰,地址,週期等參數做處理。

           //並把相關值賦給extr->ips中。

                            if((error= ext_processors[i](extensions[i], &extr))) {

                                     KLIPS_PRINT(debug_pfkey,

                                                   "klips_debug:pfkey_msg_interp: "

                                                   "extension processing for type %dfailed with error %d.\n",

                                                   i,

                                                   error);

                                     SENDERR(-error);

                            }

                   }

         }

        

         /*Parse the message types */

//這纔到核心處理數據處。比如增加SA到SA的哈希表中等。

   //extension是應用層傳來的數據.        

if((error =msg_parsers[pfkey_msg->sadb_msg_type](sk, extensions, &extr))) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_msg_interp: "

                                "message parsing failed with error%d.\n",

                                error);

                   SENDERR(-error);

         }

 

 errlab:

         if(extr.ips!= NULL) {

                   ipsec_sa_wipe(extr.ips);

         }

         if(extr.ips2!= NULL) {

                   ipsec_sa_wipe(extr.ips2);

         }

         if(extr.eroute != NULL) {

                   kfree(extr.eroute);

         }

         return(error);

}

satype2proto()函數

通過應用層傳遞sadb_msg_satype類型從satype_tbl[]表中查找內核使用的協議號。

uint8_t

satype2proto(uint8_t satype)

{

   int i =0;

 

   while(satype_tbl[i].satype != satype && satype_tbl[i].satype !=0) {

       i++;

    }

   return satype_tbl[i].proto;

}

 

struct satype_tbl {

   uint8_t proto;

   uint8_t satype;

   char* name;

} static satype_tbl[] = {

    {IPPROTO_ESP,  SADB_SATYPE_ESP,    "ESP"  },

    {IPPROTO_AH,   SADB_SATYPE_AH,     "AH"   },

    {IPPROTO_IPIP, SADB_X_SATYPE_IPIP, "IPIP" },

#ifdef CONFIG_KLIPS_IPCOMP

    {IPPROTO_COMP, SADB_X_SATYPE_COMP, "COMP" },

#endif /* CONFIG_KLIPS_IPCOMP */

    {IPPROTO_INT,  SADB_X_SATYPE_INT,  "INT" },

    {0,        0,          "UNKNOWN" }

};

 

pfkey_msg_parse ()函數

int

pfkey_msg_parse(struct sadb_msg *pfkey_msg,

       struct pf_key_ext_parsers_def *ext_parsers[],

       struct sadb_ext *extensions[],

       int dir)

{

         //此函數省略大部分內容。

          //先賦值爲默認解析處理函數ext_default_parsers。

if(ext_parsers== NULL) ext_parsers = ext_default_parsers;

 

/* Do I evenknow about this type of extension? */

       //判斷相信的解析處理函數是否爲空。

       if(ext_parsers[pfkey_ext->sadb_ext_type]==NULL) {

           ERROR("pfkey_msg_parse: "

                "ext type %d(%s) unknown,ignoring.\n",

                pfkey_ext->sadb_ext_type,

               pfkey_v2_sadb_ext_string(pfkey_ext->sadb_ext_type));

           goto next_ext;

       }

}

ext_default_parsers[]函數指針數組的指針

/*

 *PF_KEYv2 permitted and required extensions in and out bitmaps

 */

struct pf_key_ext_parsers_def {

         int  (*parser)(struct sadb_ext*);

         char  *parser_name;

};

 

#define DEFINEPARSER(NAME) static structpf_key_ext_parsers_def NAME##_def={NAME, #NAME};

 

DEFINEPARSER(pfkey_sa_parse);

DEFINEPARSER(pfkey_lifetime_parse);

DEFINEPARSER(pfkey_address_parse);

DEFINEPARSER(pfkey_key_parse);

DEFINEPARSER(pfkey_ident_parse);

DEFINEPARSER(pfkey_sens_parse);

DEFINEPARSER(pfkey_prop_parse);

DEFINEPARSER(pfkey_supported_parse);

DEFINEPARSER(pfkey_spirange_parse);

DEFINEPARSER(pfkey_x_kmprivate_parse);

DEFINEPARSER(pfkey_x_satype_parse);

DEFINEPARSER(pfkey_x_ext_debug_parse);

DEFINEPARSER(pfkey_x_ext_protocol_parse);

#ifdef NAT_TRAVERSAL

DEFINEPARSER(pfkey_x_ext_nat_t_type_parse);

DEFINEPARSER(pfkey_x_ext_nat_t_port_parse);

#endif

 

struct pf_key_ext_parsers_def*ext_default_parsers[]=

{

         NULL,                 /* pfkey_msg_parse, */

         &pfkey_sa_parse_def, //注意之前的宏定義DEFINEPARSER,這裏其它就是“函數名_def”,所以實際上是pfkey_sa_parse(),以下類似。

         &pfkey_lifetime_parse_def,

         &pfkey_lifetime_parse_def,

         &pfkey_lifetime_parse_def,

         &pfkey_address_parse_def,

         &pfkey_address_parse_def,

         &pfkey_address_parse_def,

         &pfkey_key_parse_def,

         &pfkey_key_parse_def,

         &pfkey_ident_parse_def,

         &pfkey_ident_parse_def,

         &pfkey_sens_parse_def,

         &pfkey_prop_parse_def,

         &pfkey_supported_parse_def,

         &pfkey_supported_parse_def,

         &pfkey_spirange_parse_def,

         &pfkey_x_kmprivate_parse_def,

         &pfkey_x_satype_parse_def,

         &pfkey_sa_parse_def,

         &pfkey_address_parse_def,

         &pfkey_address_parse_def,

         &pfkey_address_parse_def,

         &pfkey_address_parse_def,

         &pfkey_address_parse_def,

         &pfkey_x_ext_debug_parse_def,

         &pfkey_x_ext_protocol_parse_def

#ifdef NAT_TRAVERSAL

         ,

         &pfkey_x_ext_nat_t_type_parse_def,

         &pfkey_x_ext_nat_t_port_parse_def,

         &pfkey_x_ext_nat_t_port_parse_def,

         &pfkey_address_parse_def

#endif

};

ext_processors[]函數指針數組

DEBUG_NO_STATIC int(*ext_processors[SADB_EXT_MAX+1])(struct sadb_ext *pfkey_ext, structpfkey_extracted_data* extr) =

{

 NULL, /* pfkey_msg_process, */

       pfkey_sa_process,

       pfkey_lifetime_process,

       pfkey_lifetime_process,

       pfkey_lifetime_process,

       pfkey_address_process,

       pfkey_address_process,

       pfkey_address_process,

       pfkey_key_process,

       pfkey_key_process,

       pfkey_ident_process,

       pfkey_ident_process,

       pfkey_sens_process,

       pfkey_prop_process,

       pfkey_supported_process,

       pfkey_supported_process,

       pfkey_spirange_process,

       pfkey_x_kmprivate_process,

       pfkey_x_satype_process,

       pfkey_sa_process,

       pfkey_address_process,

       pfkey_address_process,

       pfkey_address_process,

       pfkey_address_process,

       pfkey_address_process,

         pfkey_x_debug_process,

         pfkey_x_protocol_process

#ifdef CONFIG_IPSEC_NAT_TRAVERSAL

         ,

         pfkey_x_nat_t_type_process,

         pfkey_x_nat_t_port_process,

         pfkey_x_nat_t_port_process,

         pfkey_address_process

#endif      

};

msg_parsers[]函數指針數組

//如果是隧道模式ESP協議增加SA的話會依次執行pfkey_add_parse(),pfkey_x_grpsa_parse()和pfkey_x_addflow_parse()

DEBUG_NO_STATIC int (*msg_parsers[SADB_MAX +1])(struct sock*sk, struct sadb_ext *extensions[], stru

 =

{

    NULL, /* RESERVED */

    pfkey_getspi_parse, //獲取SPI

    pfkey_update_parse,//更新SA

    pfkey_add_parse, //增加SA

    pfkey_delete_parse,//5 //刪除SA

 

    pfkey_get_parse, //獲取SA

    pfkey_acquire_parse, //請求操作

    pfkey_register_parse, //註冊

    pfkey_expire_parse, //到期

    pfkey_flush_parse,//10 //清空SA

 

    pfkey_dump_parse,  //傾斜SA

    pfkey_x_promisc_parse, //混雜模式

    pfkey_x_pchange_parse, //

    pfkey_x_grpsa_parse, //歸組SA

    pfkey_x_addflow_parse,//15

 

    pfkey_x_delflow_parse,

    pfkey_x_msg_debug_parse

#ifdef CONFIG_IPSEC_NAT_TRAVERSAL

    ,pfkey_x_nat_t_new_mapping_parse

#endif

};

pfkey_add_parse()函數

DEBUG_NO_STATIC int

pfkey_add_parse (struct sock *sk, structsadb_ext **extensions, struct pfkey_extracted_data* extr)

{

         interror = 0;

         structipsec_sa* ipsq;

         charsa[SATOT_BUF];

         size_tsa_len;

         structsadb_ext *extensions_reply[SADB_EXT_MAX+1];

         structsadb_msg *pfkey_reply = NULL;

         structsocket_list *pfkey_socketsp;

         uint8_tsatype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;

 

         KLIPS_PRINT(debug_pfkey,

                       "klips_debug:pfkey_add_parse:.\n");

 

         pfkey_extensions_init(extensions_reply);

 

         if(((structsadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_add_parse: "

                                "error, sa_state=%d must beMATURE=%d\n",

                                ((structsadb_sa*)extensions[SADB_EXT_SA])->sadb_sa_state,

                                SADB_SASTATE_MATURE);

                   SENDERR(EINVAL);

         }

 

         if(!extr|| !extr->ips) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_add_parse: "

                                "extr or extr->ips pointerNULL\n");

                   SENDERR(EINVAL);

         }

 

         sa_len= satot(&extr->ips->ips_said, 0, sa, sizeof(sa));

 

         ipsq= ipsec_sa_getbyid(&(extr->ips->ips_said));

         if(ipsq!= NULL) {

                   ipsec_sa_put(ipsq);

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_add_parse: "

                                "found an old ipsec_sa for SA%s,delete it first.\n",

                                sa_len ? sa : " (error)");

                   SENDERR(EEXIST);

         }

 

         if(inet_addr_type((unsignedlong)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == RTN_LOCAL) {

                   extr->ips->ips_flags|= EMT_INBOUND;

         }

        

         /*XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/

         extr->ips->ips_rcvif= NULL;

        

         if((error = pfkey_ipsec_sa_init(extr->ips))) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_add_parse: "

                                "not successful for SA: %s,deleting.\n",

                                sa_len ? sa : " (error)");

                   SENDERR(-error);

         }

 

         extr->ips->ips_life.ipl_addtime.ipl_count= jiffies / HZ;

         if(!extr->ips->ips_life.ipl_allocations.ipl_count){

                  extr->ips->ips_life.ipl_allocations.ipl_count+= 1;

         }

        

         //構造消息頭structsadb_msg、struct sadb_sa、struct sadb_lifetime、struct sadb_address等,此部分構造消息方法和應用層是一樣的。

         if(!(pfkey_safe_build(error= pfkey_msg_hdr_build(&extensions_reply[0],

                                                                   SADB_ADD,

                                                                  satype,

                                                                   0,

                                                                   ((structsadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,

                                                                   ((structsadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),

                                  extensions_reply)

              && pfkey_safe_build(error =pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],

                                                                 SADB_EXT_SA,

                                                                 extr->ips->ips_said.spi,

                                                                 extr->ips->ips_replaywin,

                                                                 extr->ips->ips_state,

                                                                 extr->ips->ips_authalg,

                                                                 extr->ips->ips_encalg,

                                                                 extr->ips->ips_flags,

                                                                 extr->ips->ips_ref),

                                      extensions_reply)

              /* The 3 lifetime extentions should onlybe sent if non-zero. */

              &&(extensions[SADB_EXT_LIFETIME_HARD]

                    ? pfkey_safe_build(error =pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_HARD],

                                                                            SADB_EXT_LIFETIME_HARD,

                                                                            extr->ips->ips_life.ipl_allocations.ipl_hard,

                                                                            extr->ips->ips_life.ipl_bytes.ipl_hard,

                                                                            extr->ips->ips_life.ipl_addtime.ipl_hard,

                                                                            extr->ips->ips_life.ipl_usetime.ipl_hard,

                                                                            extr->ips->ips_life.ipl_packets.ipl_hard),

                                         extensions_reply) : 1)

              &&(extensions[SADB_EXT_LIFETIME_SOFT]

                    ? pfkey_safe_build(error =pfkey_lifetime_build(&extensions_reply[SADB_EXT_LIFETIME_SOFT],

                                                                            SADB_EXT_LIFETIME_SOFT,

                                                                            extr->ips->ips_life.ipl_allocations.ipl_soft,

                                                                            extr->ips->ips_life.ipl_bytes.ipl_soft,

                                                                            extr->ips->ips_life.ipl_addtime.ipl_soft,

                                                                            extr->ips->ips_life.ipl_usetime.ipl_soft,

                                                                            extr->ips->ips_life.ipl_packets.ipl_soft),

                                         extensions_reply) : 1)

              && pfkey_safe_build(error =pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],

                                                                      SADB_EXT_ADDRESS_SRC,

                                                                      0, /*extr->ips->ips_said.proto,*/

                                                                      0,

                                                                      extr->ips->ips_addr_s),

                                      extensions_reply)

              && pfkey_safe_build(error =pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],

                                                                      SADB_EXT_ADDRESS_DST,

                                                                      0, /*extr->ips->ips_said.proto,*/

                                                                      0,

                                                                      extr->ips->ips_addr_d),

                                      extensions_reply)

           &&(extr->ips->ips_ident_s.data

                 ? pfkey_safe_build(error =pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_SRC],

                                                             SADB_EXT_IDENTITY_SRC,

                                                                       extr->ips->ips_ident_s.type,

                                                                       extr->ips->ips_ident_s.id,

                                                             extr->ips->ips_ident_s.len,

                                                                       extr->ips->ips_ident_s.data),

                                   extensions_reply) : 1)

           && (extr->ips->ips_ident_d.data

                 ? pfkey_safe_build(error =pfkey_ident_build(&extensions_reply[SADB_EXT_IDENTITY_DST],

                                                             SADB_EXT_IDENTITY_DST,

                                                                       extr->ips->ips_ident_d.type,

                                                                       extr->ips->ips_ident_d.id,

                                                             extr->ips->ips_ident_d.len,

                                                                       extr->ips->ips_ident_d.data),

                                   extensions_reply) : 1)

                   )){

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_add_parse: "

                                "failed to build the add reply messageextensions\n");

                   SENDERR(-error);

         }

                  

         if((error= pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_add_parse: "

                                "failed to build the add replymessage\n");

                   SENDERR(-error);

         }

         //嚮應用層發送增加SA成功或失敗的消息。

         for(pfkey_socketsp= pfkey_open_sockets;

             pfkey_socketsp;

             pfkey_socketsp = pfkey_socketsp->next) {

                   if((error= pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {

                            KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_add_parse: "

                                         "sending up add reply message forsatype=%d(%s) to socket=0p%p failed with error=%d.\n",

                                         satype,

                                         satype2name(satype),

                                        pfkey_socketsp->socketp,

                                         error);

                            SENDERR(-error);

                   }

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_add_parse: "

                                "sending up add reply message forsatype=%d(%s) to socket=0p%p succeeded.\n",

                                satype,

                                satype2name(satype),

                                pfkey_socketsp->socketp);

         }

         //增加SA到sa哈希表中。

         if((error= ipsec_sa_add(extr->ips))) {

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_add_parse: "

                                "failed to add the mature SA=%s witherror=%d.\n",

                                sa_len ? sa : " (error)",

                                error);

                   SENDERR(-error);

         }

         extr->ips= NULL;

        

         KLIPS_PRINT(debug_pfkey,

                       "klips_debug:pfkey_add_parse: "

                       "successful for SA: %s\n",

                       sa_len ? sa : " (error)");

        

 errlab:

         if(pfkey_reply) {

                   pfkey_msg_free(&pfkey_reply);

         }

         pfkey_extensions_free(extensions_reply);

         returnerror;

}

pfkey_delete_parse()函數

DEBUG_NO_STATIC int

pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data*extr)

{

         structipsec_sa *ipsp;

         charsa[SATOT_BUF];

         size_tsa_len;

         interror = 0;

         structsadb_ext *extensions_reply[SADB_EXT_MAX+1];

         structsadb_msg *pfkey_reply = NULL;

         structsocket_list *pfkey_socketsp;

         uint8_tsatype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;

 

         KLIPS_PRINT(debug_pfkey,

                       "klips_debug:pfkey_delete_parse:.\n");

 

         pfkey_extensions_init(extensions_reply);

 

         if(!extr|| !extr->ips) {

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_delete_parse:"

                                "extr or extr->ips pointer NULL,fatal\n");

                   SENDERR(EINVAL);

         }

 

         sa_len= satot(&extr->ips->ips_said, 0, sa, sizeof(sa));

 

         spin_lock_bh(&tdb_lock);//加自旋鎖

 

         ipsp= ipsec_sa_getbyid(&(extr->ips->ips_said));

         if(ipsp == NULL) {

                   spin_unlock_bh(&tdb_lock);

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_delete_parse:"

                                "ipsec_sa not found for SA:%s, couldnot delete.\n",

                                sa_len ? sa : " (error)");

                   SENDERR(ESRCH);

         }

 

         ipsec_sa_put(ipsp);

         if((error= ipsec_sa_delchain(ipsp))){

                   spin_unlock_bh(&tdb_lock);

                   KLIPS_PRINT(debug_pfkey,

                                "klips_debug:pfkey_delete_parse:"

                                "error=%d returned trying to deleteipsec_sa for SA:%s.\n",

                                error,

                                sa_len ? sa : " (error)");

                   SENDERR(-error);

         }

         spin_unlock_bh(&tdb_lock);

 

         if(!(pfkey_safe_build(error= pfkey_msg_hdr_build(&extensions_reply[0],

                                                                   SADB_DELETE,

                                                                   satype,

                                                                   0,

                                                                   ((structsadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq,

                                                                   ((structsadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid),

                                  extensions_reply)

              && pfkey_safe_build(error =pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA],

                                                                 SADB_EXT_SA,

                                                                 extr->ips->ips_said.spi,

                                                                 0,

                                                                 0,

                                                                 0,

                                                                 0,

                                                                 0,

                                                                 extr->ips->ips_ref),

                                      extensions_reply)

              && pfkey_safe_build(error =pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC],

                                                                      SADB_EXT_ADDRESS_SRC,

                                                                      0, /*extr->ips->ips_said.proto,*/

                                                                      0,

                                                                      extr->ips->ips_addr_s),

                                      extensions_reply)

              && pfkey_safe_build(error =pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST],

                                                                      SADB_EXT_ADDRESS_DST,

                                                                      0, /*extr->ips->ips_said.proto,*/

                                                                      0,

                                                                      extr->ips->ips_addr_d),

                                      extensions_reply)

                   )){

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_delete_parse: "

                                "failed to build the delete replymessage extensions\n");

                   SENDERR(-error);

         }

        

         if((error= pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_delete_parse: "

                                "failed to build the delete replymessage\n");

                   SENDERR(-error);

         }

//嚮應用層發送刪除SA成功或失敗的消息。

         for(pfkey_socketsp= pfkey_open_sockets;

             pfkey_socketsp;

             pfkey_socketsp = pfkey_socketsp->next) {

                   if((error= pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) {

                            KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_delete_parse: "

                                         "sending up delete reply message forsatype=%d(%s) to socket=0p%p failed with error=%d.\n",

                                         satype,

                                         satype2name(satype),

                                         pfkey_socketsp->socketp,

                                         error);

                            SENDERR(-error);

                   }

                   KLIPS_PRINT(debug_pfkey,"klips_debug:pfkey_delete_parse: "

                                "sending up delete reply message forsatype=%d(%s) to socket=0p%p succeeded.\n",

                                satype,

                                satype2name(satype),

                                pfkey_socketsp->socketp);

         }

        

 errlab:

         if(pfkey_reply) {

                   pfkey_msg_free(&pfkey_reply);

         }

         pfkey_extensions_free(extensions_reply);

         returnerror;

}

 

ipsec_sa_delchain()函數

/*

  Theipsec_sa table better be locked before it is handed in, or races

 might happen

*/

int

ipsec_sa_delchain(struct ipsec_sa *ips)

{

         structipsec_sa *ipsdel;

         interror = 0;

       char sa[SATOT_BUF];

         size_tsa_len;

 

         if(ips== NULL) {

                   KLIPS_PRINT(debug_xform,

                                "klips_error:ipsec_sa_delchain: "

                                "null pointer passed in!\n");

                   return-ENODATA;

         }

 

         sa_len= satot(&ips->ips_said, 0, sa, sizeof(sa));

         KLIPS_PRINT(debug_xform,

                       "klips_debug:ipsec_sa_delchain: "

                       "passed SA:%s\n",

                       sa_len ? sa : " (error)");

         while(ips->ips_onext!= NULL) {

                   ips= ips->ips_onext;

         }

 

         while(ips){

                   /*XXX send a pfkey message up to advise of deleted ipsec_sa */

                   sa_len= satot(&ips->ips_said, 0, sa, sizeof(sa));

                   KLIPS_PRINT(debug_xform,

                               "klips_debug:ipsec_sa_delchain: "

                                "unlinking and delting SA:%s",

                                sa_len ? sa : " (error)");

                   ipsdel= ips;

                   ips= ips->ips_inext;

                   if(ips!= NULL) {

                            sa_len= satot(&ips->ips_said, 0, sa, sizeof(sa));

                            KLIPS_PRINT(debug_xform,

                                        ", inext=%s",

                                         sa_len ? sa : " (error)");

                            atomic_dec(&ipsdel->ips_refcount);

                            ipsdel->ips_inext= NULL;

                            atomic_dec(&ips->ips_refcount);

                            ips->ips_onext= NULL;

                   }

                   KLIPS_PRINT(debug_xform,

                                ".\n");

                   if((error= ipsec_sa_del(ipsdel))) {//從哈希表中刪除sa,之前已講過

                            KLIPS_PRINT(debug_xform,

                                         "klips_debug:ipsec_sa_delchain: "

                                         "ipsec_sa_del returned error%d.\n", -error);

                            returnerror;

                   }

                   if((error= ipsec_sa_wipe(ipsdel))){//釋放從哈希表中刪除的sa佔用的內存。

                            KLIPS_PRINT(debug_xform,

                                         "klips_debug:ipsec_sa_delchain: "

                                         "ipsec_sa_wipe returned error%d.\n", -error);

                            returnerror;

                   }

         }

         returnerror;

}

ipsec_sa_wipe()函數

int

ipsec_sa_wipe(struct ipsec_sa *ips)

{

         if(ips== NULL) {

                   return-ENODATA;

         }

 

         /*if(atomic_dec_and_test(ips)) {

         };*/

 

#if IPSEC_SA_REF_CODE

         /*remove me from the SArefTable */

         {

                   charsa[SATOT_BUF];

                   size_tsa_len;

                   sa_len= satot(&ips->ips_said, 0, sa, sizeof(sa));

                   KLIPS_PRINT(debug_xform,

                                "klips_debug:ipsec_sa_wipe: "

                                "removing SA=%s(0p%p), SAref=%d,table=%d(0p%p), entry=%d from the refTable.\n",

                                sa_len ? sa : " (error)",

                                ips,

                                ips->ips_ref,

                                IPsecSAref2table(IPsecSA2SAref(ips)),

                               ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))],

                                IPsecSAref2entry(IPsecSA2SAref(ips)));

         }

         if(ips->ips_ref== IPSEC_SAREF_NULL) {

                   KLIPS_PRINT(debug_xform,

                                "klips_debug:ipsec_sa_wipe: "

                                "why does this SA not have a validSAref?.\n");

         }

         ipsec_sadb.refTable[IPsecSAref2table(IPsecSA2SAref(ips))]->entry[IPsecSAref2entry(IPsecSA2SAref(ips))]= NULL;

         ips->ips_ref= IPSEC_SAREF_NULL;

         ipsec_sa_put(ips);

#endif /* IPSEC_SA_REF_CODE */

 

         /*paranoid clean up */

         if(ips->ips_addr_s!= NULL) {

                   memset((caddr_t)(ips->ips_addr_s),0, ips->ips_addr_s_size);

                   kfree(ips->ips_addr_s);

         }

         ips->ips_addr_s= NULL;

 

         if(ips->ips_addr_d!= NULL) {

                   memset((caddr_t)(ips->ips_addr_d),0, ips->ips_addr_d_size);

                   kfree(ips->ips_addr_d);

         }

         ips->ips_addr_d= NULL;

 

         if(ips->ips_addr_p!= NULL) {

                   memset((caddr_t)(ips->ips_addr_p),0, ips->ips_addr_p_size);

                   kfree(ips->ips_addr_p);

         }

         ips->ips_addr_p= NULL;

 

#ifdef CONFIG_IPSEC_NAT_TRAVERSAL

         if(ips->ips_natt_oa){

                   memset((caddr_t)(ips->ips_natt_oa),0, ips->ips_natt_oa_size);

                   kfree(ips->ips_natt_oa);

         }

         ips->ips_natt_oa= NULL;

#endif

 

         if(ips->ips_key_a!= NULL) {

                   memset((caddr_t)(ips->ips_key_a),0, ips->ips_key_a_size);

                   kfree(ips->ips_key_a);

         }

         ips->ips_key_a= NULL;

 

         if(ips->ips_key_e!= NULL) {

                   if(ips->ips_alg_enc &&

                       ips->ips_alg_enc->ixt_e_destroy_key)

                   {

                            ips->ips_alg_enc->ixt_e_destroy_key(ips->ips_alg_enc,

                                                                     ips->ips_key_e);

                   }else

                   {

                            memset((caddr_t)(ips->ips_key_e),0, ips->ips_key_e_size);

                            kfree(ips->ips_key_e);

                   }

         }

         ips->ips_key_e= NULL;

 

         if(ips->ips_iv!= NULL) {

                   memset((caddr_t)(ips->ips_iv),0, ips->ips_iv_size);

                   kfree(ips->ips_iv);

         }

         ips->ips_iv= NULL;

 

         if(ips->ips_ident_s.data!= NULL) {

                   memset((caddr_t)(ips->ips_ident_s.data),

                      0,

                          ips->ips_ident_s.len *IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident));

                   kfree(ips->ips_ident_s.data);

       }

         ips->ips_ident_s.data= NULL;

        

         if(ips->ips_ident_d.data!= NULL) {

                   memset((caddr_t)(ips->ips_ident_d.data),

                       0,

                          ips->ips_ident_d.len *IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident));

                   kfree(ips->ips_ident_d.data);

       }

         ips->ips_ident_d.data= NULL;

 

         if(ips->ips_alg_enc||ips->ips_alg_auth) {

                   ipsec_alg_sa_wipe(ips);

         }

        

         memset((caddr_t)ips,0, sizeof(*ips));

         kfree(ips);

         ips= NULL;

 

         return0;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章