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));
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);
375 }
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)
392 {
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);
405 }
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)
424 {
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);
437 }
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)
449 {
450 /* NOT_IMPLEMENTED */
451 }
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)
463 {
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);
564 }
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)
575 {
576 netapi_secDelSA_internal( h, iface_no, sa_app_id, 0x00, perr);
577 }
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)
594 {
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;
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);
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);
719 }
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)
730 {
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;
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;
800 }
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)
810 {
811 netapi_secDelRxPolicy_internal(h, policy_app_id, 0, perr);
812 }
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)
822 {
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 }
842 }
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)
853 {
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;
900 }