Added IPV6 and bridge interface support
[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 /**********************************************************************
64  ************************** Local Definitions *************************
65  **********************************************************************/
66 char*  DTS_LOG_FILE_QUEUE_ETHx[] = {
67  "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/complete-queue",
68  "/proc/device-tree/soc/pktdma@2004000/channels/netrx1/complete-queue",
69  "/proc/device-tree/soc/pktdma@2004000/channels/netrx2/complete-queue",
70  "/proc/device-tree/soc/pktdma@2004000/channels/netrx3/complete-queue",
71  "/proc/device-tree/soc/pktdma@2004000/channels/netrx4/complete-queue",
72  "/proc/device-tree/soc/pktdma@2004000/channels/netrx5/complete-queue",
73  "/proc/device-tree/soc/pktdma@2004000/channels/netrx6/complete-queue",
74  "/proc/device-tree/soc/pktdma@2004000/channels/netrx7/complete-queue",
75  "/proc/device-tree/soc/pktdma@2004000/channels/netrx8/complete-queue",
76  "/proc/device-tree/soc/pktdma@2004000/channels/netrx9/complete-queue",
77  "/proc/device-tree/soc/pktdma@2004000/channels/netrx10/complete-queue",
78  "/proc/device-tree/soc/pktdma@2004000/channels/netrx11/complete-queue",
79  "/proc/device-tree/soc/pktdma@2004000/channels/netrx12/complete-queue",
80  "/proc/device-tree/soc/pktdma@2004000/channels/netrx13/complete-queue",
81  "/proc/device-tree/soc/pktdma@2004000/channels/netrx14/complete-queue",
82  "/proc/device-tree/soc/pktdma@2004000/channels/netrx15/complete-queue"
83 };
84 char*  DTS_LOG_FILE_FLOW_ETHx[] = {
85 "/proc/device-tree/soc/pktdma@2004000/channels/netrx0/flow",
86 "/proc/device-tree/soc/pktdma@2004000/channels/netrx1/flow",
87 "/proc/device-tree/soc/pktdma@2004000/channels/netrx2/flow",
88 "/proc/device-tree/soc/pktdma@2004000/channels/netrx3/flow",
89 "/proc/device-tree/soc/pktdma@2004000/channels/netrx4/flow",
90 "/proc/device-tree/soc/pktdma@2004000/channels/netrx5/flow",
91 "/proc/device-tree/soc/pktdma@2004000/channels/netrx6/flow",
92 "/proc/device-tree/soc/pktdma@2004000/channels/netrx7/flow",
93 "/proc/device-tree/soc/pktdma@2004000/channels/netrx8/flow",
94 "/proc/device-tree/soc/pktdma@2004000/channels/netrx9/flow",
95 "/proc/device-tree/soc/pktdma@2004000/channels/netrx10/flow",
96 "/proc/device-tree/soc/pktdma@2004000/channels/netrx11/flow",
97 "/proc/device-tree/soc/pktdma@2004000/channels/netrx12/flow",
98 "/proc/device-tree/soc/pktdma@2004000/channels/netrx13/flow",
99 "/proc/device-tree/soc/pktdma@2004000/channels/netrx14/flow",
100 "/proc/device-tree/soc/pktdma@2004000/channels/netrx15/flow",
101 };
103 /**********************************************************************
104  ************************** Global Variables **************************
105  **********************************************************************/
107 static ipsecmgr_ipc_daemon_send_if_t *send_iface;
108 NETAPI_T netapi_handle;
110 //paSysStats_t netcp_stats;
111 ipsecMgrMcb_t globalDB;
112 ipsecMgrIfConfigEntry_T ipConfigList[16];
114 /* Lock file for the daemon */
115 #define LOCK_FILE   "/var/lock/ipsecmgr_daemon"
117 /* snoop task */
118 static pthread_t    snoop_run_th;
120 static NETAPI_CFG_T our_netapi_default_cfg=
122     TUNE_NETAPI_PERM_MEM_SZ,
123     128,  //start of packet offset for hw to place data on rx for default flow
124     TUNE_NETAPI_QM_CONFIG_MAX_DESC_NUM, //max number of descriptors in system
125     TUNE_NETAPI_NUM_GLOBAL_DESC,        //total we will use
126     TUNE_NETAPI_DEFAULT_NUM_BUFFERS,   //#descriptors+buffers in default heap
127     64, //#descriptors w/o buffers in default heap
128     TUNE_NETAPI_DEFAULT_BUFFER_SIZE+128+128,  //size of buffers in default heap
129     128   ,  //tail room
130     256      //extra room
131 };
136 static int QUIT = 0;
138 /* stub functions */
139 static void recv_cb(struct PKTIO_HANDLE_Tag * channel, Ti_Pkt* p_recv[],
140                          PKTIO_METADATA_T meta[], int n_pkts,
141                          uint64_t ts )
143     return;
146 /* byte swap routine */
147 static unsigned int swap32 (unsigned int x)
149     unsigned int y;
151     y = (((x >> 24) & 0xff) <<  0) |
152         (((x >> 16) & 0xff) <<  8) |
153         (((x >>  8) & 0xff) << 16) |
154         (((x >>  0) & 0xff) << 24) ;
156     return (y);
160 void cleanup_sa_sp()
162     int slot, error=0;;
163     /* delete any offloaded rx SA's and policies */
164     /* and delete any offloaded tx SA's */
165     for (slot = 0;slot < 64;slot++)
166     {
167         if(globalDB.rx_sa[slot].in_use)
168         {
169             globalDB.rx_sa[slot].in_use = 0;
170             if(globalDB.rx_sa[slot].spAppId)
171             {
172                 netapi_secDelRxPolicy(netapi_handle,
173                               (NETCP_CFG_IPSEC_POLICY_T) globalDB.rx_sa[slot].spAppId,
174                               &error);
175                 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
176                 "cleanup_sa_sp: SP deleted: sp_app_id: 0x%x, slot: %d, error: %d\n", 
177                 globalDB.rx_sa[slot].spAppId, slot, error);
178             }
179             netapi_secDelSA(netapi_handle,
180                         NETCP_CFG_NO_INTERFACE,
181                         (NETCP_CFG_SA_T) globalDB.rx_sa[slot].saAppId,
182                         &error);
183             ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
184                 "cleanup_sa_sp: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n", 
185                 globalDB.rx_sa[slot].saAppId, slot, error);
186             
187         }
188         if(globalDB.tx_sa[slot].in_use)
189         {
190             globalDB.tx_sa[slot].in_use = 0;
191             netapi_secDelSA(netapi_handle,
192                             NETCP_CFG_NO_INTERFACE,
193                            (NETCP_CFG_SA_T) globalDB.tx_sa[slot].saAppId,
194                             &error);
195             ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
196                 "cleanup_sa_sp: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n", 
197                 globalDB.tx_sa[slot].saAppId, slot, error);
198         }
199     }
202 static void* snoop_run_thread (void* arg)
204     ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
205         "snoop_run_thread: daemon entering forever event loop\n");
206     while (1)
207     {
208         /* Poll for message from user application */
209         ipsecmgr_ipc_poll();
211         /* Poll for message from Kernel */
212         ipsecmgr_snoop_run();
213         if (QUIT == 1)
214             break;
215     }
216     ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
217         "snoop_run_thread: calling shutdown\n");
218     ipsecmgr_snoop_shutdown ();
219     cleanup_sa_sp();
220     netapi_shutdown(netapi_handle);
222     return;
225 /**
226  *  @b Description
227  *  @n  
228  *      SIGTERM handler.
229  *
230  *  @param[in]  signum
231  *      signal number to terminate deamon.
232  */
233 static void sig_term_handler(int signum)
235     QUIT = 1;
238 /**
239  *  @b Description
240  *  @n  
241  *      Function to implement task sleep functionality 
242  *      for IPSecMgr
243  *
244  *  @param[in]  time_in_msec
245  *      Time in milliseconds to sleep
246  *
247  *  @retval
248  *      Not Applicable.
249  */
250 static void task_sleep(uint32_t time_in_msec)
252     pthread_mutex_t fake_mutex = PTHREAD_MUTEX_INITIALIZER;
253     pthread_cond_t fake_cond = PTHREAD_COND_INITIALIZER;
254     struct timespec ts;
255     int rt;
256     unsigned int sec, nsec;
258     sec = time_in_msec/1000;
259     nsec = (time_in_msec - (sec*1000)) * 1000000;
261     /* Use the wall-clock time */
262     clock_gettime(CLOCK_REALTIME, &ts);
264     ts.tv_sec += sec;
265     ts.tv_nsec += nsec;
267     pthread_mutex_lock(&fake_mutex);
268     rt = pthread_cond_timedwait(&fake_cond, &fake_mutex, &ts);
269     pthread_mutex_unlock(&fake_mutex);
273 /**
274  *  @b Description
275  *  @n  
276  *      NETAPI Proxy's IPSecMgr Start Offload Response 
277  *      message handler.
278  *
279  *      This function is called by the IPSecMgr library
280  *      when it has a response ready corresponding to an
281  *      Start Offload SP request issued by the user application.
282  *
283  *  @param[in]  rsp
284  *      IPSecMgr's Start Offload SP response
285  *  @param[in]  addr
286  *      Destination address (user application) to send 
287  *      the response to
288  *  @param[in]  addr_size
289  *      Size of destination address passed
290  *
291  *  @retval
292  *      Success -   0
293  *  @retval
294  *      ERROR   -   <0
295  */
296 static int offload_sp_rsp_send
298     ipsecmgr_snoop_offload_sp_rsp_param_t *rsp,
299     void                                  *addr,
300     uint32_t                              addr_size
303     ipsecmgr_ipc_offload_sp_rsp_param_t offload_sp_rsp;
305     offload_sp_rsp.type = rsp->type;
306     offload_sp_rsp.result = rsp->result;
307     offload_sp_rsp.trans_id = rsp->trans_id;
308     offload_sp_rsp.err_code = rsp->err_code;
309     offload_sp_rsp.sp_handle = rsp->sp_handle;
310     offload_sp_rsp.sa_handle = rsp->sa_handle;
312     if (addr_size != sizeof(ipsecmgr_ipc_addr_t)) {
313         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR,
314             "offload_sp_rsp_send: addr size not correct\n");
315         return -1;
316     }
318     return send_iface->offload_sp_rsp(&offload_sp_rsp,
319                                       (ipsecmgr_ipc_addr_t *)addr);
321 static void offload_sp_req_recv
323     ipsecmgr_ipc_offload_sp_req_param_t *req,
324     ipsecmgr_ipc_addr_t                 *src_addr
327     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"offload_sp_req_recv called for policy id\n",
328     req->policy_id);
329     ipsecmgr_snoop_offload_sp_rsp_param_t rsp;
330     uint32_t addr_size = sizeof(ipsecmgr_ipc_addr_t);
331     ipsecmgr_snoop_offload_sp_req_param_t offload_sp_req;
333     offload_sp_req.trans_id = req->trans_id;
334     offload_sp_req.policy_id = req->policy_id;
335     offload_sp_req.sa_flags = req->sa_flags;
336     offload_sp_req.if_name = req->if_name;
337     offload_sp_req.dscp_cfg = req->dscp_cfg;
338     offload_sp_req.l5_selector = req->l5_selector;
340     memset(&rsp, 0, sizeof(rsp));
341     rsp.trans_id = req->trans_id;
343     if (ipsecmgr_snoop_offload_sp_req(&offload_sp_req, (void*)src_addr,
344                                       addr_size)) {
345         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
346             "offload_sp_req_recv: snoop_offload_sp_req failed\n");
347         rsp.result = RESULT_FAILURE;
348         rsp.type = RSP_TYPE_ACK | RSP_TYPE_DONE;
349     }
350     else
351     {
352         rsp.result = RESULT_SUCCESS;
353         rsp.type = RSP_TYPE_ACK;
354     }
355     
356     if (offload_sp_rsp_send(&rsp, (void *)src_addr, addr_size))
357     {
358         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
359             "offload_sp_req_recv: failed to send ACK for offload_sp\n");
360     }
361     return;
365 /**
366  *  @b Description
367  *  @n  
368  *      NETAPI Proxy's IPSecMgr Stop Offload response message 
369  *      handler.
370  *
371  *      This function is called by the IPSecMgr library
372  *      when it has a response ready corresponding to an
373  *      Stop Offload SP request issued by the user application.
374  *
375  *  @param[in]  rsp
376  *      IPSecMgr's Stop Offload SP response
377  *  @param[in]  addr
378  *      Destination address (user application) to send 
379  *      the response to
380  *  @param[in]  addr_size
381  *      Size of destination address passed
382  *
383  *  @retval
384  *      Success -   0
385  *  @retval
386  *      ERROR   -   <0
387  */
388 static int stop_offload_rsp_send
390     ipsecmgr_snoop_stop_offload_rsp_param_t *rsp,
391     void                                    *addr,
392     uint32_t                                addr_size
395     ipsecmgr_ipc_stop_offload_rsp_param_t stop_offload_rsp;
397     stop_offload_rsp.type = rsp->type;
398     stop_offload_rsp.result = rsp->result;
399     stop_offload_rsp.trans_id = rsp->trans_id;
401     if (addr_size != sizeof(ipsecmgr_ipc_addr_t)) {
402         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR,
403             "stop_offload_rsp_send: addr size not correct\n");
404         return -1;
405     }
407     return send_iface->stop_offload_rsp(&stop_offload_rsp,
408                                       (ipsecmgr_ipc_addr_t *)addr);
411 static void stop_offload_req_recv
413     ipsecmgr_ipc_stop_offload_req_param_t   *req,
414     ipsecmgr_ipc_addr_t                     *src_addr
417     ipsecmgr_snoop_stop_offload_req_param_t stop_offload_req;
418     uint32_t addr_size = sizeof(ipsecmgr_ipc_addr_t);
419     ipsecmgr_snoop_stop_offload_rsp_param_t rsp;
421     stop_offload_req.trans_id = req->trans_id;
422     stop_offload_req.policy_id = req->policy_id;
424     memset(&rsp, 0, sizeof(rsp));
425     rsp.trans_id = req->trans_id;
427     if (ipsecmgr_snoop_stop_offload(&stop_offload_req, (void*)src_addr,
428                                       addr_size)) {
429         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
430             "stop_offload_req_recv: snoop_stop_offload failed\n");
431         rsp.result = RESULT_FAILURE;
432         rsp.type = RSP_TYPE_ACK | RSP_TYPE_DONE;
433     }
434     else
435     {
436         rsp.result = RESULT_SUCCESS;
437         rsp.type = RSP_TYPE_ACK;
438     }
440     if (stop_offload_rsp_send(&rsp, (void *)src_addr, addr_size))
441     {
442         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
443             "stop_offload_req_recv: failed to send ACK for stop_offload\n");
444     }
445     return;
448 /**
449  *  @b Description
450  *  @n  
451  *      Function to initialize IPSec Manager library.
452  *
453  *  @retval
454  *      Success -   0
455  *  @retval
456  *      ERROR   -   >0
457  */
458 static int32_t init_ipsecmgr (void)
460     struct ipsecmgr_snoop_fp_cfg_cb     fp_cfg_cb;
461     struct ipsecmgr_snoop_mgnt_cb       mgnt_cb;
462     struct ipsecmgr_snoop_platform_cb   plat_cb;
463     ipsecmgr_ipc_daemon_recv_if_t       recv_if;
464     ipsecmgr_ipc_cfg_t                  ipc_cfg;
465     int32_t                             status;
466     pthread_attr_t threadAttr;
468     /* Initializations */
469     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, 
470                         "DEBUG: init_ipsecmgr() starting initialization\n");
471     memset(&fp_cfg_cb, 0, sizeof(fp_cfg_cb));
472     memset(&mgnt_cb, 0, sizeof(mgnt_cb));
473     memset(&plat_cb, 0, sizeof(plat_cb));
474     memset(&recv_if, 0, sizeof(recv_if));
475     memset(&ipc_cfg, 0, sizeof(ipc_cfg));
477     /* Initialize IPC library */
478     ipc_cfg.mode = IPC_MODE_SNOOP_DAEMON;
479     if (ipsecmgr_ipc_init(&ipc_cfg)) {
480         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
481             "init_ipsecmgr: ipc_init failed\n");
482         return -1;
483     }
484     else
485         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
486             "init_ipsecmgr: ipc_init sucess\n");
488     if (ipsecmgr_ipc_get_daemon_send_iface(&send_iface)) {
489         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
490             "init_ipsecmgr: ipc_get_daemon_send_iface failed\n");
491         return -1;
492     }
493     recv_if.offload_sp_req = offload_sp_req_recv;
494     recv_if.stop_offload_req = stop_offload_req_recv;
495     /* Register ipsecmgr daemon recieve i/f */
496     if (ipsecmgr_ipc_register_daemon_recv_iface(&recv_if)) {
497         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
498             "snoop_run: ipc_register_daemon_recv_iface failed\n");
499         return -1;
500     }
502     /* Initialize the IPSec Manager Snoop library */
503     fp_cfg_cb.add_sa        =   netapilib_ifAddSA;
504     fp_cfg_cb.add_sp        =   netapilib_ifAddSP;
505     fp_cfg_cb.del_sa        =   netapilib_ifDeleteSA;
506     fp_cfg_cb.del_sp        =   netapilib_ifDeleteSP;
507     fp_cfg_cb.get_sa_ctx    =   netapilib_ifGetSACtx;
509     plat_cb.log_msg  = (ipsecmgr_snoop_log_msg_t)ipsecmgr_syslog_msg;
510     plat_cb.sleep           =   task_sleep;
512     mgnt_cb.offload_sp_rsp  =   offload_sp_rsp_send;
513     mgnt_cb.stop_offload_rsp=   stop_offload_rsp_send;
514     mgnt_cb.rekey_event     =   NULL; // No explicit notifications needed on Rekey completion
516     if ((status = ipsecmgr_snoop_init (&fp_cfg_cb, &mgnt_cb, &plat_cb))) 
517     {
518         ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
519                             "DEBUG: init_ipsecmgr() ipsecmgr_snoop_init failed (%d)\n", status);
520         return -1;
521     }
523     /* Create the task context for snoop library */
524     pthread_attr_init(&threadAttr);
525     pthread_attr_setstacksize(&threadAttr, 0x10000);
526     if (pthread_create(&snoop_run_th, (void*) NULL, snoop_run_thread, NULL))
527     {
528         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
529             "ERROR: snoop run thread failed to start, error code\n"); 
530         return -1;
531     }
533     /* Setup signal handler for SIGTERM */
534     if (signal(SIGTERM, sig_term_handler) == SIG_ERR) {
535         ipsecmgr_syslog_msg(SYSLOG_LEVEL_WARN,
536             "init_ipsecmgr: cannot handle SIGTERM\n");
537     }
538     /* Wait for the NETAPI Proxy task to finish its processing and exit. */
539     pthread_join (snoop_run_th, NULL);
541     return 0;
544 /**
545  *  @b Description
546  *  @n  
547  *      Utility function to daemonize the current
548  *      application.
549  *
550  *  @param[in]  lock_file
551  *      Lock file to be used by the daemon
552  */
553 static void daemonize (const char *lock_file)
555     pid_t       pid, sid;
556     int32_t     lock_fp = -1;
557     char        str[10];
559     /* already a daemon */
560     if (getppid () == 1)
561         return;
563     /* Fork off the parent process */
564     if ((pid = fork ()) < 0) 
565     {
566         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR, 
567                             "ERROR: daemonize() unable to fork daemon, code=%d (%s)",
568                             errno, 
569                             strerror(errno));
570         exit (-1);
571     }
573     /* If we got a PID, then exit the parent process. */
574     if (pid > 0)
575         exit (0);
577     /* At this point we are executing as the child process */
579     /* Create a new SID for the child process */
580     if ((sid = setsid ()) < 0) 
581     {
582         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR, 
583                             "ERROR: daemonize() unable to create a new session, code %d (%s)",
584                             errno, 
585                             strerror(errno));
586         exit (-1);
587     }
589     /* Change the file mode mask */
590     umask (027);
592     /* Change the current working directory.  This prevents the current
593      * directory from being locked; hence not being able to remove it. */
594     if ((chdir("/")) < 0) 
595     {
596         ipsecmgr_syslog_msg(SYSLOG_LEVEL_ERROR, 
597                             "ERROR: daemonize() unable to change directory to %s, code %d (%s)",
598                             "/", 
599                             errno, 
600                             strerror(errno));
601         exit (-1);
602     }
604     /* Create the lock file */
605     if (lock_file) 
606     {
607         if ((lock_fp = open(lock_file, O_RDWR|O_CREAT, 0640)) < 0 ) 
608         {
609             ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, 
610                                 "ERROR: daemonize() unable to create lock file %s, code=%d (%s)",
611                                 lock_file, 
612                                 errno, 
613                                 strerror(errno));
614             exit (-1);
615         }
616     }
618     if (lockf (lock_fp, F_TLOCK, 0) < 0) 
619         exit(-1); /* can not lock */
621     /* Record pid to lockfile */
622     sprintf (str, "%d\n", getpid());
623     write (lock_fp, str, strlen(str)); 
625     /* Cancel certain signals */
626     signal (SIGCHLD, SIG_DFL); /* A child process dies */
627     signal (SIGTSTP, SIG_IGN); /* Various TTY signals */
628     signal (SIGTTOU, SIG_IGN);
629     signal (SIGTTIN, SIG_IGN);
630     signal (SIGHUP, SIG_IGN); /* Ignore hangup signal */
631     signal (SIGTERM, sig_term_handler); /* catch SIGTERM */
633     /* Redirect standard files to /dev/null */
634     freopen( "/dev/null", "r", stdin);
635     freopen( "/dev/null", "w", stdout);
636     freopen( "/dev/null", "w", stderr);
638     /* Done setting up the daemon */
639     return;
642 /* FUNCTION PURPOSE:validate and process inputs to the application */
643 int32_t parse_cmd_line_args(int argc, char** argv)
645     int32_t             i;
647     /* Valid command line options */
648     if (argc == 1)
649     {
650         printf("netapi_proxyParseCommandLineArgs, argc =1\n");
651         return 0;
652     }
653     else
654     {
655            printf("netapi_proxyParseCommandLineArgs, argc=%d\n", argc);
656     }
658     /* Scan and parse the command line options */
659     for (i = 1; i < argc; i ++)
660     {
661         if (argv[i][0] == '-' && argv[i][1] == 'f')
662         {
663             /* Log file name */                
664             if (i+1 >= argc || argv[i+1] == NULL)
665                 return -1;
666             i++;
667         }
668         else
669         {
670             /* Invalid options */
671             return -1;
672         }
673     }
674     /* Success */
675     return 0;
678 int get_kernel_config(int index)
680     uint32_t temp=0;
681     FILE *pDts = NULL;
683     pDts = fopen(DTS_LOG_FILE_QUEUE_ETHx[index], "rb");
685     if(pDts)
686     {
687         fread((void*)&temp, sizeof(uint32_t), 1, pDts);
688         globalDB.qNum[index]= (int)swap32(temp);
689         fclose(pDts);
690     }
691     else
692     {
693         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
694             "main: error opening device tree file: %s\n",DTS_LOG_FILE_QUEUE_ETHx[index]);
695         return -1;
696     }
698     pDts = NULL;
699     pDts = fopen(DTS_LOG_FILE_FLOW_ETHx[index], "rb");
701     if(pDts)
702     {
703         fread((void*)&temp, sizeof(uint32_t), 1, pDts);
704         globalDB.flowId[index] = (int)swap32(temp);
705         fclose(pDts);
706     }
707     else
708     {
709         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
710             "main: error opening device tree file: %s\n",DTS_LOG_FILE_FLOW_ETHx[index]);
711         return -1;
712     }
713     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
714             "get_kernel_config(%d): flow: 0x%x, qNum: 0x%x\n", 
715                     index, globalDB.flowId[index], globalDB.qNum[index]);
716     return 0;
719 int create_pktio_channel(int index)
721     static int count = 0;
722     int error = 0;
723     char name[19];
724     PKTIO_HANDLE_T *pktio_channel;
725     PKTIO_CFG_T pktio_cfg;
726     NETCP_CFG_ROUTE_T route;
727     NETCP_CFG_FLOW_T flow;
728     NETCP_CFG_EXCEPTION_PKT_T expPkt_appid = 0;
730     memset(&pktio_cfg,0,sizeof(PKTIO_CFG_T));
731     memset((void *)&route, 0, sizeof (NETCP_CFG_ROUTE_T));
732     memset((void *)&flow, 0, sizeof (NETCP_CFG_FLOW_T));
734     sprintf(&name[0],"%s%d","offload_", index);
735     pktio_cfg.qnum = globalDB.qNum[index];
736     pktio_cfg.flags1 = PKTIO_RX;
737     pktio_cfg.flags2 = PKTIO_GLOBAL | PKTIO_PKT;
738     pktio_cfg.max_n = 8;
740     globalDB.pktio_channel[index] = netapi_pktioCreate(netapi_handle,
741                                                &name[0],
742                                                (PKTIO_CB)recv_cb,
743                                                &pktio_cfg,
744                                                &error);
745     if (!globalDB.pktio_channel[index])
746     {
747         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
748             "create_pktio_channel: failed\n");
749         return -1;
750     }
752     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
753             "create_pktio_channel: index: %d, qnum: %d, pktio_handle: 0x%x\n",
754             index, 
755             pktio_cfg.qnum,
756             globalDB.pktio_channel[index]);
758     /* Only want to create exception route for 1st interface */
759     if (index != 0)
760         return 0;
761     flow.dma_engine= 1;
762     flow.flowid = globalDB.flowId[index];
763     route.p_dest_q = globalDB.pktio_channel[index];
764     route.p_flow = &flow;
766     /* enable exception packet handling for fragmented packets */
767     expPkt_appid = netapi_netcpCfgExceptions(netapi_handle,
768                                              7,
769                                              NETCP_CFG_ACTION_TO_SW,
770                                              (NETCP_CFG_ROUTE_HANDLE_T) &route);
771     printf("create_pktio_channel: expPkt appid: 0x%x\n", expPkt_appid);
773     return 0;
775 /**
776  *  @b Description
777  *  @n  
778  *      Entry point for the NETAPI Proxy application.
779  *
780  *  @param[in]  argc
781  *      Number of arguments passed to the application
782  *  @param[in]  argv
783  *      Arguments passed to the application.
784  *
785  *  @retval
786  *      Success -   0
787  *  @retval
788  *      ERROR   -   >0
789  */
790 int32_t main (int argc, char* argv[])
792     int32_t             retVal;
793     int i, iface;
794     char* pTok = NULL;
795     int ip_entry_count = 0;
796     struct ifaddrs *ifaddr, *ifa;
797     int family, s;
798     char host[NI_MAXHOST];
799     struct sockaddr_in6 ipv6_addr;
801     ipsecmgr_syslog_init();
803     memset(&globalDB, 0, sizeof(globalDB));
804     memset(&ipConfigList, 0, sizeof(ipConfigList));
805     /* create netapi */
806     netapi_handle = netapi_init(NETAPI_SYS_MASTER, &our_netapi_default_cfg);
808     if(netapi_handle == NULL)
809     {
810         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "ERROR: netapi_init failed\n");
811         return -1;
812     }
813     else
814         netapi_netcpCfgExceptions(netapi_handle, NETCP_CFG_ALL_EXCEPTIONS, NETCP_CFG_ACTION_DISCARD, (NETCP_CFG_ROUTE_HANDLE_T) NULL);
816     for (i = 0; i < 16; i++)
817     {
818         if (get_kernel_config(i))
819         {
820             ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
821                                 "ERROR: main: get_kernel_config() failed\n");
822             continue;
823         }
824         else
825         {
826             /* create pktio channel */
827             if(create_pktio_channel(i))
828             {
829                 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
830                                 "ERROR: main: pktio channel creation failed\n");
831             }
832         }
833     }
834     /* Read and parse command line options */
835     if (parse_cmd_line_args (argc, argv) < 0)
836     {
837         printf ("Usage format: netfpproxy.out [-f <log_file>]\n");
838         return -1;
839     }
840     printf("main: calling daemonize\n");
842     /* Create the proxy daemon. */
843     daemonize (LOCK_FILE);
845     if (getifaddrs(&ifaddr) == -1)
846     {
847         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
848                                 "main: getifaddrs failure\n");
849         return -1;
850     }
852     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
853     {
854         if (ifa->ifa_addr == NULL)
855             continue;
857         family = ifa->ifa_addr->sa_family;
859         ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
860                         "%s  address family: %d%s\n",
861                         ifa->ifa_name, family,
862                         (family == AF_PACKET) ? " (AF_PACKET)" :
863                         (family == AF_INET) ?   " (AF_INET)" :
864                         (family == AF_INET6) ?  " (AF_INET6)" : "");
865         if ((family == AF_INET) ||(family == AF_INET6))
866         {
867             s = getnameinfo(ifa->ifa_addr,
868                 (family == AF_INET) ? sizeof(struct sockaddr_in):
869                                       sizeof(struct sockaddr_in6),
870                 host,
871                 NI_MAXHOST,
872                 NULL,
873                 0,
874                 NI_NUMERICHOST);
876             if (s != 0)
877             {
878                 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
879                     "getnameinfo() failed: %s\n", gai_strerror(s));
880                     continue;
881             }
882             if (family == AF_INET)
883             {
884                 ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
885                                     "ipv4 string %s\n", host);
886                 for (i=0;i<NWAL_IPV4_ADDR_SIZE;i++)
887                 {
888                     ipConfigList[ip_entry_count].ip[i] =
889                                     ifa->ifa_addr->sa_data[i+2];
890                 }
891             }
892             else
893             {
894                 pTok = strtok(host,"%");
895                 for (i=0;i<NWAL_IPV6_ADDR_SIZE;i++)
896                 {
897                     inet_pton(AF_INET6, pTok, &(ipv6_addr.sin6_addr));
899                     ipConfigList[ip_entry_count].ip[i] =
900                         ipv6_addr.sin6_addr.s6_addr[i];
901                     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
902                         "ipv6[%d]: 0x%x\n",
903                         i,
904                         ipConfigList[ip_entry_count].ip[i]);
905                 }
906             }
907             memcpy(&ipConfigList[ip_entry_count].name[0],
908                     ifa->ifa_name,
909                     strlen(ifa->ifa_name));
910             pTok = strtok(ifa->ifa_name, ":.");
911             /* now we have the interface name, is this eth0, eth1 or bridge i/f */
912             if (pTok)
913             {
914                 if(strstr(pTok,"eth"))
915                 {
916                     sscanf(pTok,"eth%d", &iface);
917                     ipConfigList[ip_entry_count].iface = iface;
918                     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
919                         "eth i/f found with iface %d\n", iface);
920                 }
921                 else if(strstr(pTok,"br"))
922                 {
923                     sscanf(pTok,"br%d", &iface);
924                     ipConfigList[ip_entry_count].iface = iface;
925                     ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
926                         "bridge i/f found with iface %d\n", iface);
927                 }
928                 else
929                 {
930                     ipConfigList[ip_entry_count].iface = -1;
931                 }
932                 ip_entry_count++;
933             }
934         }
935     }
937     if (ifaddr)
938         freeifaddrs(ifaddr);
940     /* Initialize and start the IPSec Mgr Snoop functionality */
941     if ((retVal = init_ipsecmgr ()) < 0)
942     {
943         ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
944                             "ERROR: IPSec Mgr init failed, error code %d \n",
945                             retVal);
946         return -1;
947     }
948     else
949         ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
950                              "main: ipsecmgr daemon shutdonw complete\n");