[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=
121 {
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 )
142 {
143 return;
144 }
146 /* byte swap routine */
147 static unsigned int swap32 (unsigned int x)
148 {
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);
158 }
160 void cleanup_sa_sp()
161 {
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);
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 }
200 }
202 static void* snoop_run_thread (void* arg)
203 {
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;
223 }
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)
234 {
235 QUIT = 1;
236 }
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)
251 {
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);
270 }
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
297 (
298 ipsecmgr_snoop_offload_sp_rsp_param_t *rsp,
299 void *addr,
300 uint32_t addr_size
301 )
302 {
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);
320 }
321 static void offload_sp_req_recv
322 (
323 ipsecmgr_ipc_offload_sp_req_param_t *req,
324 ipsecmgr_ipc_addr_t *src_addr
325 )
326 {
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 }
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;
362 }
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
389 (
390 ipsecmgr_snoop_stop_offload_rsp_param_t *rsp,
391 void *addr,
392 uint32_t addr_size
393 )
394 {
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);
409 }
411 static void stop_offload_req_recv
412 (
413 ipsecmgr_ipc_stop_offload_req_param_t *req,
414 ipsecmgr_ipc_addr_t *src_addr
415 )
416 {
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;
446 }
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)
459 {
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;
542 }
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)
554 {
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;
640 }
642 /* FUNCTION PURPOSE:validate and process inputs to the application */
643 int32_t parse_cmd_line_args(int argc, char** argv)
644 {
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;
676 }
678 int get_kernel_config(int index)
679 {
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;
717 }
719 int create_pktio_channel(int index)
720 {
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;
774 }
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[])
791 {
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");
952 }