This commits adds the following:
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / netapi_sec.c
1 /**************************************************************
2  * FILE PURPOSE :  NETAPI SECURITY CONFIGURATION-
3  *         user space access to security transport resources on SOC
4  **************************************************************
5  * @file netapi_sec.c
6  * 
7  * @brief DESCRIPTION:  netapi security cfg file for user space transport
8  *               library
9  * 
10  * REVISION HISTORY:
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2013
13  * 
14  *  Redistribution and use in source and binary forms, with or without 
15  *  modification, are permitted provided that the following conditions 
16  *  are met:
17  *
18  *    Redistributions of source code must retain the above copyright 
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  *    Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the 
23  *    documentation and/or other materials provided with the   
24  *    distribution.
25  *
26  *    Neither the name of Texas Instruments Incorporated nor the names of
27  *    its contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *****************************************************************************/
43 #include "netapi_sec.h"
46 /********************************************************************
47  * FUNCTION PURPOSE:  API to add an IPSEC SA
48  ********************************************************************
49  * DESCRIPTION:  API to add an IPSEC SA
50  ********************************************************************/
51 NETCP_CFG_SA_T netapi_secAddSA(NETAPI_T h,
52                                int iface_no,
53                                NETAPI_SEC_SA_INFO_T *sa_info,
54                                nwalSecKeyParams_t * key_params,
55                                int inflow_mode,
56                                NETCP_CFG_ROUTE_HANDLE_T  route,
57                                void **p_data_mode_handle,
58                                void **p_inflow_mode_handle,
59                                void * p_user_data,
60                                int * perr)
61 {
62     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
63     nwal_RetValue       retValue;
64     NetapiNwalTransInfo_t *pTransInfo;
65     nwal_TransID_t     trans_id;
66     unsigned int appId = NETAPI_NETCP_MATCH_IPSEC | iface_no;
67     int tunnelId;
68     nwalSaIpSecId_t  saInfo;
69     int have_to_wait=1;
70     nwalTxDmPSCmdInfo_t     dmPSCmdInfo;
71     nwalSaIpSecId_t nwalSaIpSecId;
72     uint32_t    swInfo0;
73     uint32_t    swInfo1;
75     nwalCreateSAParams_t    createParam =
76     {
77         /* mac handle */
78         NULL,  //to be filled in
79         4,
80         /*nwalSaIpSecParam_t */
81             {
82                 0,/* validParams */
83                 nwal_SA_MODE_TUNNEL,  //update from input
84                 64,/* replayWindow */\
85                 NWAL_SA_DIR_INBOUND,
86                 0,
87                 0,
88                 NWAL_SA_AALG_HMAC_SHA1,/* update from input */
89                 NWAL_SA_EALG_AES_CTR,  /* update from input */
90                 { 0x00},      /* remMacAddr:  NA */
91                 12,             /* update from input, mac size */
92                 NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,/* Continue parsing to next route for match */
93                 NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,/* For next route fail action by default is route to host */
94                 CPPI_PARAM_NOT_SPECIFIED,         /* Use default flow configured to NWAL  if packet is routed to host */
95                 QMSS_PARAM_NOT_SPECIFIED          /* Use default queue configured to NWAL if packet is routed to host */
96            },
97            /* nwalSaIpSecKeyParams_t */
98            {0}
99     };
102     void * mac_handle = netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context,iface_no);
103     *perr =0;
104     if ((!n) || (!sa_info)  ||  (!p_data_mode_handle))
105     {
106         *perr = NETAPI_ERR_BAD_INPUT;
107         return -1;
108     }
110     /* reserve a slot */
111     tunnelId = netapip_netcpCfgFindSaSlot(&netapi_get_global()->nwal_context,
112                            iface_no);
114     if (tunnelId <0)
115     {
116         *perr= NETAPI_ERR_NOMEM;
117         return -1;
118     }
119     appId |=  (tunnelId << NETAPI_NETCP_MATCH_ID_SHIFT);
120     netapi_Log("netapi_secAddSA: app id: 0x%x\n", appId);
122     *p_data_mode_handle= NULL;  
123     *p_inflow_mode_handle= NULL;
127     if (inflow_mode & NETAPI_SEC_SA_INFLOW)
128     {
129         pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
130         if (!pTransInfo)
131         {
132             *perr =  NETAPI_ERR_BUSY;
133             netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
134             return -1;
135         }
136         pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA;
137         pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
138         pTransInfo->inUse = nwal_TRUE;
139         pTransInfo->netapi_handle = h;
141         /* build SA parameters */
142         saInfo.spi = sa_info->spi;
143         memcpy(&saInfo.dst, &sa_info->dst, sizeof( nwalIpAddr_t));
144         memcpy(&saInfo.src, &sa_info->src, sizeof( nwalIpAddr_t));
145         saInfo.proto = sa_info->proto;
146         createParam.macHandle = mac_handle;
147         createParam.ipType = sa_info->ipType;
148         createParam.saIpSecParam.dir = sa_info->dir;
149         createParam.saIpSecParam.saMode = sa_info->saMode;
150         createParam.saIpSecParam.replayWindow = sa_info->replayWindow;
151         createParam.saIpSecParam.authMode = sa_info->authMode;
152         createParam.saIpSecParam.cipherMode = sa_info->cipherMode;
153         createParam.saIpSecParam.esnLo = sa_info->esnLo;
154         createParam.saIpSecParam.esnHi = sa_info->esnHi;
155         if ((sa_info->cipherMode == NWAL_SA_EALG_AES_GCM) ||
156             (sa_info->cipherMode == NWAL_SA_EALG_AES_CCM) ||
157             (sa_info->authMode == NWAL_SA_AALG_GMAC)      ||
158             (sa_info->authMode == NWAL_SA_AALG_HMAC_SHA2_256_RFC4868))
159         {
160             createParam.saIpSecParam.macSize = 16;
161         }
162         if  ((sa_info->authMode == NWAL_SA_AALG_NULL) && 
163             (!((sa_info->cipherMode == NWAL_SA_EALG_AES_GCM) || 
164                (sa_info->cipherMode == NWAL_SA_EALG_AES_CCM))))
165         {
166             createParam.saIpSecParam.replayWindow = 0;
167             createParam.saIpSecParam.macSize = 0;
168         }
169         memcpy(&createParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
171         if (route != NULL)
172         {
173             netapip_netcpCfgBuildRoute(route,&createParam.saIpSecParam.appRxPktFlowId, 
174                                          &createParam.saIpSecParam.appRxPktQueue);
175         }
177         /* fire off config message */
178         retValue = nwal_setSecAssoc (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
179                                         trans_id,
180                                         (nwal_AppId) appId,
181                                         &saInfo,
182                                         &createParam,
183                                         &pTransInfo->handle);
184         if(retValue == nwal_TRANS_COMPLETE)
185         {
186             have_to_wait=0;
187         }
188         else if(retValue !=  nwal_OK)
189         {
190             *perr = NETAPI_ERR_NWAL_ERR0;
191             netapip_freeTransInfo(pTransInfo);
192             netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
193             return -1;
194         }
196         if((trans_id != NWAL_TRANSID_SPIN_WAIT)&&(have_to_wait))
197         {
198             n->nwal_local.numPendingCfg++;
199             while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
200                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
201             {
202                 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
203             }
204             if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
205             {
206                 pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
207                 pTransInfo->inUse = nwal_FALSE;
208                 *perr = NETAPI_ERR_PA_FW;
209                 netapi_Log ("netapi_sec - ERROR returned by NETCP PA firmware %d\n",
210                         *perr);
211                 netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
212                 return -1;
213             }
214         }
216         *p_inflow_mode_handle=pTransInfo->handle;
217         netapip_freeTransInfo(pTransInfo);
219         if (sa_info->dir == NWAL_SA_DIR_OUTBOUND)
220         {
221             memset(&nwalSaIpSecId, 0, sizeof(nwalSaIpSecId_t));
222             nwalSaIpSecId.spi = sa_info->spi;
223             memcpy(&(nwalSaIpSecId.src), &sa_info->src,sizeof( nwalIpAddr_t));
224             memcpy(&(nwalSaIpSecId.dst), &sa_info->dst,sizeof( nwalIpAddr_t));
225             nwalSaIpSecId.proto = sa_info->proto;
226             if (nwal_getSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
227                                      &nwalSaIpSecId, 
228                                      NWAL_SA_DIR_OUTBOUND,
229                                      p_inflow_mode_handle,
230                                      &swInfo0,
231                                      &swInfo1) == nwal_TRUE)
232             {
233                 //netapi_Log("netapisecAddSA swInfo0: 0x%x, swInfo1: 0x%x\n", swInfo0, swInfo1);
234             }
235             else
236                 netapi_Log("netapisecAddSA: call to nwal_getSecAssoc() returned error\n");
237         }
238     }
240     /* sideband mode */
241     if (inflow_mode &NETAPI_SEC_SA_SIDEBAND)
242     {
243         nwalCreateDmSAParams_t  dmSaParam;
244         void * dm_handle;
245         memset(&dmSaParam,0,sizeof(nwalCreateDmSAParams_t));
246         dmSaParam.dmSaParam.dmChnType= (sa_info->dir==NWAL_SA_DIR_INBOUND)?  NWAL_DM_CHAN_DECRYPT: NWAL_DM_CHAN_ENCRYPT; /**direction*/ 
247         dmSaParam.dmSaParam.replayWindow=sa_info->replayWindow;
248         dmSaParam.dmSaParam.authMode=sa_info->authMode;
249         dmSaParam.dmSaParam.cipherMode=sa_info->cipherMode;
250         dmSaParam.dmSaParam.macSize=12;
251         dmSaParam.dmSaParam.aadSize=0;
252         dmSaParam.dmSaParam.enc1st =  (sa_info->dir ==NWAL_SA_DIR_OUTBOUND) ? nwal_TRUE : nwal_FALSE;  //encypt 1st for outbound
253         if ((sa_info->cipherMode == NWAL_SA_EALG_AES_GCM) ||
254             (sa_info->cipherMode == NWAL_SA_EALG_AES_CCM) ||
255             (sa_info->authMode == NWAL_SA_AALG_GMAC))
256         {
257             dmSaParam.dmSaParam.macSize = 16;
258             dmSaParam.dmSaParam.aadSize=8;
259             /* Enc1st needs to always be true for combined mode algorithms */
260             dmSaParam.dmSaParam.enc1st = nwal_TRUE;
261         }
262        else
263         {
264             dmSaParam.dmSaParam.macSize=12;
265             dmSaParam.dmSaParam.aadSize=0;
266         }
268        if  (sa_info->authMode == NWAL_SA_AALG_NULL)
269        {
270             dmSaParam.dmSaParam.enc1st = nwal_TRUE;
271        }
272         /* todo; allow app q for Sideband return */
273         memcpy(&dmSaParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
274         retValue = nwal_setDMSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
275                                   (nwal_AppId)appId,
276                                   &dmSaParam,
277                                   &dm_handle);
278         if(retValue != nwal_OK)
279         {
280             *perr = NETAPI_ERR_NWAL_ERR0;
281             netapi_Log ("netapi_secAddSA: nwal_setDMSecAssoc() returned Error Code %d\n",
282             retValue);
283             netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
284             return -1;
285         }
287         //netapi_Log("netapi_secAddSA: Creating sideband mode SA for %d ( mac %d)\n", tunnelId, iface_no); 
288         *p_data_mode_handle = dm_handle;
289         memset(&dmPSCmdInfo, 0, sizeof(nwalTxDmPSCmdInfo_t));
290         retValue =  nwal_initDMPSCmdInfo(netapip_returnNwalInstanceHandle(h),
291                                          *p_data_mode_handle,
292                                          &dmPSCmdInfo); 
293     }
295     netapip_netcpCfgInsertSa(&netapi_get_global()->nwal_context,
296                           tunnelId,
297                           (sa_info->dir ==   NWAL_SA_DIR_INBOUND) ? TRUE: FALSE,
298                           inflow_mode,
299                           &saInfo, &createParam,
300                           *p_inflow_mode_handle,
301                           *p_data_mode_handle,
302                           &dmPSCmdInfo,
303                           swInfo0,
304                           swInfo1,
305                           p_user_data);
306     return  (appId);
309 /********************************************************************
310  * FUNCTION PURPOSE:  Internal function  to dynamically switch between inflow
311  *                                  and sideband mode
312  ********************************************************************
313  * DESCRIPTION:  Internal function  to dynamically switch between inflow
314  *                                  and sideband mode
315  ********************************************************************/
316 void netapi_secInflowMode(int iface,
317                           NETCP_CFG_SA_T sa,
318                           int on)
320     /* NOT_IMPLEMENTED */
321     netapi_Log("netapi_secInflowMode:  dynamic switch between inflow and sideband is NOT_IMPLEMENTED\n");
324 /********************************************************************
325  * FUNCTION PURPOSE:  Internal function  to delete an IPSEC SA
326  ********************************************************************
327  * DESCRIPTION:  Internal function to delete an IPSEC SA
328  ********************************************************************/
329 static void netapi_secDelSA_internal(NETAPI_T h,
330                                      int iface_no,
331                                      NETCP_CFG_SA_T sa_app_id,
332                                      int flags,
333                                      int *perr)
335     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
336     nwal_RetValue       retValue;
337     NetapiNwalTransInfo_t *pTransInfo;
338     nwal_TransID_t     trans_id;
339     int tunnelId = (sa_app_id >> NETAPI_NETCP_MATCH_ID_SHIFT) &NETAPI_NETCP_MATCH_ID_MASK;
340     void * handle_inflow;
341     void * handle_sideband;
342     int have_to_wait = 1;
344     handle_inflow = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,
345                                           tunnelId, &handle_sideband);
346     *perr =0;
348     if(handle_inflow)
349     {
350     /* get a transaction id */
351         pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
352         if (!pTransInfo)
353         {
354             *perr =  NETAPI_ERR_BUSY;
355             return;
356         }
357         pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA;
358         pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
359         pTransInfo->inUse = nwal_TRUE;
360         pTransInfo->netapi_handle = h;
362         retValue = nwal_delSecAssoc(
363                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
364                 trans_id,
365                 handle_inflow);
366         if(retValue == nwal_TRANS_COMPLETE)
367         {
368            have_to_wait=0;
369         }
370         else if(retValue !=  nwal_OK)
371         {
372                 *perr = NETAPI_ERR_NWAL_ERR0;
373                 netapi_Log ("netcp_cfg - ERROR: netapi_secDelSA_internal returned Error Code %d\n",
374                             retValue);
375                 netapip_freeTransInfo(pTransInfo);
376                 netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
377         }
378         if((trans_id != NWAL_TRANSID_SPIN_WAIT)&&(have_to_wait))
379         {
380             n->nwal_local.numPendingCfg++;
382             while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
383                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
384             {
385                 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
386             }
387             if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
388             {
389                 netapip_freeTransInfo(pTransInfo);
390                 *perr = NETAPI_ERR_PA_FW;
391                  if (!flags) 
392                     netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context, tunnelId);
393                 netapi_Log ("netapi_sec - ERROR returned by NETCP PA firmware %d\n",
394                         *perr);
395                 return;
396            }
397         }
398         netapi_Log ("netapi sec: inflow tunnel %d (iface %d) deleted\n",tunnelId,iface_no);
399         netapip_freeTransInfo(pTransInfo);
400     }
401     if (handle_sideband)
402     {
403         retValue=nwal_delDMSecAssoc( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
404                                     handle_sideband);
405         if(retValue !=  nwal_OK)
406         {
407             *perr = NETAPI_ERR_NWAL_ERR0;
408              netapi_Log ("netapi_sec  - ERROR: nwal_delDMSA returned Error Code %d\n",
409                     retValue);
411         }
412         else 
413             netapi_Log("netapi_sec: Sideband SA deleted\n");
414     }
415    
416     /* zap the entry */
417     if (!flags)
418         netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context, tunnelId);
421 /********************************************************************
422  * FUNCTION PURPOSE:  API to delete an IPSEC SA
423  ********************************************************************
424  * DESCRIPTION:  API to delete an IPSEC SA
425  ********************************************************************/
426 void netapi_secDelSA(NETAPI_T h,
427                      int iface_no,
428                      NETCP_CFG_SA_T sa_app_id,
429                      int *perr)
431     netapi_secDelSA_internal( h, iface_no,  sa_app_id, 0x00, perr);
435 /********************************************************************
436  * FUNCTION PURPOSE:  API to add a receive security policy
437  ********************************************************************
438  * DESCRIPTION:  API to add a receive security policy
439  ********************************************************************/
440 NETCP_CFG_IPSEC_POLICY_T netapi_secAddRxPolicy(NETAPI_T h, 
441                                                NETCP_CFG_SA_T sa,
442                                                nwal_IpType ipType,
443                                                nwalIpAddr_t * src_ip_addr,
444                                                nwalIpAddr_t * dst_ip_addr,
445                                                nwalIpOpt_t * ip_qualifiers,
446                                                NETCP_CFG_ROUTE_HANDLE_T  route,
447                                                void * user_data,
448                                                int * perr)
450     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
451     nwal_RetValue       retValue;
452     NetapiNwalTransInfo_t *pTransInfo;
453     nwal_TransID_t     trans_id;
454     unsigned int appId = NETAPI_NETCP_MATCH_IPSEC_POLICY | (sa& NETAPI_NETCP_MATCH_ID_MASK);
455     int policyId;
456     int tunnelId= netapi_cfgGetMatchId(sa);
457     void * blah;
458     int iface_no = netapi_cfgGetMatchLogicalMacIface(sa);
460     nwalSecPolParams_t createParam =
461     {
462         0,  /* handle */
463         NWAL_SA_DIR_INBOUND,
464         4,      /* IP Type */
465         {0},  /* dst */
466         {0},  /* src */
467         {0 },/* IP Options */
468         NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
469         NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
470         CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
471         QMSS_PARAM_NOT_SPECIFIED                     /* Use default queue configured to NWAL if packet is routed to host */
472     };
474     void * sa_handle = NULL;
475     *perr =0;
476     
477     if ((!n) )
478     {
479         *perr = NETAPI_ERR_BAD_INPUT;
480         return -1;
481     }
483     sa_handle = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,tunnelId,&blah);
484     if (!sa_handle)
485     {
486         *perr = NETAPI_ERR_BAD_INPUT;
487         return -1;
488     }
490     /* get a transaction id */
491     pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
492     if (!pTransInfo)
493     {
494         *perr =  NETAPI_ERR_BUSY;
495         return -1;
496     }
497     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY;
498     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
499     pTransInfo->inUse = nwal_TRUE;
500     pTransInfo->netapi_handle = h;
501     createParam.handle = sa_handle;
502     createParam.ipType = ipType;
503     if (dst_ip_addr) memcpy(&createParam.dst, dst_ip_addr, sizeof(nwalIpAddr_t)); 
504     if (src_ip_addr) memcpy(&createParam.src, src_ip_addr, sizeof(nwalIpAddr_t)); 
505     if (ip_qualifiers) memcpy(&createParam.ipOpt,ip_qualifiers ,sizeof(nwalIpOpt_t));
506     if (route != NULL)
507     {
508         netapip_netcpCfgBuildRoute(route,&createParam.appRxPktFlowId,
509                                      &createParam.appRxPktQueue);
510     }
511     /* reserve a slot */
512     policyId = netapip_netcpCfgFindPolicySlot(&netapi_get_global()->nwal_context,
513                            tunnelId);
514     if (policyId <0) 
515     {
516         *perr= NETAPI_ERR_NOMEM;
517         netapip_freeTransInfo(pTransInfo);
518         return -1;
519     }
520     appId |=  (policyId<<8);
522     /* fire off config message */
523     retValue = nwal_setSecPolicy (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
524                                   trans_id,
525                                   (nwal_AppId) appId,
526                                   &createParam,
527                                   &pTransInfo->handle);
528     if(retValue !=  nwal_OK)
529     {
530         *perr = NETAPI_ERR_NWAL_ERR0;
531         netapi_Log ("netapi sec - ERROR: nwal_setPolicy returned Error Code %d\n",
532                     retValue);
533         netapip_freeTransInfo(pTransInfo);
534         
535         netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context,policyId);
536         return -1;
537     }
539     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
540     {
541         n->nwal_local.numPendingCfg++;
542         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
543                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
544         {
545             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
546         }
547         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
548         {
549             netapip_freeTransInfo(pTransInfo);
550             *perr = NETAPI_ERR_PA_FW;
551             netapi_Log ("netapi_sec - ERROR2: netapi_secAddRxPolicy returned Error Code %d\n",
552                     *perr);
553             netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context,policyId);
554             return -1;
555         }
556     }
557     netapi_Log ("netapi sec: SA %d added to tunnel %d  mac %d\n", policyId, tunnelId, iface_no);
559     /* save stuff */
560     netapip_netcpCfgInsertPolicy(&netapi_get_global()->nwal_context,
561                            policyId,
562                           (void *) pTransInfo->handle,
563                           user_data);
564     netapip_freeTransInfo(pTransInfo);
565     return  (appId);
568 /********************************************************************
569  * FUNCTION PURPOSE:  Internal function to delete a receive security policy
570  ********************************************************************
571  * DESCRIPTION:  Internal function to delete a receive security policy
572  ********************************************************************/
573 static void netapi_secDelRxPolicy_internal(NETAPI_T h,
574                                            NETCP_CFG_IPSEC_POLICY_T policy_app_id,
575                                            int flags,
576                                            int *perr)
578     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
579     nwal_RetValue       retValue;
580     NetapiNwalTransInfo_t *pTransInfo;
581     nwal_TransID_t     trans_id;
582     int policyId = netapi_cfgGetMatchId(policy_app_id);
583     void * handle_policy=NULL;
585     handle_policy = netapip_netcpCfgGetPolicy(&netapi_get_global()->nwal_context,policyId);
586                                           ;
587     if (!handle_policy)
588     {
589         *perr = NETAPI_ERR_BAD_INPUT;
590         goto ERR_netapi_secDelRxPolicy_internal;
591      }
592     *perr =0;
594     /* get a transaction id */
595     pTransInfo = netapip_getFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
596     if (!pTransInfo)
597     {
598         *perr =  NETAPI_ERR_BUSY;
599         goto ERR_netapi_secDelRxPolicy_internal;
600     }
601     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY;
602     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
603     pTransInfo->inUse = nwal_TRUE;
604     pTransInfo->netapi_handle = h;
606     /* issue request */
607     retValue = nwal_delSecPolicy(
608                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
609                 trans_id,
610                 handle_policy);
611     if(retValue !=  nwal_OK)
612     {
613         *perr = NETAPI_ERR_NWAL_ERR0;
614         netapi_Log ("netapi sec - ERROR: netapi_secDelRxPolicy_internal returned Error Code %d\n",
615                     retValue);
616         netapip_freeTransInfo(pTransInfo);
617         goto ERR_netapi_secDelRxPolicy_internal;
618     }
620     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
621     {
622         n->nwal_local.numPendingCfg++;
623         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
624                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
625         {
626             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
627         }
628         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
629         {
630             netapip_freeTransInfo(pTransInfo);
631             *perr = NETAPI_ERR_PA_FW;
632             netapi_Log ("netapi_sec - ERROR2: netapi_secDelRxPolicy_internal returned Error Code %d\n",
633                     *perr);
634             //zap the entry
635             if (!flags)
636                 netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context, policyId);
637             goto ERR_netapi_secDelRxPolicy_internal;
638             
639         }
640     }
641     netapi_Log ("netapi sec: policy %d (iface %d) deleted\n",policyId,(policy_app_id&0xff));
642     netapip_freeTransInfo(pTransInfo);
643     /* zap the entry */
644     if (!flags)
645     {
646         netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context, policyId);
647     }
648 ERR_netapi_secDelRxPolicy_internal:
649     return;
652 /********************************************************************
653  * FUNCTION PURPOSE:  API to delete a receive security policy
654  ********************************************************************
655  * DESCRIPTION:  API to delete a receive security policy
656  ********************************************************************/
657 void netapi_secDelRxPolicy(NETAPI_T h,
658                            NETCP_CFG_IPSEC_POLICY_T policy_app_id,
659                            int *perr)
661     netapi_secDelRxPolicy_internal(h,  policy_app_id, 0, perr);
664 /********************************************************************
665  * FUNCTION PURPOSE:  API to retrieve SA statistics via NWAL
666  ********************************************************************
667  * DESCRIPTION:  API to retrieve SA statistics via NWAL
668  ********************************************************************/
669 void  netapi_getSaStats (NETAPI_T               h, 
670                          NETCP_CFG_SA_T         handle,
671                          NETAPI_SA_STATS_T*     pSaStats)
673     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
674     void * handle_inflow;
675     void * handle_sideband;
676     int tunnelId = (handle >>8) &0xffff;
677     int have_to_wait = 1;
678     handle_inflow = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,
679                                           tunnelId, &handle_sideband);
680     if(handle_inflow)
681     {
682         nwal_getSecAssocStats(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, 
683                                                 handle_inflow, &(pSaStats->saIpsecStats));
684         pSaStats->validParams |= NETAPI_IPSEC_STAT_VALID;
685     }
686     if(handle_sideband)
687     {
688         nwal_getDataModeStats(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, 
689                                                 handle_sideband, &(pSaStats->dataModeStats));
690         pSaStats->validParams |= NETAPI_SIDEBAND_DATA_MODE_STAT_VALID;
691     }