]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/netapi.git/blob - ti/runtime/netapi/src/netapi_sec.c
netlib: set SA by IP rule.
[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.h"
45 NETAPI_SA_INFO_LOCAL_T netapi_sa_db[TUNE_NETAPI_MAX_SA];
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_secAddSAInternal(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                                        NETCP_CFG_IP_T ip_rule,
61                                        int * perr)
62 {
63     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
64     nwal_RetValue       retValue;
65     NetapiNwalTransInfo_t *pTransInfo;
66     nwal_TransID_t     trans_id;
67     unsigned int appId = NETAPI_NETCP_MATCH_IPSEC | iface_no;
68     int tunnelId;
69     nwalSaIpSecId_t  saInfo;
70     int have_to_wait=1;
71     nwalTxDmPSCmdInfo_t     dmPSCmdInfo;
72     nwalSaIpSecId_t nwalSaIpSecId;
73     uint32_t    swInfo0 = 0;
74     uint32_t    swInfo1 = 0;
75     int sa_db_slot;
76     int free_sa_db_slot = 0;
77     int ip_slot = 0;
78     void * handle;
79     nwalCreateSAParams_t    createParam =
80     {
81         /* mac handle */
82         NULL,  //to be filled in
83         4,
84         /*nwalSaIpSecParam_t */
85             {
86                 0,/* validParams */
87                 nwal_SA_MODE_TUNNEL,  //update from input
88                 64,/* replayWindow */\
89                 NWAL_SA_DIR_INBOUND,
90                 0,
91                 0,
92                 NWAL_SA_AALG_HMAC_SHA1,/* update from input */
93                 NWAL_SA_EALG_AES_CTR,  /* update from input */
94                 { 0x00},      /* remMacAddr:  NA */
95                 12,             /* update from input, mac size */
96                 NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,/* Continue parsing to next route for match */
97                 NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,/* For next route fail action by default is route to host */
98                 CPPI_PARAM_NOT_SPECIFIED,         /* Use default flow configured to NWAL  if packet is routed to host */
99                 QMSS_PARAM_NOT_SPECIFIED,         /* Use default queue configured to NWAL if packet is routed to host */
100                 0                                 /* route type */
101            },
102            /* nwalSaIpSecKeyParams_t */
103            {0}
104     };
106     /* Get IP slot for IP rule. */
107     if (ip_rule)
108     {
109         ip_slot = netapi_cfgGetMatchId(ip_rule);
110         handle = netapip_netcpCfgGetIpHandle(&netapi_get_global()->nwal_context,iface_no,ip_slot);
111     }
112     else
113     {
114         handle = netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context,iface_no);
115     }
117     *perr =NETAPI_ERR_OK;
118     if ((!n) || (!sa_info)  ||  (!p_data_mode_handle))
119     {
120         *perr = NETAPI_ERR_BAD_INPUT;
121         return -1;
122     }
124     /* prior to building table, will need to store SA entry in local database,
125      * and make sure this SA has not been already offloaded, if already off-loaded,
126      * just return app_id associated with the SA */
128     for(sa_db_slot=0; sa_db_slot < TUNE_NETAPI_MAX_SA; sa_db_slot++)
129     {
130         if (netapi_sa_db[sa_db_slot].inUse)
131         {
132             if (sa_info->ipType == nwal_IPV4)
133             {
134                 if (netapi_sa_db[sa_db_slot].spi != sa_info->spi)
135                     continue;
136                 if(memcmp(&netapi_sa_db[sa_db_slot].dst.ipv4,
137                           &sa_info->dst.ipv4, sizeof(sa_info->dst.ipv4)))
138                     continue;
140                 netapi_sa_db[sa_db_slot].ref_count++;
141                 return netapi_sa_db[sa_db_slot].app_id;
142             }
143             else if (sa_info->ipType == nwal_IPV6)
144             {
145                 if (netapi_sa_db[sa_db_slot].spi != sa_info->spi)
146                     continue;
147                 if(memcmp(&netapi_sa_db[sa_db_slot].dst.ipv6,
148                           &sa_info->dst.ipv6, sizeof(sa_info->dst.ipv6)))
149                     continue;
151                 netapi_sa_db[sa_db_slot].ref_count++;
152                 return netapi_sa_db[sa_db_slot].app_id;
153             }
154             else
155             {
156                 *perr = NETAPI_ERR_BAD_INPUT;
157                 return -1;
158             }
159         }
160         else
161         {
162             /* found free slot */
163             free_sa_db_slot = sa_db_slot;
164         }
165     }
166     saInfo.spi = sa_info->spi;
168     memcpy(&saInfo.dst, &sa_info->dst, sizeof( nwalIpAddr_t));
169     
170     /* reserve a slot */
171     tunnelId = netapip_netcpCfgFindSaSlot(n,
172                                           &netapi_get_global()->nwal_context,
173                                           iface_no);
175     if (tunnelId <0)
176     {
177         *perr= NETAPI_ERR_NOMEM;
178         return -1;
179     }
180     appId |=  (tunnelId << NETAPI_NETCP_MATCH_ID_SHIFT);
182     *p_data_mode_handle= NULL;  
183     *p_inflow_mode_handle= NULL;
187     if (inflow_mode & NETAPI_SEC_SA_INFLOW)
188     {
189         pTransInfo = netapip_getFreeTransInfo(n,
190                                               (NETAPI_PROC_GLOBAL_T *) n->proc_global,
191                                                &trans_id);
192         if (!pTransInfo)
193         {
194             *perr =  NETAPI_ERR_BUSY;
195             netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
196             return -1;
197         }
198         pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA;
199         pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
200         pTransInfo->inUse = nwal_TRUE;
201         pTransInfo->netapi_handle = h;
203         /* build SA parameters */
204         saInfo.spi = sa_info->spi;
205         memcpy(&saInfo.dst, &sa_info->dst, sizeof( nwalIpAddr_t));
206         memcpy(&saInfo.src, &sa_info->src, sizeof( nwalIpAddr_t));
207         saInfo.proto = sa_info->proto;
208         createParam.handle = handle;
209         createParam.ipType = sa_info->ipType;
210         createParam.saIpSecParam.dir = sa_info->dir;
211         createParam.saIpSecParam.saMode = sa_info->saMode;
212         createParam.saIpSecParam.replayWindow = sa_info->replayWindow;
213         createParam.saIpSecParam.authMode = sa_info->authMode;
214         createParam.saIpSecParam.cipherMode = sa_info->cipherMode;
215         createParam.saIpSecParam.esnLo = sa_info->esnLo;
216         createParam.saIpSecParam.esnHi = sa_info->esnHi;
217         if ((sa_info->cipherMode == NWAL_SA_EALG_AES_GCM) ||
218             (sa_info->cipherMode == NWAL_SA_EALG_AES_CCM) ||
219             (sa_info->authMode == NWAL_SA_AALG_GMAC)      ||
220             (sa_info->authMode == NWAL_SA_AALG_HMAC_SHA2_256)      ||
221             (sa_info->authMode == NWAL_SA_AALG_HMAC_SHA2_256_RFC4868))
222         {
223             createParam.saIpSecParam.macSize = 16;
224         }
225         if  ((sa_info->authMode == NWAL_SA_AALG_NULL) && 
226             (!((sa_info->cipherMode == NWAL_SA_EALG_AES_GCM) || 
227                (sa_info->cipherMode == NWAL_SA_EALG_AES_CCM))))
228         {
229             createParam.saIpSecParam.replayWindow = 0;
230             createParam.saIpSecParam.macSize = 0;
231         }
232         memcpy(&createParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
234         if (route != NULL)
235         {
236             if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
237                 NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
238             {
239                createParam.saIpSecParam.validParams |= 
240                         NWAL_SA_INFO_VALID_PARAM_ROUTE_TYPE;
241             }
242             netapip_netcpCfgBuildRoute(route,
243                                        &createParam.saIpSecParam.appRxPktFlowId,
244                                        &createParam.saIpSecParam.appRxPktQueue,
245                                        &createParam.saIpSecParam.routeType);
246         }
248         /* fire off config message */
249         retValue = nwal_setSecAssoc (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
250                                         trans_id,
251                                         (nwal_AppId) appId,
252                                         &saInfo,
253                                         &createParam,
254                                         &pTransInfo->handle);
255         if(retValue == nwal_TRANS_COMPLETE)
256         {
257             have_to_wait=0;
258         }
259         else if(retValue !=  nwal_OK)
260         {
261             *perr = NETAPI_ERR_NWAL_ERR0;
262             netapip_freeTransInfo(pTransInfo);
263             netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
264             return -1;
265         }
267         if((trans_id != NWAL_TRANSID_SPIN_WAIT)&&(have_to_wait))
268         {
269             n->nwal_local.numPendingCfg++;
270             while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
271                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
272             {
273                 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
274             }
275             if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
276             {
277                 pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
278                 pTransInfo->inUse = nwal_FALSE;
279                 *perr = NETAPI_ERR_PA_FW;
280                 netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
281                 return -1;
282             }
283         }
285         *p_inflow_mode_handle=pTransInfo->handle;
286         netapip_freeTransInfo(pTransInfo);
288         if (sa_info->dir == NWAL_SA_DIR_OUTBOUND)
289         {
290             memset(&nwalSaIpSecId, 0, sizeof(nwalSaIpSecId_t));
291             nwalSaIpSecId.spi = sa_info->spi;
292             memcpy(&(nwalSaIpSecId.src), &sa_info->src,sizeof( nwalIpAddr_t));
293             memcpy(&(nwalSaIpSecId.dst), &sa_info->dst,sizeof( nwalIpAddr_t));
294             nwalSaIpSecId.proto = sa_info->proto;
295             if (nwal_getSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
296                                      &nwalSaIpSecId, 
297                                      NWAL_SA_DIR_OUTBOUND,
298                                      p_inflow_mode_handle,
299                                      &swInfo0,
300                                      &swInfo1) != nwal_TRUE)
301                 netapi_Log("netapisecAddSA: call to nwal_getSecAssoc() returned error\n");
302         }
303     }
305     /* sideband mode */
306     if (inflow_mode &NETAPI_SEC_SA_SIDEBAND)
307     {
308         nwalCreateDmSAParams_t  dmSaParam;
309         void * dm_handle;
310         memset(&dmSaParam,0,sizeof(nwalCreateDmSAParams_t));
311         dmSaParam.dmSaParam.dmChnType= (sa_info->dir==NWAL_SA_DIR_INBOUND)?  NWAL_DM_CHAN_DECRYPT: NWAL_DM_CHAN_ENCRYPT; /**direction*/ 
312         dmSaParam.dmSaParam.replayWindow=sa_info->replayWindow;
313         dmSaParam.dmSaParam.authMode=sa_info->authMode;
314         dmSaParam.dmSaParam.cipherMode=sa_info->cipherMode;
315         dmSaParam.dmSaParam.macSize=12;
316         dmSaParam.dmSaParam.aadSize=0;
317         dmSaParam.dmSaParam.enc1st =  (sa_info->dir ==NWAL_SA_DIR_OUTBOUND) ? nwal_TRUE : nwal_FALSE;  //encypt 1st for outbound
318         if ((sa_info->cipherMode == NWAL_SA_EALG_AES_GCM) ||
319             (sa_info->cipherMode == NWAL_SA_EALG_AES_CCM) ||
320             (sa_info->authMode == NWAL_SA_AALG_GMAC))
321         {
322             dmSaParam.dmSaParam.macSize = 16;
323             dmSaParam.dmSaParam.aadSize=8;
324             /* Enc1st needs to always be true for combined mode algorithms */
325             dmSaParam.dmSaParam.enc1st = nwal_TRUE;
326         }
327        else
328         {
329             dmSaParam.dmSaParam.macSize=12;
330             dmSaParam.dmSaParam.aadSize=0;
331         }
333        if  (sa_info->authMode == NWAL_SA_AALG_NULL)
334        {
335             dmSaParam.dmSaParam.enc1st = nwal_TRUE;
336        }
337         /* todo; allow app q for Sideband return */
338         memcpy(&dmSaParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
339         retValue = nwal_setDMSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
340                                   (nwal_AppId)appId,
341                                   &dmSaParam,
342                                   &dm_handle);
343         if(retValue != nwal_OK)
344         {
345             *perr = NETAPI_ERR_NWAL_ERR0;
346             netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
347             return -1;
348         }
350         *p_data_mode_handle = dm_handle;
351         memset(&dmPSCmdInfo, 0, sizeof(nwalTxDmPSCmdInfo_t));
352         retValue =  nwal_initDMPSCmdInfo(netapip_returnNwalInstanceHandle(h),
353                                          *p_data_mode_handle,
354                                          &dmPSCmdInfo); 
355     }
357     netapip_netcpCfgInsertSa(&netapi_get_global()->nwal_context,
358                           tunnelId,
359                           (sa_info->dir ==   NWAL_SA_DIR_INBOUND) ? NETAPI_TRUE: NETAPI_FALSE,
360                           inflow_mode,
361                           &saInfo,
362                           &createParam,
363                           *p_inflow_mode_handle,
364                           *p_data_mode_handle,
365                           &dmPSCmdInfo,
366                           swInfo0,
367                           swInfo1,
368                           p_user_data);
369     netapi_sa_db[free_sa_db_slot].app_id = appId;
370     netapi_sa_db[free_sa_db_slot].inUse = 1;
371     netapi_sa_db[free_sa_db_slot].spi = sa_info->spi;
372     netapi_sa_db[free_sa_db_slot].ref_count++;
373     memcpy(&(netapi_sa_db[free_sa_db_slot].dst), &sa_info->dst,sizeof( nwalIpAddr_t));
374     return  (appId);
377 /********************************************************************
378  * FUNCTION PURPOSE:  API to add an IPSEC SA
379  ********************************************************************
380  * DESCRIPTION:  API to add an IPSEC SA
381  ********************************************************************/
382 NETCP_CFG_SA_T netapi_secAddSA(NETAPI_T h,
383                                  int iface_no,
384                                  NETAPI_SEC_SA_INFO_T *sa_info,
385                                  nwalSecKeyParams_t * key_params,
386                                  int inflow_mode,
387                                  NETCP_CFG_ROUTE_HANDLE_T  route,
388                                  void **p_data_mode_handle,
389                                  void **p_inflow_mode_handle,
390                                  void * p_user_data,
391                                  int * perr)
393         *perr = 0;
394         return netapi_secAddSAInternal(h,
395                                        iface_no,
396                                        sa_info,
397                                        key_params,
398                                        inflow_mode,
399                                        route,
400                                        p_data_mode_handle,
401                                        p_inflow_mode_handle,
402                                        p_user_data,
403                                        0,
404                                        perr);
407 /********************************************************************
408  * FUNCTION PURPOSE:  API IP handle to add an IPSEC SA
409  ********************************************************************
410  * DESCRIPTION:  API to add an IPSEC SA.
411  *               Piggy back off perr for IP handle flag and IP slot.
412  ********************************************************************/
413 NETCP_CFG_SA_T netapi_secAddSAIP(NETAPI_T h,
414                                  int iface_no,
415                                  NETAPI_SEC_SA_INFO_T *sa_info,
416                                  nwalSecKeyParams_t * key_params,
417                                  int inflow_mode,
418                                  NETCP_CFG_ROUTE_HANDLE_T  route,
419                                  void **p_data_mode_handle,
420                                  void **p_inflow_mode_handle,
421                                  void * p_user_data,
422                                  NETCP_CFG_IP_T ip_rule,
423                                  int * perr)
425         *perr = 0;
426         return netapi_secAddSAInternal(h,
427                                        iface_no,
428                                        sa_info,
429                                        key_params,
430                                        inflow_mode,
431                                        route,
432                                        p_data_mode_handle,
433                                        p_inflow_mode_handle,
434                                        p_user_data,
435                                        ip_rule,
436                                        perr);
439 /********************************************************************
440  * FUNCTION PURPOSE:  Internal function  to dynamically switch between inflow
441  *                                  and sideband mode
442  ********************************************************************
443  * DESCRIPTION:  Internal function  to dynamically switch between inflow
444  *                                  and sideband mode
445  ********************************************************************/
446 void netapi_secInflowMode(int iface,
447                           NETCP_CFG_SA_T sa,
448                           int on)
450     /* NOT_IMPLEMENTED */
453 /********************************************************************
454  * FUNCTION PURPOSE:  Internal function  to delete an IPSEC SA
455  ********************************************************************
456  * DESCRIPTION:  Internal function to delete an IPSEC SA
457  ********************************************************************/
458 static void netapi_secDelSA_internal(NETAPI_T h,
459                                      int iface_no,
460                                      NETCP_CFG_SA_T sa_app_id,
461                                      int flags,
462                                      int *perr)
464     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
465     nwal_RetValue       retValue;
466     NetapiNwalTransInfo_t *pTransInfo;
467     nwal_TransID_t     trans_id;
468     int tunnelId = (sa_app_id >> NETAPI_NETCP_MATCH_ID_SHIFT) &NETAPI_NETCP_MATCH_ID_MASK;
469     void * handle_inflow;
470     void * handle_sideband;
471     int have_to_wait = 1;
472     int sa_db_slot;
474     *perr =0;
475     for(sa_db_slot=0; sa_db_slot < TUNE_NETAPI_MAX_SA; sa_db_slot++)
476     {
477             if((netapi_sa_db[sa_db_slot].inUse) &&
478             (netapi_sa_db[sa_db_slot].app_id == sa_app_id))
479             {
480                 if(!netapi_sa_db[sa_db_slot].ref_count)
481                 {
482                     *perr = NETAPI_ERR_NOTFOUND;
483                     return;
484                 }
485                 netapi_sa_db[sa_db_slot].ref_count--;
486                 if(netapi_sa_db[sa_db_slot].ref_count)
487                 {
488                     return;
489                 }
490                 else
491                 {
492                     netapi_sa_db[sa_db_slot].inUse = 0;
493                     break;
494                 }
495             }
496     }
497     handle_inflow = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,
498                                           tunnelId, &handle_sideband);
501     if(handle_inflow)
502     {
503     /* get a transaction id */
504         pTransInfo = netapip_getFreeTransInfo(n,
505                                               (NETAPI_PROC_GLOBAL_T *) n->proc_global,
506                                               &trans_id);
507         if (!pTransInfo)
508         {
509             *perr =  NETAPI_ERR_BUSY;
510             return;
511         }
512         pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA;
513         pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
514         pTransInfo->inUse = nwal_TRUE;
515         pTransInfo->netapi_handle = h;
517         retValue = nwal_delSecAssoc(
518                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
519                 trans_id,
520                 handle_inflow);
521         if(retValue == nwal_TRANS_COMPLETE)
522         {
523            have_to_wait=0;
524         }
525         else if(retValue !=  nwal_OK)
526         {
527                 *perr = NETAPI_ERR_NWAL_ERR0;
528                 netapip_freeTransInfo(pTransInfo);
529                 netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context,tunnelId);
530         }
531         if((trans_id != NWAL_TRANSID_SPIN_WAIT)&&(have_to_wait))
532         {
533             n->nwal_local.numPendingCfg++;
535             while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
536                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
537             {
538                 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
539             }
540             if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
541             {
542                 netapip_freeTransInfo(pTransInfo);
543                 *perr = NETAPI_ERR_PA_FW;
544                  if (!flags) 
545                     netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context, tunnelId);
546                 return;
547            }
548         }
549         netapip_freeTransInfo(pTransInfo);
550     }
551     if (handle_sideband)
552     {
553         retValue=nwal_delDMSecAssoc( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
554                                     handle_sideband);
555         if(retValue !=  nwal_OK)
556         {
557             *perr = NETAPI_ERR_NWAL_ERR0;
558         }
559     }
561     /* zap the entry */
562     if (!flags)
563         netapip_netcpCfgDeleteSa(&netapi_get_global()->nwal_context, tunnelId);
566 /********************************************************************
567  * FUNCTION PURPOSE:  API to delete an IPSEC SA
568  ********************************************************************
569  * DESCRIPTION:  API to delete an IPSEC SA
570  ********************************************************************/
571 void netapi_secDelSA(NETAPI_T h,
572                      int iface_no,
573                      NETCP_CFG_SA_T sa_app_id,
574                      int *perr)
576     netapi_secDelSA_internal( h, iface_no,  sa_app_id, 0x00, perr);
580 /********************************************************************
581  * FUNCTION PURPOSE:  API to add a receive security policy
582  ********************************************************************
583  * DESCRIPTION:  API to add a receive security policy
584  ********************************************************************/
585 NETCP_CFG_IPSEC_POLICY_T netapi_secAddRxPolicy(NETAPI_T h, 
586                                                NETCP_CFG_SA_T sa,
587                                                nwal_IpType ipType,
588                                                nwalIpAddr_t * src_ip_addr,
589                                                nwalIpAddr_t * dst_ip_addr,
590                                                nwalIpOpt_t * ip_qualifiers,
591                                                NETCP_CFG_ROUTE_HANDLE_T  route,
592                                                void * user_data,
593                                                int * perr)
595     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
596     nwal_RetValue       retValue;
597     NetapiNwalTransInfo_t *pTransInfo;
598     nwal_TransID_t     trans_id;
599     unsigned int appId = NETAPI_NETCP_MATCH_IPSEC_POLICY;
600     int policyId;
601     int tunnelId= netapi_cfgGetMatchId(sa);
602     void * blah;
603     int iface_no = netapi_cfgGetMatchLogicalMacIface(sa);
605     nwalSecPolParams_t createParam =
606     {
607         0,  /* handle */
608         0,  /* valid params */
609         NWAL_SA_DIR_INBOUND,
610         4,      /* IP Type */
611         {0},  /* dst */
612         {0},  /* src */
613         {0 },/* IP Options */
614         NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
615         NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
616         CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
617         QMSS_PARAM_NOT_SPECIFIED,                    /* Use default queue configured to NWAL if packet is routed to host */
618         0                                            /* Optional: route type */
619     };
621     void * sa_handle = NULL;
622     *perr =0;
623     
624     if ((!n) )
625     {
626         *perr = NETAPI_ERR_BAD_INPUT;
627         return -1;
628     }
630     sa_handle = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,tunnelId,&blah);
631     if (!sa_handle)
632     {
633         *perr = NETAPI_ERR_BAD_INPUT;
634         return -1;
635     }
637     /* get a transaction id */
638     pTransInfo = netapip_getFreeTransInfo(n,
639                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
640                                           &trans_id);
641     if (!pTransInfo)
642     {
643         *perr =  NETAPI_ERR_BUSY;
644         return -1;
645     }
646     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY;
647     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
648     pTransInfo->inUse = nwal_TRUE;
649     pTransInfo->netapi_handle = h;
650     createParam.handle = sa_handle;
651     createParam.ipType = ipType;
652     if (dst_ip_addr) memcpy(&createParam.dst, dst_ip_addr, sizeof(nwalIpAddr_t)); 
653     if (src_ip_addr) memcpy(&createParam.src, src_ip_addr, sizeof(nwalIpAddr_t)); 
654     if (ip_qualifiers) memcpy(&createParam.ipOpt,ip_qualifiers ,sizeof(nwalIpOpt_t));
655     if (route != NULL)
656     {
657         if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
658             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
659         {
660            createParam.validParams |= 
661                     NWAL_SET_SEC_POLICY_VALID_PARAM_ROUTE_TYPE;
662         }
663         netapip_netcpCfgBuildRoute(route,
664                                    &createParam.appRxPktFlowId,
665                                    &createParam.appRxPktQueue,
666                                    &createParam.routeType);
667     }
668     /* reserve a slot */
669     policyId = netapip_netcpCfgFindPolicySlot(n,
670                                               &netapi_get_global()->nwal_context,
671                                               tunnelId);
672     if (policyId <0) 
673     {
674         *perr= NETAPI_ERR_NOMEM;
675         netapip_freeTransInfo(pTransInfo);
676         return -1;
677     }
678     appId |=  (policyId <<8);
680     /* fire off config message */
681     retValue = nwal_setSecPolicy (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
682                                   trans_id,
683                                   (nwal_AppId) appId,
684                                   &createParam,
685                                   &pTransInfo->handle);
686     if(retValue !=  nwal_OK)
687     {
688         *perr = NETAPI_ERR_NWAL_ERR0;
689         netapip_freeTransInfo(pTransInfo);
690         
691         netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context,policyId);
692         return -1;
693     }
695     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
696     {
697         n->nwal_local.numPendingCfg++;
698         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
699                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
700         {
701             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
702         }
703         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
704         {
705             netapip_freeTransInfo(pTransInfo);
706             *perr = NETAPI_ERR_PA_FW;
707             netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context,policyId);
708             return -1;
709         }
710     }
712     /* save stuff */
713     netapip_netcpCfgInsertPolicy(&netapi_get_global()->nwal_context,
714                            policyId,
715                           (void *) pTransInfo->handle,
716                           user_data);
717     netapip_freeTransInfo(pTransInfo);
718     return  (appId);
721 /********************************************************************
722  * FUNCTION PURPOSE:  Internal function to delete a receive security policy
723  ********************************************************************
724  * DESCRIPTION:  Internal function to delete a receive security policy
725  ********************************************************************/
726 static void netapi_secDelRxPolicy_internal(NETAPI_T h,
727                                            NETCP_CFG_IPSEC_POLICY_T policy_app_id,
728                                            int flags,
729                                            int *perr)
731     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
732     nwal_RetValue       retValue;
733     NetapiNwalTransInfo_t *pTransInfo;
734     nwal_TransID_t     trans_id;
735     int policyId = netapi_cfgGetMatchId(policy_app_id);
736     void * handle_policy=NULL;
738     handle_policy = netapip_netcpCfgGetPolicy(&netapi_get_global()->nwal_context,policyId);
739                                           ;
740     if (!handle_policy)
741     {
742         *perr = NETAPI_ERR_BAD_INPUT;
743         goto ERR_netapi_secDelRxPolicy_internal;
744      }
745     *perr =0;
747     /* get a transaction id */
748     pTransInfo = netapip_getFreeTransInfo(n,
749                                          (NETAPI_PROC_GLOBAL_T *) n->proc_global,
750                                          &trans_id);
751     if (!pTransInfo)
752     {
753         *perr =  NETAPI_ERR_BUSY;
754         goto ERR_netapi_secDelRxPolicy_internal;
755     }
756     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY;
757     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
758     pTransInfo->inUse = nwal_TRUE;
759     pTransInfo->netapi_handle = h;
761     /* issue request */
762     retValue = nwal_delSecPolicy(
763                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
764                 trans_id,
765                 handle_policy);
766     if(retValue !=  nwal_OK)
767     {
768         *perr = NETAPI_ERR_NWAL_ERR0;
769         netapip_freeTransInfo(pTransInfo);
770         goto ERR_netapi_secDelRxPolicy_internal;
771     }
773     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
774     {
775         n->nwal_local.numPendingCfg++;
776         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
777                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
778         {
779             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
780         }
781         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
782         {
783             netapip_freeTransInfo(pTransInfo);
784             *perr = NETAPI_ERR_PA_FW;
785             //zap the entry
786             if (!flags)
787                 netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context, policyId);
788             goto ERR_netapi_secDelRxPolicy_internal;
789             
790         }
791     }
792     netapip_freeTransInfo(pTransInfo);
793     /* zap the entry */
794     if (!flags)
795     {
796         netapip_netcpCfgDeletePolicy(&netapi_get_global()->nwal_context, policyId);
797     }
798 ERR_netapi_secDelRxPolicy_internal:
799     return;
802 /********************************************************************
803  * FUNCTION PURPOSE:  API to delete a receive security policy
804  ********************************************************************
805  * DESCRIPTION:  API to delete a receive security policy
806  ********************************************************************/
807 void netapi_secDelRxPolicy(NETAPI_T h,
808                            NETCP_CFG_IPSEC_POLICY_T policy_app_id,
809                            int *perr)
811     netapi_secDelRxPolicy_internal(h,  policy_app_id, 0, perr);
814 /********************************************************************
815  * FUNCTION PURPOSE:  API to retrieve SA statistics via NWAL
816  ********************************************************************
817  * DESCRIPTION:  API to retrieve SA statistics via NWAL
818  ********************************************************************/
819 void  netapi_getSaStats (NETAPI_T               h, 
820                          NETCP_CFG_SA_T         handle,
821                          NETAPI_SA_STATS_T*     pSaStats)
823     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
824     void * handle_inflow;
825     void * handle_sideband;
826     int tunnelId = (handle >> NETAPI_NETCP_MATCH_ID_SHIFT) &0xffff;
827     int have_to_wait = 1;
828     handle_inflow = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,
829                                           tunnelId, &handle_sideband);
830     if(handle_inflow)
831     {
832         nwal_getSecAssocStats(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, 
833                                                 handle_inflow, &(pSaStats->saIpsecStats));
834         pSaStats->validParams |= NETAPI_IPSEC_STAT_VALID;
835     }
836     if(handle_sideband)
837     {
838         nwal_getDataModeStats(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, 
839                                                 handle_sideband, &(pSaStats->dataModeStats));
840         pSaStats->validParams |= NETAPI_SIDEBAND_DATA_MODE_STAT_VALID;
841     }
845 /**********************************************************************************
846  * FUNCTION PURPOSE:  API to  API to retrieve local channel context information
847  **********************************************************************************
848  * DESCRIPTION:  API to retrieve API to retrieve local channel context information
849  *********************************************************************************/
850 void netapi_secGetChanCtxInfo(NETAPI_T h,
851                            NETCP_CFG_APP_ID_T appId,
852                            nwalChanCxtInfo_t* pInfo)
855     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
856     void * handle_inflow;
857     void * handle_sideband = NULL;
858     void * handle_policy=NULL;
859     nwalChanCxtInfo_t info;
860     uint32_t stage = 0;
861     int policyId;
862     int tunnelId;
864     if(!pInfo)
865         return;
866     memset(pInfo, 0, sizeof(nwalChanCxtInfo_t));
868     stage = netapi_cfgGetMatchStage(appId);
870     switch (stage)
871     {
872         case 1:
873             /* this is for SA, need SA and OUTER IP handle */
874             tunnelId = netapi_cfgGetMatchId(appId);
875             handle_inflow = netapip_netcpCfgGetSaHandles(&netapi_get_global()->nwal_context,
876                                           tunnelId, &handle_sideband);
877             if(handle_inflow)
878             {
879                 nwal_getChanCxtInfo(&netapi_get_global()->nwal_context,
880                             handle_inflow,
881                             pInfo);
882             }
883             break;
884         case 2:
885             /* this is for policy, need SA inner IP */
886             policyId = netapi_cfgGetMatchId(appId);
887             handle_policy = netapip_netcpCfgGetPolicy(&netapi_get_global()->nwal_context,
888                                                           policyId);
889             if (handle_policy)
890             {
891                 nwal_getChanCxtInfo(&netapi_get_global()->nwal_context,
892                             handle_policy,
893                             pInfo);
894             }
895             break;
896         default:
897             break;
898     }
899     return;