07ccd673b70aa382fceb7449292c1caca04b9c86
[keystone-rtos/netapi.git] / ti / runtime / netapi / applications / ipsec_offload / ipsecmgr / src / netapi_ipsecmgr.c
1 /*
2  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
3  *
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *    Neither the name of Texas Instruments Incorporated nor the names of
18  *    its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33 */
36 /* IPSec Manager Include Files */
37 #include "ipsecmgr_snoop.h"
38 #include "ipsecmgr_ipc.h"
39 #include "ipsecmgr_syslog.h"
41 /* Local include */
42 #include "netapilib_interface.h"
44 /* Standard includes */
45 #include <dlfcn.h>
46 #include <stdlib.h>
47 #include <signal.h>
48 #include <stdarg.h>
52 #include <arpa/inet.h>
53 #include <sys/socket.h>
54 #include <ifaddrs.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <unistd.h>
59 #include <sys/types.h>
60 #include <netinet/in.h> 
61 #include <string.h> 
63 #if defined(DEVICE_K2H)
64 #include <ti/drv/qmss/device/k2h/src/qmss_device.c>
65 #include <ti/drv/cppi/device/k2h/src/cppi_device.c>
66 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
67  "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/complete-queue"};
68 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
69 "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/flow"};
70 #elif defined (DEVICE_K2K)
71 #include <ti/drv/qmss/device/k2k/src/qmss_device.c>
72 #include <ti/drv/cppi/device/k2k/src/cppi_device.c>
73 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
74  "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/complete-queue"};
75 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
76 "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/flow"};
77 #elif defined (DEVICE_K2L)
78 #include <ti/drv/qmss/device/k2l/src/qmss_device.c>
79 #include <ti/drv/cppi/device/k2l/src/cppi_device.c>
80 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
81  "/proc/device-tree/soc/pktdma@26186000/channels/netrx0/complete-queue"};
82 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
83 "/proc/device-tree/soc/pktdma@26186000/channels/netrx0/flow"};
84 #elif defined (DEVICE_K2E)
85 #include <ti/drv/qmss/device/k2e/src/qmss_device.c>
86 #include <ti/drv/cppi/device/k2e/src/cppi_device.c>
87 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
88  "/proc/device-tree/soc/pktdma@24186000/channels/netrx0/complete-queue"};
89 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
90 "/proc/device-tree/soc/pktdma@24186000/channels/netrx0/flow"};
92 #else /*Default */
93 #include <ti/runtime/hplib/device/k2h/src/hplib_device.c>
94 #include <ti/runtime/netapi/device/k2h/src/netapi_device.c>
95 #include <ti/drv/qmss/device/k2h/src/qmss_device.c>
96 #include <ti/drv/cppi/device/k2h/src/cppi_device.c>
97 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
98  "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/complete-queue"};
99 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
100 "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/flow"};
102 #endif
104 /**********************************************************************
105  ************************** Local Definitions *************************
106  **********************************************************************/
107 #if 0
109 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
110  "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/complete-queue"};
111 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
112 "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/flow"};
114 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
115  "/proc/device-tree/soc/pktdma@26186000/channels/netrx0/complete-queue"};
116 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
117 "/proc/device-tree/soc/pktdma@26186000/channels/netrx0/flow"};
118 #endif
121 /**********************************************************************
122  ************************** Global Variables **************************
123  **********************************************************************/
124 extern Rm_ServiceHandle   *rmClientServiceHandle;
126 static ipsecmgr_ipc_daemon_send_if_t *send_iface;
127 NETAPI_T netapi_handle;
129 ipsecMgrMcb_t globalDB;
131 static int use_rm =0;
133 /* Lock file for the daemon */
134 #define LOCK_FILE   "/var/lock/ipsecmgr_daemon"
136 /* snoop task */
137 static pthread_t    snoop_run_th;
139 static NETAPI_CFG_T our_netapi_default_cfg=
141     TUNE_NETAPI_PERM_MEM_SZ,
142     128,  //start of packet offset for hw to place data on rx for default flow
143     TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
144     TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
145     TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap
146     64, //#descriptors w/o buffers in default heap
147     TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128,  //size of buffers in default heap
148     128,    //tail room
149     256,    //extra room
150     0,
151     NULL
152 };
156 static int QUIT = 0;
158 /* stub functions */
159 static void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
160                          PKTIO_METADATA_T meta[], int n_pkts,
161                          uint64_t ts )
163     return;
166 /* byte swap routine */
167 static unsigned int swap32 (unsigned int x)
169     unsigned int y;
171     y = (((x >> 24) & 0xff) <<  0) |
172         (((x >> 16) & 0xff) <<  8) |
173         (((x >>  8) & 0xff) << 16) |
174         (((x >>  0) & 0xff) << 24) ;
176     return (y);
180 void cleanup_sa_sp()
182     int slot, error=0;;
183     /* delete any offloaded rx SA's and policies */
184     /* and delete any offloaded tx SA's */
185     for (slot = 0;slot < 64;slot++)
186     {
187         if(globalDB.rx_sa[slot].in_use)
188         {
189             globalDB.rx_sa[slot].in_use = 0;
190             if(globalDB.rx_sa[slot].spAppId)
191             {
192                 netapi_secDelRxPolicy(netapi_handle,
193                               (NETCP_CFG_IPSEC_POLICY_T) globalDB.rx_sa[slot].spAppId,
194                               &error);
195                 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
196                 "cleanup_sa_sp: SP deleted: sp_app_id: 0x%x, slot: %d, error: %d\n", 
197                 globalDB.rx_sa[slot].spAppId, slot, error);
198             }
199             netapi_secDelSA(netapi_handle,
200                         NETCP_CFG_NO_INTERFACE,
201                         (NETCP_CFG_SA_T) globalDB.rx_sa[slot].saAppId,
202                         &error);
203             ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
204                 "cleanup_sa_sp: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n", 
205                 globalDB.rx_sa[slot].saAppId, slot, error);
206             
207         }
208         if(globalDB.tx_sa[slot].in_use)
209         {
210             globalDB.tx_sa[slot].in_use = 0;
211             netapi_secDelSA(netapi_handle,
212                             NETCP_CFG_NO_INTERFACE,
213                            (NETCP_CFG_SA_T) globalDB.tx_sa[slot].saAppId,
214                             &error);
215             ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
216                 "cleanup_sa_sp: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n", 
217                 globalDB.tx_sa[slot].saAppId, slot, error);
218         }
219     }
223 static void* snoop_run_thread (void* arg)
225     cpu_set_t cpu_set;
226     CPU_ZERO( &cpu_set);
227     CPU_SET( 0, &cpu_set);
229     hplib_utilSetupThread(0, &cpu_set, hplib_spinLock_Type_LOL);
230     ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
231         "snoop_run_thread: daemon entering forever event loop\n");
233     while (1)
234     {
235         /* Poll for message from user application */
236         ipsecmgr_ipc_poll();
238         /* Poll for message from Kernel */
239         ipsecmgr_snoop_run();
240         if (QUIT == 1)
241             break;
242     }
243     ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
244         "snoop_run_thread: calling shutdown\n");
245     ipsecmgr_snoop_shutdown ();
246     cleanup_sa_sp();
247     netapi_shutdown(netapi_handle);
249     if (use_rm)
250         closeRm();
251     return;
254 /**
255  *  @b Description
256  *  @n  
257  *      SIGTERM handler.
258  *
259  *  @param[in]  signum
260  *      signal number to terminate deamon.
261  */
262 static void sig_term_handler(int signum)
264     QUIT = 1;
267 /**
268  *  @b Description
269  *  @n  
270  *      Function to implement task sleep functionality 
271  *      for IPSecMgr
272  *
273  *  @param[in]  time_in_msec
274  *      Time in milliseconds to sleep
275  *
276  *  @retval
277  *      Not Applicable.
278  */
279 static void task_sleep(uint32_t time_in_msec)
281     pthread_mutex_t fake_mutex = PTHREAD_MUTEX_INITIALIZER;
282     pthread_cond_t fake_cond = PTHREAD_COND_INITIALIZER;
283     struct timespec ts;
284     int rt;
285     unsigned int sec, nsec;
287     sec = time_in_msec/1000;
288     nsec = (time_in_msec - (sec*1000)) * 1000000;
290     /* Use the wall-clock time */
291     clock_gettime(CLOCK_REALTIME, &ts);
293     ts.tv_sec += sec;
294     ts.tv_nsec += nsec;
296     pthread_mutex_lock(&fake_mutex);
297     rt = pthread_cond_timedwait(&fake_cond, &fake_mutex, &ts);
298     pthread_mutex_unlock(&fake_mutex);
302 /**
303  *  @b Description
304  *  @n  
305  *      NETAPI Proxy's IPSecMgr Start Offload Response 
306  *      message handler.
307  *
308  *      This function is called by the IPSecMgr library
309  *      when it has a response ready corresponding to an
310  *      Start Offload SP request issued by the user application.
311  *
312  *  @param[in]  rsp
313  *      IPSecMgr's Start Offload SP response
314  *  @param[in]  addr
315  *      Destination address (user application) to send 
316  *      the response to
317  *  @param[in]  addr_size
318  *      Size of destination address passed
319  *
320  *  @retval
321  *      Success -   0
322  *  @retval
323  *      ERROR   -   <0
324  */
325 static int offload_sp_rsp_send
327     ipsecmgr_snoop_offload_sp_rsp_param_t *rsp,
328     void                                  *addr,
329     uint32_t                              addr_size
332     ipsecmgr_ipc_offload_sp_rsp_param_t offload_sp_rsp;
334     offload_sp_rsp.type = rsp->type;
335     offload_sp_rsp.result = rsp->result;
336     offload_sp_rsp.trans_id = rsp->trans_id;
337     offload_sp_rsp.err_code = rsp->err_code;
338     offload_sp_rsp.sp_handle = rsp->sp_handle;
339     offload_sp_rsp.sa_handle = rsp->sa_handle;
341     if (addr_size != sizeof(ipsecmgr_ipc_addr_t)) {
342         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR,
343             "offload_sp_rsp_send: addr size not correct\n");
344         return -1;
345     }
347     return send_iface->offload_sp_rsp(&offload_sp_rsp,
348                                       (ipsecmgr_ipc_addr_t *)addr);
350 static void offload_sp_req_recv
352     ipsecmgr_ipc_offload_sp_req_param_t *req,
353     ipsecmgr_ipc_addr_t                 *src_addr
356     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"offload_sp_req_recv called for policy id\n",
357     req->policy_id);
358     ipsecmgr_snoop_offload_sp_rsp_param_t rsp;
359     uint32_t addr_size = sizeof(ipsecmgr_ipc_addr_t);
360     ipsecmgr_snoop_offload_sp_req_param_t offload_sp_req;
362     offload_sp_req.trans_id = req->trans_id;
363     offload_sp_req.policy_id = req->policy_id;
364     offload_sp_req.sa_flags = req->sa_flags;
365     offload_sp_req.if_name = req->if_name;
366     offload_sp_req.dscp_cfg = req->dscp_cfg;
367     offload_sp_req.l5_selector = req->l5_selector;
368     //offload_sp_req.oseq_offset = req->oseq_offset;
370     memset(&rsp, 0, sizeof(rsp));
371     rsp.trans_id = req->trans_id;
373     if (ipsecmgr_snoop_offload_sp_req(&offload_sp_req, (void*)src_addr,
374                                       addr_size)) {
375         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
376             "offload_sp_req_recv: snoop_offload_sp_req failed\n");
377         rsp.result = RESULT_FAILURE;
378         rsp.type = RSP_TYPE_ACK | RSP_TYPE_DONE;
379     }
380     else
381     {
382         rsp.result = RESULT_SUCCESS;
383         rsp.type = RSP_TYPE_ACK;
384     }
385     
386     if (offload_sp_rsp_send(&rsp, (void *)src_addr, addr_size))
387     {
388         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
389             "offload_sp_req_recv: failed to send ACK for offload_sp\n");
390     }
391     return;
395 /**
396  *  @b Description
397  *  @n  
398  *      NETAPI Proxy's IPSecMgr Stop Offload response message 
399  *      handler.
400  *
401  *      This function is called by the IPSecMgr library
402  *      when it has a response ready corresponding to an
403  *      Stop Offload SP request issued by the user application.
404  *
405  *  @param[in]  rsp
406  *      IPSecMgr's Stop Offload SP response
407  *  @param[in]  addr
408  *      Destination address (user application) to send 
409  *      the response to
410  *  @param[in]  addr_size
411  *      Size of destination address passed
412  *
413  *  @retval
414  *      Success -   0
415  *  @retval
416  *      ERROR   -   <0
417  */
418 static int stop_offload_rsp_send
420     ipsecmgr_snoop_stop_offload_rsp_param_t *rsp,
421     void                                    *addr,
422     uint32_t                                addr_size
425     ipsecmgr_ipc_stop_offload_rsp_param_t stop_offload_rsp;
427     stop_offload_rsp.type = rsp->type;
428     stop_offload_rsp.result = rsp->result;
429     stop_offload_rsp.trans_id = rsp->trans_id;
431     if (addr_size != sizeof(ipsecmgr_ipc_addr_t)) {
432         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR,
433             "stop_offload_rsp_send: addr size not correct\n");
434         return -1;
435     }
437     return send_iface->stop_offload_rsp(&stop_offload_rsp,
438                                       (ipsecmgr_ipc_addr_t *)addr);
441 static void stop_offload_req_recv
443     ipsecmgr_ipc_stop_offload_req_param_t   *req,
444     ipsecmgr_ipc_addr_t                     *src_addr
447     ipsecmgr_snoop_stop_offload_req_param_t stop_offload_req;
448     uint32_t addr_size = sizeof(ipsecmgr_ipc_addr_t);
449     ipsecmgr_snoop_stop_offload_rsp_param_t rsp;
451     stop_offload_req.trans_id = req->trans_id;
452     stop_offload_req.policy_id = req->policy_id;
454     memset(&rsp, 0, sizeof(rsp));
455     rsp.trans_id = req->trans_id;
457     if (ipsecmgr_snoop_stop_offload(&stop_offload_req, (void*)src_addr,
458                                       addr_size)) {
459         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
460             "stop_offload_req_recv: snoop_stop_offload failed\n");
461         rsp.result = RESULT_FAILURE;
462         rsp.type = RSP_TYPE_ACK | RSP_TYPE_DONE;
463     }
464     else
465     {
466         rsp.result = RESULT_SUCCESS;
467         rsp.type = RSP_TYPE_ACK;
468     }
470     if (stop_offload_rsp_send(&rsp, (void *)src_addr, addr_size))
471     {
472         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
473             "stop_offload_req_recv: failed to send ACK for stop_offload\n");
474     }
475     return;
478 /**
479  *  @b Description
480  *  @n  
481  *      Function to initialize IPSec Manager library.
482  *
483  *  @retval
484  *      Success -   0
485  *  @retval
486  *      ERROR   -   >0
487  */
488 static int32_t init_ipsecmgr (void)
490     struct ipsecmgr_snoop_fp_cfg_cb     fp_cfg_cb;
491     struct ipsecmgr_snoop_mgnt_cb       mgnt_cb;
492     struct ipsecmgr_snoop_platform_cb   plat_cb;
493     ipsecmgr_ipc_daemon_recv_if_t       recv_if;
494     ipsecmgr_ipc_cfg_t                  ipc_cfg;
495     int32_t                             status;
496     pthread_attr_t threadAttr;
498     /* Initializations */
499     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, 
500                         "DEBUG: init_ipsecmgr() starting initialization\n");
501     memset(&fp_cfg_cb, 0, sizeof(fp_cfg_cb));
502     memset(&mgnt_cb, 0, sizeof(mgnt_cb));
503     memset(&plat_cb, 0, sizeof(plat_cb));
504     memset(&recv_if, 0, sizeof(recv_if));
505     memset(&ipc_cfg, 0, sizeof(ipc_cfg));
507     /* Initialize IPC library */
508     ipc_cfg.mode = IPC_MODE_SNOOP_DAEMON;
509     if (ipsecmgr_ipc_init(&ipc_cfg)) {
510         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
511             "init_ipsecmgr: ipc_init failed\n");
512         return -1;
513     }
514     else
515         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
516             "init_ipsecmgr: ipc_init sucess\n");
518     if (ipsecmgr_ipc_get_daemon_send_iface(&send_iface)) {
519         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
520             "init_ipsecmgr: ipc_get_daemon_send_iface failed\n");
521         return -1;
522     }
523     recv_if.offload_sp_req = offload_sp_req_recv;
524     recv_if.stop_offload_req = stop_offload_req_recv;
525     /* Register ipsecmgr daemon recieve i/f */
526     if (ipsecmgr_ipc_register_daemon_recv_iface(&recv_if)) {
527         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
528             "snoop_run: ipc_register_daemon_recv_iface failed\n");
529         return -1;
530     }
532     /* Initialize the IPSec Manager Snoop library */
533     fp_cfg_cb.add_sa        =   netapilib_ifAddSA;
534     fp_cfg_cb.add_sp        =   netapilib_ifAddSP;
535     fp_cfg_cb.del_sa        =   netapilib_ifDeleteSA;
536     fp_cfg_cb.del_sp        =   netapilib_ifDeleteSP;
537     fp_cfg_cb.get_sa_ctx    =   netapilib_ifGetSACtx;
539     plat_cb.log_msg  = (ipsecmgr_snoop_log_msg_t)ipsecmgr_syslog_msg;
540     plat_cb.sleep           =   task_sleep;
542     mgnt_cb.offload_sp_rsp  =   offload_sp_rsp_send;
543     mgnt_cb.stop_offload_rsp=   stop_offload_rsp_send;
544     mgnt_cb.rekey_event     =   NULL; // No explicit notifications needed on Rekey completion
546     if ((status = ipsecmgr_snoop_init (&fp_cfg_cb, &mgnt_cb, &plat_cb))) 
547     {
548         ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
549                             "DEBUG: init_ipsecmgr() ipsecmgr_snoop_init failed (%d)\n", status);
550         return -1;
551     }
555 #ifdef GDB_DEBUG
556     snoop_run_thread(NULL);
557 #else
558     /* Create the task context for snoop library */
559     pthread_attr_init(&threadAttr);
560     pthread_attr_setstacksize(&threadAttr, 0x10000);
561     if (pthread_create(&snoop_run_th, (void*) NULL, snoop_run_thread, NULL))
562     {
563         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
564             "ERROR: snoop run thread failed to start, error code\n"); 
565         return -1;
566     }
568     /* Setup signal handler for SIGTERM */
569     if (signal(SIGTERM, sig_term_handler) == SIG_ERR) {
570         ipsecmgr_syslog_msg(SYSLOG_LEVEL_WARN,
571             "init_ipsecmgr: cannot handle SIGTERM\n");
572     }
573     /* Wait for the NETAPI Proxy task to finish its processing and exit. */
574     pthread_join (snoop_run_th, NULL);
575 #endif
576     return 0;
579 /**
580  *  @b Description
581  *  @n  
582  *      Utility function to daemonize the current
583  *      application.
584  *
585  *  @param[in]  lock_file
586  *      Lock file to be used by the daemon
587  */
588 static void daemonize (const char *lock_file)
590     pid_t       pid, sid;
591     int32_t     lock_fp = -1;
592     char        str[10];
594     /* already a daemon */
595     if (getppid () == 1)
596         return;
598     /* Fork off the parent process */
599     if ((pid = fork ()) < 0) 
600     {
601         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR, 
602                             "ERROR: daemonize() unable to fork daemon, code=%d (%s)",
603                             errno, 
604                             strerror(errno));
605         exit (-1);
606     }
608     /* If we got a PID, then exit the parent process. */
609     if (pid > 0)
610         exit (0);
612     /* At this point we are executing as the child process */
614     /* Create a new SID for the child process */
615     if ((sid = setsid ()) < 0) 
616     {
617         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR, 
618                             "ERROR: daemonize() unable to create a new session, code %d (%s)",
619                             errno, 
620                             strerror(errno));
621         exit (-1);
622     }
624     /* Change the file mode mask */
625     umask (027);
627     /* Change the current working directory.  This prevents the current
628      * directory from being locked; hence not being able to remove it. */
629     if ((chdir("/")) < 0) 
630     {
631         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR, 
632                             "ERROR: daemonize() unable to change directory to %s, code %d (%s)",
633                             "/", 
634                             errno, 
635                             strerror(errno));
636         exit (-1);
637     }
639     /* Create the lock file */
640     if (lock_file) 
641     {
642         if ((lock_fp = open(lock_file, O_RDWR|O_CREAT, 0640)) < 0 ) 
643         {
644             ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, 
645                                 "ERROR: daemonize() unable to create lock file %s, code=%d (%s)",
646                                 lock_file, 
647                                 errno, 
648                                 strerror(errno));
649             exit (-1);
650         }
651     }
653     if (lockf (lock_fp, F_TLOCK, 0) < 0) 
654         exit(-1); /* can not lock */
656     /* Record pid to lockfile */
657     sprintf (str, "%d\n", getpid());
658     write (lock_fp, str, strlen(str)); 
660     /* Cancel certain signals */
661     signal (SIGCHLD, SIG_DFL); /* A child process dies */
662     signal (SIGTSTP, SIG_IGN); /* Various TTY signals */
663     signal (SIGTTOU, SIG_IGN);
664     signal (SIGTTIN, SIG_IGN);
665     signal (SIGHUP, SIG_IGN); /* Ignore hangup signal */
666     signal (SIGTERM, sig_term_handler); /* catch SIGTERM */
668     /* Redirect standard files to /dev/null */
669     freopen( "/dev/null", "r", stdin);
670     freopen( "/dev/null", "w", stdout);
671     freopen( "/dev/null", "w", stderr);
673     /* Done setting up the daemon */
674     return;
677 int get_kernel_config()
679     uint32_t temp=0;
680     FILE *pDts = NULL;
682     pDts = fopen(DTS_LOG_FILE_QUEUE_ETHx[0], "rb");
684     if(pDts)
685     {
686         fread((void*)&temp, sizeof(uint32_t), 1, pDts);
687         globalDB.qNum = (int)swap32(temp);
688         fclose(pDts);
689     }
690     else
691     {
692         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
693             "main: error opening device tree file: %s\n",DTS_LOG_FILE_QUEUE_ETHx[0]);
694         return -1;
695     }
697     pDts = NULL;
698     pDts = fopen(DTS_LOG_FILE_FLOW_ETHx[0], "rb");
700     if(pDts)
701     {
702         fread((void*)&temp, sizeof(uint32_t), 1, pDts);
703         globalDB.flowId = (int)swap32(temp);
704         fclose(pDts);
705     }
706     else
707     {
708         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
709             "main: error opening device tree file: %s\n",DTS_LOG_FILE_FLOW_ETHx[0]);
710         return -1;
711     }
712     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
713             "get_kernel_config: flow: 0x%x, qNum: 0x%x\n", 
714              globalDB.flowId, globalDB.qNum);
715     return 0;
718 int create_pktio_channel()
720     static int count = 0;
721     int error = 0;
722     char name[19];
723     PKTIO_HANDLE_T *pktio_channel;
724     PKTIO_CFG_T pktio_cfg;
725     NETCP_CFG_ROUTE_T route;
726     NETCP_CFG_FLOW_T flow;
727     NETCP_CFG_EXCEPTION_PKT_T expPkt_appid = 0;
729     memset(&pktio_cfg,0,sizeof(PKTIO_CFG_T));
730     memset((void *)&route, 0, sizeof (NETCP_CFG_ROUTE_T));
731     memset((void *)&flow, 0, sizeof (NETCP_CFG_FLOW_T));
733     sprintf(&name[0],"%s","offload_0");
734     pktio_cfg.qnum = globalDB.qNum;
735     pktio_cfg.flags1 = PKTIO_RX;
736     pktio_cfg.flags2 = PKTIO_GLOBAL | PKTIO_PKT;
737     pktio_cfg.max_n = 8;
738     pktio_cfg.queueType = Qmss_QueueType_GIC400_QUEUE;
740     globalDB.pktio_channel = netapi_pktioCreate(netapi_handle,
741                                                &name[0],
742                                                (PKTIO_CB)recv_cb,
743                                                &pktio_cfg,
744                                                &error);
745     if (!globalDB.pktio_channel)
746     {
747         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
748             "create_pktio_channel: failed\n");
749         return -1;
750     }
753     flow.dma_engine= 1;
754     flow.flowid = globalDB.flowId;
755     route.p_dest_q = globalDB.pktio_channel;
756     route.p_flow = &flow;
757     route.valid_params |= NETCP_CFG_VALID_PARAM_ROUTE_TYPE;
758     route.routeType = NWAL_ROUTE_RX_INTF_W_FLOW;
759     /* enable exception packet handling for fragmented packets */
760     expPkt_appid = netapi_netcpCfgExceptions(netapi_handle,
761                                              7,
762                                              NETCP_CFG_ACTION_TO_SW,
763                                              (NETCP_CFG_ROUTE_HANDLE_T) &route);
765     return 0;
767 /**
768  *  @b Description
769  *  @n  
770  *      Entry point for the NETAPI Proxy application.
771  *
772  *  @param[in]  argc
773  *      Number of arguments passed to the application
774  *  @param[in]  argv
775  *      Arguments passed to the application.
776  *
777  *  @retval
778  *      Success -   0
779  *  @retval
780  *      ERROR   -   >0
781  */
782 int32_t main (int argc, char* argv[])
784     int32_t             retVal;
785     int i, iface;
786     char* pTok = NULL;
787     int ip_entry_count = 0;
788     struct ifaddrs *ifaddr, *ifa;
789     int family, s;
790     char host[NI_MAXHOST];
791     struct sockaddr_in6 ipv6_addr;
792     cpu_set_t cpu_set;
793     int c;
794     static char usage[] = "usage: %s -r < use Resource manager: no/yes> -s <outbound sequence number> -f <SA transmit flow Id>\n";
796     ipsecmgr_syslog_init();
799     memset(&globalDB, 0, sizeof(globalDB));
800     globalDB.sa_tx_flow = -1;
801     int temp;
802     while ((c = getopt (argc, argv, "s:f:r:")) != -1)
803     {
804        switch (c)
805        {
806             case 'r':
807                 if(strncmp("yes", optarg,1) == 0)
808                 {
809                     use_rm = 1;
810                 }
811                 break;
813             case 's':
814                 /* check is user input 0 for oseq_offset (valid but also default)*/
815                 if(strncmp("0", optarg,1) == 0)
816                 {
817                     globalDB.oseq_offset = 0;
818                 }
819                 else
820                 {
821                     globalDB.oseq_offset = (uint32_t)strtol(optarg, NULL,0);
822                     if(!globalDB.oseq_offset)
823                     {
824                         printf(usage, argv[0]);
825                         exit(EXIT_FAILURE);
826                     }
827                 }
828                 break;
829             case 'f':
830                 /* check is user input 0 for sa_tx_flow(valid) */
831                 if(strncmp("0", optarg,1) == 0)
832                 {
833                     globalDB.sa_tx_flow= 0;
834                 }
835                 else
836                 {
837                     globalDB.sa_tx_flow = (uint32_t)strtol(optarg, NULL,0);
838                     if(!globalDB.sa_tx_flow)
839                     {
840                         printf(usage, argv[0]);
841                         exit(EXIT_FAILURE);
842                     }
843                 }
844                 break;
845             case '?':
846                 printf(usage, argv[0]);
847                 exit(EXIT_FAILURE);
848             default:
849                 break;
850         }
851     }
852     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
853                    "main: oseq_offset: %d, sa_tx_flow: %d\n",
854                     globalDB.oseq_offset, globalDB.sa_tx_flow);
856     if (use_rm)
857     {
858         if (initRm())
859         {
860             exit(EXIT_FAILURE);
861         }
862     }
864     /* assign main net_test thread to run on core 0 */
865     CPU_ZERO( &cpu_set);
866     CPU_SET( 0, &cpu_set);
867     hplib_utilSetupThread(0, &cpu_set, hplib_spinLock_Type_LOL);
868     /* create netapi */
869     our_netapi_default_cfg.rmHandle = rmClientServiceHandle;
870     netapi_handle = netapi_init(NETAPI_SYS_MASTER,
871                                 &our_netapi_default_cfg);
872     if(netapi_handle == NULL)
873     {
874         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
875                              "ERROR: netapi_init failed\n");
876         return -1;
877     }
878     else
879         netapi_netcpCfgExceptions(netapi_handle,
880                                   NETCP_CFG_ALL_EXCEPTIONS,
881                                   NETCP_CFG_ACTION_DISCARD,
882                                   (NETCP_CFG_ROUTE_HANDLE_T) NULL);
884     if (get_kernel_config())
885     {
886         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
887                             "ERROR: main: get_kernel_config() failed\n");
888         return -1;
889     }
890     else
891     {
892         /* create pktio channel */
893         if(create_pktio_channel())
894         {
895             ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
896                             "ERROR: main: pktio channel creation failed\n");
897             return -1;
898         }
899     }
900      /*Create the proxy daemon. */
901     ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO, "main: calling daemonize\n");
902     daemonize (LOCK_FILE);
904     /* Initialize and start the IPSec Mgr Snoop functionality */
905     if ((retVal = init_ipsecmgr ()) < 0)
906     {
907         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
908                             "ERROR: IPSec Mgr init failed, error code %d \n",
909                             retVal);
910         return -1;
911     }
912     else
913         ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
914                              "main: ipsecmgr daemon shutdonw complete\n");
916     exit(EXIT_SUCCESS);