Files
m241Neelima/components/ip_net2-6.9/wrnad/wrnad.c
T
2026-07-30 11:19:44 +05:30

576 lines
13 KiB
C

/* wrnad.c - Wind River network acceleration daemon (NAD) */
/*
* Copyright (c) 2010 Wind River Systems, Inc.
*
* The right to copy, distribute or otherwise make use of this software
* may be licensed only pursuant to the terms of an applicable Wind River
* license agreement.
*/
/*
DESCRIPTION
INCLUDE FILES
wrnad.h
*/
/* includes */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <stdarg.h>
#include "wrnad.h"
#ifdef IPWRNAD
#include <ipcom_sysvar.h>
#include <ipcom_syslog.h>
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#include <ipcom_os.h>
#include <ipcom_shell.h>
#endif
#ifdef IPCOM_FORWARDER_NAE
#warning IPCOM_FORWARDER_NAE_must_not_be_defined_for_wrnad
#endif
#if 0
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#endif
/* imports */
extern int wrnad_mipcfd;
/* globals */
#ifdef IPWRNAD
IP_PUBLIC Ip_err wrnad_create(void);
IP_PUBLIC Ip_err wrnad_start(void);
IP_PUBLIC const char *wrnad_version(void);
IP_PUBLIC Ip_err wrnad_configure(void);
#endif
/* locals */
#ifndef IPWRNAD
#ifdef WRNAD_IDENTIFY_ROUTERS
static char *options = "hdsl:n:p:b:4:6:";
#else
static char *options = "hdsl:n:p:b:";
#endif
static int do_usage = 0;
#endif
static int do_log = 0;
static int dont_fork = 0;
#ifdef IPWRNAD
int wrnad_log_level = LOG_INFO; /* leave global for adjustment from kernel shell */
#else
static int wrnad_log_level = LOG_INFO;
#endif
static char logbuf[4096];
static unsigned short int nae_bus = WRNAD_MIPC_NAE_BUS;
static unsigned short int nae_node = WRNAD_MIPC_NAE_NODE;
static unsigned short int nae_port = WRNAD_MIPC_NAE_PORT;
#ifdef WRNAD_IDENTIFY_ROUTERS
/* router lookup hash table sizes */
unsigned int v4_slots = 1024; /* must be power of 2 */
unsigned int v6_slots = 1024; /* must be power of 2 */
#endif
/*******************************************************************************
*
* wrnad_usage - print usage
*
* This routine is used to print usage information of wrnad
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
#ifndef IPWRNAD
static void
wrnad_usage(void)
{
#ifdef WRNAD_IDENTIFY_ROUTERS
printf("Usage: wrnad [-h] [-d] [-s] [-l level] [-n node] [-p port] [-b bus] [-4 size] [-6 size]\n\n");
#else
printf("Usage: wrnad [-h] [-d] [-s] [-l level] [-n node] [-p port] [-b bus]\n\n");
#endif
printf("Opions\n");
printf(" -s Enable logging to syslog.\n");
printf("\n");
printf(" -d Do not fork. Debug output printed to standard ouput.\n");
printf("\n");
printf(" -l Set log priority. Messages with lower priority than the specified\n");
printf(" level are not logged. Supported levels are: emerg[ency], alert,\n");
printf(" crit[ical], err[or], warn[ing], notice, info[rmation] and debug.\n");
printf(" The default log level is info. Applies to both syslog and stdout.\n");
printf("\n");
printf(" -b Set the MIPC bus number (default %d) to which wrnad should connect.\n",
WRNAD_MIPC_NAE_BUS);
printf("\n");
printf(" -n Set the MIPC node number (default %d) to which wrnad should connect.\n",
WRNAD_MIPC_NAE_NODE);
printf("\n");
printf(" -p Set the MIPC port number (default %d) to which wrnad should connect.\n",
WRNAD_MIPC_NAE_PORT);
printf("\n");
#ifdef WRNAD_IDENTIFY_ROUTERS
printf(" -4 Set size of IPv4 router lookup hash table. Must be power of two.\n\n");
printf(" -6 Set size of IPv6 router lookup hash table. Must be power of two.\n\n");
#endif
printf(" -h Print usage information and exit.\n");
}
static unsigned short int
wrnad_uint16_parse(const char *opt)
{
unsigned long val;
char *endptr;
val = strtoul(opt, &endptr, 0);
if (endptr == opt || val > 0xffff)
{
do_usage = 1;
val = 0;
}
return (unsigned short int)val;
}
static unsigned int
wrnad_uint_parse(const char *opt)
{
unsigned long val;
char *endptr;
val = strtoul(opt, &endptr, 0);
if (endptr == opt)
{
do_usage = 1;
val = 0;
}
return (unsigned int)val;
}
/*******************************************************************************
*
* wrnad_parse_cmdline - parse command line options
*
* This routine is used to parse the command line options given to wrnad
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
static void
wrnad_parse_cmdline(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, options)) != -1)
{
switch (opt)
{
case 'd':
dont_fork = 1;
break;
case 'h':
do_usage = 1;
break;
case 's':
do_log = 1;
break;
case 'l':
if (!strcmp(optarg, "emerg") || !strcmp(optarg, "emergency"))
wrnad_log_level = LOG_EMERG;
else if (!strcmp(optarg, "alert"))
wrnad_log_level = LOG_ALERT;
else if (!strcmp(optarg, "crit") || !strcmp(optarg, "critical"))
wrnad_log_level = LOG_CRIT;
else if (!strcmp(optarg, "err") || !strcmp(optarg, "error"))
wrnad_log_level = LOG_ERR;
else if (!strcmp(optarg, "warn") || !strcmp(optarg, "warning"))
wrnad_log_level = LOG_WARNING;
else if (!strcmp(optarg, "notice"))
wrnad_log_level = LOG_NOTICE;
else if (!strcmp(optarg, "info") || !strcmp(optarg, "information"))
wrnad_log_level = LOG_INFO;
else if (!strcmp(optarg, "debug"))
wrnad_log_level = LOG_DEBUG;
else
{
printf("wrnad: unknown log level '%s'\n", optarg);
do_usage = 1;
}
break;
case 'n':
nae_node = wrnad_uint16_parse(optarg);
break;
case 'p':
nae_port = wrnad_uint16_parse(optarg);
break;
case 'b':
nae_bus = wrnad_uint16_parse(optarg);
break;
#ifdef WRNAD_IDENTIFY_ROUTERS
case '4':
v4_slots = wrnad_uint_parse(optarg);
break;
case '6':
v6_slots = wrnad_uint_parse(optarg);
break;
#endif
default:
do_usage = 1;
break;
}
}
}
#endif /* !IPWRNAD */
/*******************************************************************************
*
* wrnad_log - print log messages
*
* This routine is used to wrnad log messages to the system logger and/or
* standard output
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
void
wrnad_log(int priority, const char *format, /* args*/ ...)
{
va_list ap;
#ifdef IPCOM_SYSLOG
/* User specific syslog function (no syslog daemon) call it directly */
va_start(ap, format);
vsnprintf(logbuf, sizeof(logbuf), format, ap);
logbuf[sizeof(logbuf)-1] = '\0';
va_end(ap);
IPCOM_SYSLOG(IPCOM_LOG_WRNAD | priority, "%s", logbuf);
ipcom_millisleep(10);
#else
if (do_log || dont_fork)
{
if (priority <= wrnad_log_level)
{
va_start(ap, format);
vsnprintf(logbuf, sizeof(logbuf), format, ap);
logbuf[sizeof(logbuf)-1] = '\0';
va_end(ap);
if (do_log)
{
syslog(LOG_DAEMON | priority, "%s", logbuf);
}
if (dont_fork)
{
printf("wrnad[%d]: %s\n", getpid(), logbuf);
fflush(stdout);
}
}
}
#endif
}
/*******************************************************************************
*
* main - entry point for wrnad
*
* This routine is used to start the wrnad damon on the host.
*
* RETURNS: EXIT_SUCCESS if exited normally, else EXIT_FAILURE.
*
* ERRNO: N/A
*/
#ifndef IPWRNAD
int
main(int argc, char *argv[])
{
int ret;
pid_t pid, sid;
wrnad_parse_cmdline(argc, argv);
if (do_usage)
{
wrnad_usage();
exit(EXIT_SUCCESS);
}
if (do_log)
{
setlogmask(LOG_UPTO(wrnad_log_level));
openlog("wrnad", LOG_PID, LOG_DAEMON);
}
wrnad_log(LOG_INFO, "Started.");
if (!dont_fork)
{
/* Fork the parent process */
pid = fork();
if (pid < 0)
{
wrnad_log(LOG_ERR, "fork() failed!");
exit(EXIT_FAILURE);
}
if (pid > 0)
{
/* Exit parent process */
exit(EXIT_SUCCESS);
}
/* Change the file mode mask */
umask(0);
/* Create new session id */
sid = setsid();
if (sid < 0)
{
wrnad_log(LOG_ERR, "setsid() failed!");
exit(EXIT_FAILURE);
}
/* Change current working directory to root */
if (chdir("/") < 0)
{
wrnad_log(LOG_ERR, "chdir() failed!");
exit(EXIT_FAILURE);
}
/* Redirect standard files to /dev/null */
freopen( "/dev/null", "r", stdin);
freopen( "/dev/null", "w", stdout);
freopen( "/dev/null", "w", stderr);
}
wrnad_log(LOG_INFO, "Monitor.");
/* Start monitoring */
ret = wrnad_rtnl_monitor(nae_bus, nae_node, nae_port);
wrnad_terminate(ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
#endif /* !IPWRNAD */
/*******************************************************************************
*
* wrnad_terminate - terminate the wrnad process immediately
*
* The argument <code> should be EXIT_FAILURE or EXIT_SUCCESS.
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
void
wrnad_terminate(int code)
{
wrnad_log(LOG_CRIT, "Terminated : %s",
code == EXIT_FAILURE ? "FAIL!" : "SUCCESS!");
wrnad_cleanup();
if (do_log)
closelog();
#ifdef IPWRNAD
ipcom_proc_exit(); /* TODO - clean up sockets, etc., in VxWorks? */
#else
exit(code);
#endif
}
/*******************************************************************************
*
* wrnad_process - the wrnad process
*
* This routine is the wrnad IPCOM process
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
#ifdef IPWRNAD
static void wrnad(void)
{
int ret;
do_log = 1;
#ifdef IP_DEBUG
wrnad_log_level = LOG_DEBUG;
#else
wrnad_log_level = LOG_ERR;
#endif
setlogmask(LOG_UPTO(wrnad_log_level));
openlog("wrnad", LOG_PID, LOG_DAEMON);
nae_bus = ipcom_sysvar_get_as_int("wrnad.mipc.nae_bus",
WRNAD_MIPC_NAE_BUS);
nae_node = ipcom_sysvar_get_as_int("wrnad.mipc.nae_node",
WRNAD_MIPC_NAE_NODE);
nae_port = ipcom_sysvar_get_as_int("wrnad.mipc.nae_port",
WRNAD_MIPC_NAE_PORT);
wrnad_log(LOG_INFO, "Started.");
ipcom_proc_init();
wrnad_log(LOG_INFO, "Monitor.");
ret = wrnad_rtnl_monitor(nae_bus, nae_node, nae_port);
wrnad_terminate(ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
/*******************************************************************************
*
* wrnad_cmd_pfkey
*
*
*
* RETURNS: 0
*
* ERRNO: N/A
*/
#ifdef IPIPSEC2
IP_STATIC int
wrnad_cmd_pfkey(int argc, char *argv[])
{
Ipcom_getline *gl;
int i;
char cmd[1024];
char hexbyte[3];
unsigned char pfkey[512];
(void)argc;
(void)argv;
gl = ipcom_getline_init(10);
if (gl)
{
ipcom_printf("pfkey> ");
while (ipcom_getline(IP_INVALID_SOCKET, cmd, sizeof(cmd), IP_FALSE, gl, ipcom_strlen("pfkey> ")) == 0)
{
if (ipcom_strcmp(cmd, "exit") == 0)
break;
i = 0;
while(cmd[i] != 0)
{
hexbyte[0] = cmd[i];
hexbyte[1] = cmd[i+1];
hexbyte[2] = 0;
pfkey[i>>1] = (unsigned char)ipcom_strtoul(hexbyte, IP_NULL, 16);
i+=2;
}
wrnad_mipc_send_pfkey(wrnad_mipcfd, (struct sadb_msg *)pfkey);
ipcom_printf("pfkey> ");
}
ipcom_getline_exit(gl);
}
return 0;
}
#endif /* IPIPSEC2 */
/*******************************************************************************
*
* wrnad_create - create NAD
*
* This routine is used to create the NAD with IPCOM
*
* RETURNS: 0
*
* ERRNO: N/A
*/
IP_PUBLIC Ip_err
wrnad_create(void)
{
#ifdef IPIPSEC2
(void)ipcom_shell_add_cmd("pfkey",
"pfkey",
"pfkey",
wrnad_cmd_pfkey,
IPCOM_PRIORITY_DEFAULT,
IPCOM_PROC_STACK_SMALL);
#endif /* IPIPSEC2 */
return 0;
}
/*******************************************************************************
*
* wrnad_start - start NAD
*
* This routine is used to start the NAD with IPCOM
*
* RETURNS: 0
*
* ERRNO: N/A
*/
IP_PUBLIC Ip_err
wrnad_start(void)
{
Ip_pid_t pid;
return ipcom_proc_create("wrnad", wrnad, IPCOM_PROC_STACK_DEFAULT, &pid);
}
/*******************************************************************************
*
* wrnad_version - NAD version
*
* This routine is used to fetch the NAD version
*
* RETURNS: version string
*
* ERRNO: 0
*/
IP_PUBLIC const char *
wrnad_version(void)
{
return "Wind River NAD v1.0";
}
#endif