wanpipe/util/wanconfig/wanconfig.c

3990 lines
98 KiB
C
Raw Blame History

/*****************************************************************************
* wanconfig.c WAN Multiprotocol Router Configuration Utility.
*
* Author: Nenad Corbic <ncorbic@sangoma.com>
* Gideon Hack
*
* Copyright: (c) 1995-2003 Sangoma Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ----------------------------------------------------------------------------
* Jan 11, 2010 David Rokhvarg Moved data type declarations and lookup tables
* to wanconfig.h.
* Moved code for configuration of hardware echo
* canceller to wanconfig_hwec.c.
* Both changes needed for code re-use in
* cross-platform software (Linux:wanconfig;
* Windows:wanrouter.exe).
* Sep 25, 2007 Alex Feldman Verify return code from wanec client.
* Jun 25, 2007 David Rokhvarg Added support for AFT-ISDN BRI (A500) card.
* Mar 29, 2007 David Rokhvarg Added support for AFT-56K card.
* May 11, 2001 Alex Feldman Added T1/E1 support (TE1).
* Apr 16, 2001 David Rokhvarg Added X25_SRC_ADDR and ACCEPT_CALLS_FROM to 'chan_conftab'
* Nov 15, 2000 Nenad Corbic Added true interface encoding type option
* Arp 13, 2000 Nenad Corbic Added the command line argument, startup support.
* Thus, one can configure the router using
* the command line arguments.
* Jan 28, 2000 Nenad Corbic Added support for ASYCN protocol.
* Sep 23, 1999 Nenad Corbic Added support for HDLC STREAMING, Primary
* and secondary ports.
* Jun 02, 1999 Gideon Hack Added support for the S514 PCI adapter.
* Jan 07, 1998 Jaspreet Singh Made changes for 2.1.X.
* Added support for WANPIPE and API integration.
* Jul 20, 1998 David Fong Added Inverse ARP option to channel config.
* Jun 26, 1998 David Fong Added IP_MODE to PPP Configuration.
* Used for Dynamic IP Assignment.
* Jun 18, 1998 David Fong Added Cisco HDLC definitions and structures
* Dec 16, 1997 Jaspreet Singh Moved IPX and NETWORK to 'chan_conftab'
* Dec 08, 1997 Jaspreet Singh Added USERID, PASSWD and SYSNAME in
* 'chan_conftab'
* Dec 05, 1997 Jaspreet Singh Added PAP and CHAP in 'chan_conftab'
* Added AUTHENTICATOR in 'ppp_conftab'
* Oct 12, 1997 Jaspreet Singh Added IPX and NETWORK to 'common_conftab'
* Added MULTICAST to 'chan_conftab'
* Oct 02, 1997 Jaspreet Singh Took out DLCI from 'fr_conftab'. Made changes
* so that a list of DLCI is prepared to
* configuring them when emulating a NODE
* Jul 07, 1997 Jaspreet Singh Added 'ttl' to 'common_conftab'
* Apr 25, 1997 Farhan Thawar Added 'udp_port' to 'common_conftab'
* Jan 06, 1997 Gene Kozin Initial version based on WANPIPE configurator.
*****************************************************************************/
/*****************************************************************************
* Usage:
* wanconfig [-f {conf_file}] Configure WAN links and interfaces
* wanconfig -d {device} Shut down WAN link
* wanconfig -h|? Display help screen
*
* Where:
* {conf_file} configuration file name. Default is /etc/wanpipe1.conf
* {device} name of the WAN device in /proc/net/wanrouter directory
*
* Optional switches:
* -v verbose mode
* -h or -? display help screen
*****************************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include "lib/safe-read.h"
#include "wanpipe_version.h"
#include "wanpipe_defines.h"
#include "wanpipe_cfg.h"
#include "wanproc.h"
#include "wanpipe_events.h"
#include "wanec_api.h"
#include "wanpipe.h"
#include "wanconfig.h"
#define smemof(TYPE, MEMBER) offsetof(TYPE,MEMBER),(sizeof(((TYPE *)0)->MEMBER))
/****** Defines *************************************************************/
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
#define is_digit(ch) (((ch)>=(unsigned)'0'&&(ch)<=(unsigned)'9')?1:0)
#define show_error(x) { show_error_dbg(x, __LINE__);}
/****** Function Prototypes *************************************************/
int arg_proc (int argc, char* argv[]);
void show_error_dbg (int err, int line);
int startup(void);
int wp_shutdown (void);
int configure (void);
int parse_conf_file (char* fname);
int build_linkdef_list (FILE* file);
int build_chandef_list (FILE* file);
char* read_conf_section (FILE* file, char* section);
int read_conf_record (FILE* file, char* key, int max_len);
int configure_link (link_def_t* def, char init);
int configure_chan (int dev, chan_def_t* def, char init, int id);
int set_conf_param (char* key, char* val, key_word_t* dtab, void* conf, int max_len);
void init_first_time_tokens(char **token);
void init_tokens(char **token);
int tokenize (char* str, char **tokens);
char* str_strip (char* str, char* s);
char* strupcase (char* str);
void* lookup (int val, look_up_t* table);
int name2val (char* name, look_up_t* table);
int read_data_file (char* name, data_buf_t* databuf);
int read_oct_chan_config(char*, char*, wan_custom_conf_t *conf);
unsigned long filesize (FILE* file);
unsigned int dec_to_uint (char* str, int len);
unsigned int get_config_data (int, char**);
void show_help(void);
void show_usage(void);
void set_action(int new_action);
int gencat (char *filename);
int show_status(void);
int show_config(void);
int show_hwprobe(int);
int debugging(void);
int debug_read(void);
int start_daemon(void);
int exec_link_cmd(int dev, link_def_t *def);
int exec_chan_cmd(int dev, chan_def_t *def);
void free_linkdefs(void);
/* Parsing the command line arguments, in order
* to starting WANPIPE from the command line.
*/
int get_devices (FILE *fp, int *argc, char ***argv, char**);
int get_interfaces (FILE *fp, int *argnum, char ***argv_ptr, char *device_name);
int get_hardware (FILE *fp, int *argc_ptr, char ***argv_ptr, char *device_name);
int get_intr_setup (FILE *fp, int *argc_ptr, char ***argv_ptr);
int router_down (char *devname, int ignore_error);
int router_ifdel (char *card_name, char *dev_name);
int conf_file_down (void);
unsigned int get_active_channels(int channel_flag, int start_channel, int stop_channel);
void read_adsl_vci_vpi_list(wan_adsl_vcivpi_t* vcivpi_list, unsigned short* vcivpi_num);
void update_adsl_vci_vpi_list(wan_adsl_vcivpi_t* vcivpi_list, unsigned short vcivpi_num);
void wakeup_java_ui(void);
extern int close (int);
char *time_string(time_t t,char *buf);
int has_config_changed(link_def_t *linkdef, char *name);
void free_device_link(char *devname);
int device_syncup(char *devname);
void sig_func (int sigio);
int start_chan (int dev, link_def_t *def);
int start_link (void);
int stop_link(void);
int exec_command(char *rx_data);
void catch_signal(int signum,int nomask);
/****** Global Data *********************************************************/
char master_lapb_dev[WAN_DRVNAME_SZ+1];
char master_x25_dev[WAN_DRVNAME_SZ+1];
char master_dsp_dev[WAN_DRVNAME_SZ+1];
char master_lip_dev[WAN_DRVNAME_SZ+1];
#define MAX_WAKEUI_WAIT 2
static char wakeup_ui=0;
static time_t time_ui=0;
#define MAX_FIRMW_SIZE 40000
static unsigned char firmware_file_buffer[MAX_FIRMW_SIZE];
char prognamed[20] = "wanconfig";
char progname_sp[] = " ";
char def_conf_file[] = "/etc/wanpipe/wanpipe1.conf"; /* default name */
char def_adsl_file[] = "/etc/wanpipe/wan_adsl.list"; /* default name */
char tmp_adsl_file[] = "/etc/wanpipe/wan_adsl.tmp"; /* default name */
#if defined(__LINUX__)
char router_dir[] = "/proc/net/wanrouter"; /* location of WAN devices */
#else
char router_dir[] = "/var/lock/wanrouter"; /* location of WAN devices */
#endif
char conf_dir[] = "/etc/wanpipe";
char banner[] = "WAN Router Configurator"
"(c) 1995-2003 Sangoma Technologies Inc.";
static char wan_version[100];
char usagetext[] =
"\n"
" wanconfig: Wanpipe device driver configuration tool\n\n"
" Usage: wanconfig [ -hvw ] [ -f <config-file> ] [ -U {arg options} ]\n"
" [ -y <verbose-log> ] [ -z <kernel-log> ]\n"
" [ card <wan-device-name> [ dev <dev-name> | nodev ] ]\n"
" [ help | start | stop | up | down | add | del | reload\n"
" | restart | status | show | config ]\n"
"\n";
char helptext[] =
"Usage:\n"
"------\n"
"\twanconfig [ -hvw ] [ -f <config-file> ] [ -U {arg-options} ]\n"
"\t [ -y <verbose-log> ] [ -z <kernel-log> ]\n"
"\t [ card <wan-dev-name> [ dev <dev-name> | nodev ] ]\n"
"\t [ help | start | stop | up | down | add | del\n"
"\t | reload | restart | status | show | config ]\n"
"\n"
"\tWhere:\n"
"\n"
"\t [-f {config-file}] Specify an overriding configuration file.\n"
"\t [-U {arg-options}] Configure WAN link using command line\n"
"\t arguments.\n"
"\t [-v] Verbose output to stdout.\n"
"\t [-h] | help Show this help.\n"
"\t [-w] Enable extra error messages about debug\n"
"\t log locations.\n"
"\t [-y] Give location of wanconfig verbose log\n"
"\t for -w switch.\n"
"\t [-z] Give location of syslogd kernel logging\n"
"\t for -w switch.\n"
"\t card <wan-dev-name>\n"
"\t Specify which WAN interface/card to\n"
"\t operate on. Name given in\n"
"\t /proc/net/wanrouter directory.\n"
"\t dev <dev-name> Specify which linux network interface\n"
"\t to operate on.\n"
"\t nodev Turns off creation of interface(s)\n"
"\t when (re)starting card(s).\n"
"\t start | up | add Configure WAN interface(s)/card(s)\n"
"\t and/or create linux network interface(s).\n"
"\t stop | down | del Shut down WAN interface(s)/card(s) and/or\n"
"\t destroy linux network interface(s).\n"
"\t reload | restart Restart WAN interface(s)/card(s) and/or\n"
"\t recreate linux network interface(s).\n"
"\t status | stat | show\n"
"\t Display status information on all\n"
"\t interfaces/cards or for a specific\n"
"\t WAN interface/card.\n"
"\t config Display configuration information for all\n"
"\t WAN interfaces/cards.\n"
"\n"
"\t{config-file}\tconfiguration file (default is\n"
"\t\t\t/etc/wanpipe/wanpipe#.conf or\n"
"\t\t\t/etc/wanpipe/wanpipe.conf in that order)\n"
"\t{arg-options}\tare as given below\n"
"\nArg Options:\n"
" [devices] \\ \n"
" <devname> <protocol> \\ \n"
" [interfaces] \\ \n"
" <if_name> <devname> <{addr/-}> <operation_mode> \\ \n"
" <if_name> <devname> <{addr/-}> <operation_mode> \\ \n"
" ... \\ \n"
" [devname] \\ \n"
" <hw_option> <hw_option_value> \\ \n"
" <hw_option> <hw_option_value> \\ \n"
" ... \\ \n"
" [if_name] \\ \n"
" <protocol_opton> <protocol_option_value> \\ \n"
" <protocol_opton> <protocol_option_value> \\ \n"
" ... \\ \n\n"
" devname device name. ex:wanpipe# (#=1..16) \n"
" protocol wan protocol. ex: WAN_FR,WAN_CHDLC,WAN_PPP,WAN_X25 \n"
" if_name interface name. ex: wp1_fr16, wp1_ppp \n"
" addr/- For Frame Relay: DLCI number ex: 16, 25\n"
" X25 PVC : LCN number ex: 1, 2, 4\n"
" X25 SVC : X25 address ex: @123, @4343 \n"
" For other protocol set to: '-'\n"
" operation_mode Mode of operation: WANPIPE - for routing \n"
" API - raw api interface\n"
" The API only applies to WAN_CHDLC, WAN_FR and \n"
" WAN_X25 protocols.\n"
" hw_option\n"
" protocol_option \n"
" Please refer to sample wanpipe#.conf files in \n"
" /etc/wanpipe/samples directory for the\n"
" appropriate HW/Protocol optoins. \n"
" ex: ioprot, irq, s514_cpu, pci_slot ... \n"
" hw_option_value \n"
" protocol_option_value \n"
" Value of the above options. Refer to the above \n"
" sample files. ex: ioport = '0x360' multicast=YES \n\n"
" Example 1: Bring up wanpipe1 device from the command line\n"
" wanconfig -U [devices] \\ \n"
" wanpipe1 WAN_CHDLC \\ \n"
" [interfaces] \\ \n"
" wp1_chdlc wanpipe1 - WANPIPE \\ \n"
" [wanpipe1] \\ \n"
" IOPORT 0x360 \\ \n"
" IRQ 7 \\ \n"
" Firmware /etc/wanpipe/firmware/cdual514.sfm \\ \n"
" CommPort PRI \\ \n"
" Receive_Only NO \\ \n"
" Interface V35 \\ \n"
" Clocking External \\ \n"
" BaudRate 1600000 \\ \n"
" MTU 1500 \\ \n"
" UDPPORT 9000 \\ \n"
" TTL 255 \\ \n"
" [wp1_chdlc] \\ \n"
" MULTICAST NO \\ \n"
" IGNORE_DCD YES \\ \n"
" IGNORE_CTS YES \\ \n"
" IGNORE_KEEPALIVE YES \\ \n"
" HDLC_STREAMING YES \\ \n"
" KEEPALIVE_TX_TIMER 10000 \n\n"
" Example 2: Shutdown wanpipe1 device from the command line \n"
" \n\t\t#> wanconfig card wanpipe1 stop\n\n"
" Example 3: Create fr17 linux network interface and \n"
" start wanpipe1 device (if not already started)\n"
" from the command line \n"
" \n\t\t#> wanconfig card wanpipe1 dev fr17 start\n\n"
" wanconfig card wanpipe1 dev fr17 start\n\n"
" Example 4: Shutdown all WAN devices from the command line \n"
" \n\t\t#> wanconfig stop\n"
;
char* err_messages[] = /* Error messages */
{
"Invalid command line syntax", /* ERR_SYNTAX */
"Invalid configuration file syntax", /* ERR_CONFIG */
"Wanpipe module not loaded", /* ERR_MODULE */
"Unknown error code", /* ERR_LIMIT */
};
enum /* modes */
{
DO_UNDEF,
DO_START,
DO_STOP,
DO_RESTART,
DO_HELP,
DO_ARG_CONFIG,
DO_ARG_DOWN,
DO_SHOW_STATUS,
DO_SHOW_CONFIG,
DO_SHOW_HWPROBE,
DO_SHOW_HWPROBE_LEGACY,
DO_SHOW_HWPROBE_VERBOSE,
DO_DEBUGGING,
DO_DEBUG_READ,
} action; /* what to do */
#define SLEEP_TIME 1 /* Sleep time after executing ioctl */
int verbose = 0; /* verbosity level */
char* conf_file = NULL; /* configuration file */
char* adsl_file = NULL; /* ADSL VCI/VPI list */
char *dev_name = NULL;
char *card_name = NULL;
static char *command=NULL;
char *krnl_log_file = "/var/log/messages";
char *verbose_log = "/var/log/wanrouter";
int weanie_flag = 1;
int nodev_flag = 0;
link_def_t* link_defs; /* list of WAN link definitions */
union
{
wandev_conf_t linkconf; /* link configuration structure */
wanif_conf_t chanconf; /* channel configuration structure */
} u;
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
wan_conf_t config;
#endif
static void SIZEOFASSERT (key_word_t* dtab, int type_size)
{
if (dtab->size != type_size) {
printf("\n==========CRITICAL ERROR============\n\n");
printf("Size Mismatch: Type Size %i != %i\n",dtab->size, type_size);
printf("======================================\n\n");
fprintf(stderr,"\n==========CRITICAL ERROR============\n\n");
fprintf(stderr,"Size Mismatch: Type Size %i != %i\n",dtab->size, type_size);
fprintf(stderr,"======================================\n\n");
fprintf(stderr,"Plese email /var/log/wanrouter file to Sangoma Support\n");
fprintf(stderr,"Email to techdesk@sangoma.com\n");
fprintf(stderr,"======================================\n\n");
}
}
void init_first_time_tokens(char **token)
{
int i;
for (i=0;i<MAX_TOKENS;i++){
token[i]=NULL;
}
}
/****** Entry Point *********************************************************/
int main (int argc, char *argv[])
{
int err = 0; /* return code */
int c;
snprintf(wan_version, 100, "%s.%s",
WANPIPE_VERSION, WANPIPE_SUB_VERSION);
/* Process command line switches */
action = DO_SHOW_STATUS;
while(1) {
c = getopt(argc, argv, "D:hvwUf:a:y:zd:y:z;V;x:r:");
if( c == -1)
break;
switch(c) {
case 'x':
return start_daemon();
case 'd':
conf_file = optarg;
set_action(DO_STOP);
break;
case 'a':
adsl_file = optarg;
break;
case 'f':
conf_file = optarg;
set_action(DO_START);
break;
case 'v':
verbose = 1;
break;
case 'w':
weanie_flag = 1;
break;
case 'U':
set_action(DO_ARG_CONFIG);
break;
case 'y':
verbose_log = optarg;
break;
case 'z':
krnl_log_file = optarg;
break;
case 'h':
show_help();
break;
case 'D':
dev_name = optarg;
set_action(DO_DEBUGGING);
break;
case 'r':
dev_name = optarg;
set_action(DO_DEBUG_READ);
break;
case 'V':
printf("wanconfig: %s-%s %s %s\n",
WANPIPE_VERSION, WANPIPE_SUB_VERSION,
WANPIPE_COPYRIGHT_DATES,WANPIPE_COMPANY);
printf("\n");
show_usage();
break;
case '?':
case ':':
default:
show_usage();
break;
}
}
/* Check that the no action is given with non-swtiched arguments
*/
if( action != DO_SHOW_STATUS && action != DO_ARG_CONFIG ) {
if(optind < argc)
show_usage();
}
/* Process interface control command arguments */
if( action == DO_SHOW_STATUS && optind < argc ) {
for( ; optind < argc; optind++ ){
if( strcmp( argv[optind], "wan" ) == 0 \
|| strcmp( argv[optind], "card") == 0 ) {
/* Check that card name arg is given */
if((optind+1) >= argc ) show_usage();
card_name = argv[optind+1];
optind++;
}
else if( strcmp( argv[optind], "dev" ) == 0 ) {
/* Make sure nodev argument is not given */
if(nodev_flag) show_usage();
/* Make sure card argument is given */
if(card_name == NULL) show_usage();
/* Check that interface name arg is given */
if((optind+1) >= argc ) show_usage();
dev_name = argv[optind+1];
optind++;
}
else if( strcmp( argv[optind], "nodev" ) == 0 ) {
/* Make sure dev argument is not given */
if(dev_name != NULL) show_usage();
nodev_flag = 1;
}
else if( strcmp( argv[optind], "start" ) == 0
|| strcmp( argv[optind], "up") == 0
|| strcmp( argv[optind], "add") == 0 ) {
set_action(DO_START);
}
else if( strcmp( argv[optind], "stop" ) == 0
|| strcmp( argv[optind], "del" ) == 0
|| strcmp( argv[optind], "delete" ) == 0
|| strcmp( argv[optind], "down") == 0 ) {
set_action(DO_STOP);
}
else if( strcmp( argv[optind], "restart" ) == 0
|| strcmp( argv[optind], "reload") == 0 ) {
set_action(DO_RESTART);
}
else if( strcmp( argv[optind], "status" ) == 0
|| strcmp( argv[optind], "stat" ) == 0
|| strcmp( argv[optind], "show" ) == 0 ) {
set_action(DO_SHOW_STATUS);
}
else if( strcmp( argv[optind], "config" ) == 0 ) {
set_action(DO_SHOW_CONFIG);
}
else if( strcmp( argv[optind], "hwprobe" ) == 0 ) {
if ((optind + 1 < argc) && (strcmp( argv[optind+1], "verbose" ) == 0 )){
set_action(DO_SHOW_HWPROBE_VERBOSE);
optind++;
}else if ((optind + 1 < argc) && (strcmp( argv[optind+1], "legacy" ) == 0 )){
set_action(DO_SHOW_HWPROBE_LEGACY);
optind++;
}else{
set_action(DO_SHOW_HWPROBE);
}
}
else if( strcmp( argv[optind], "help" ) == 0 ) {
show_help();
}
else {
show_usage();
}
}
}
/* Check length of names */
if( card_name != NULL && strlen(card_name) > WAN_DRVNAME_SZ) {
fprintf(stderr, "%s: WAN device names must be %d characters long or less\n",
prognamed, WAN_DRVNAME_SZ);
exit(1);
}
if( dev_name != NULL && strlen(dev_name) > WAN_IFNAME_SZ) {
fprintf(stderr, "%s: Interface names must be %d characters long or less\n",
prognamed, WAN_IFNAME_SZ);
exit(1);
}
/* Perform requested action */
if (verbose) puts(banner);
if (!err)
switch (action) {
case DO_START:
err = startup();
break;
case DO_STOP:
err = wp_shutdown();
break;
case DO_RESTART:
err = wp_shutdown();
if(err)
break;
sleep(SLEEP_TIME);
err = startup();
break;
case DO_ARG_CONFIG:
conf_file = "wanpipe_temp.conf";
argc = argc - optind;
argv = &argv[optind];
err = get_config_data(argc,argv);
if (err)
break;
err = configure();
remove(conf_file);
break;
case DO_ARG_DOWN:
printf("DO_ARG_DOWN\n");
wp_shutdown();
break;
case DO_HELP:
show_help();
break;
case DO_SHOW_STATUS:
return show_status();
break;
case DO_SHOW_CONFIG:
return show_config();
break;
case DO_SHOW_HWPROBE:
case DO_SHOW_HWPROBE_LEGACY:
case DO_SHOW_HWPROBE_VERBOSE:
return show_hwprobe(action);
break;
case DO_DEBUGGING:
return debugging();
break;
case DO_DEBUG_READ:
return debug_read();
break;
default:
err = ERR_SYNTAX;
break;
}
/* Always a good idea to sleep a bit - easier on system and link
* we could be operating 2 cards and 1st one improperly configured
* so dwell a little to make things easier before wanconfig reinvoked.
*/
if( !err || err == ERR_SYSTEM ) usleep(SLEEP_TIME);
return err;
}
/*============================================================================
* Show help text
*/
void show_help(void) {
puts(helptext);
exit(1);
}
/*============================================================================
* Show usage text
*/
void show_usage(void) {
fprintf(stderr, usagetext);
exit(1);
}
/*============================================================================
* set action
*/
void set_action(int new_action) {
if(action == DO_SHOW_STATUS )
action = new_action;
else{
show_usage();
}
}
/*============================================================================
* Show error message.
*/
void show_error_dbg (int err, int line)
{
switch(err){
case ERR_SYSTEM:
fprintf(stderr, "%s:%d: SYSTEM ERROR %d: %s!\n",
prognamed, line, errno, strerror(errno));
break;
case ERR_MODULE:
fprintf(stderr, "%s:%d: ERROR: %s!\n",
prognamed, line, err_messages[min(err, ERR_LIMIT) - 2]);
break;
default:
fprintf(stderr, "%s:%d: ERROR: %s : %s!\n", prognamed,
line, err_messages[min(err, ERR_LIMIT) - 2], conf_file);
}
}
/*============================================================================
* cat a given file to stdout - this is used for status and config
*/
int gencat (char *filename)
{
FILE *file;
char buf[256];
file = fopen(filename, "r");
if( file == NULL ) {
fprintf( stderr, "%s: cannot open %s\n",
prognamed, filename);
show_error(ERR_SYSTEM);
exit(ERR_SYSTEM);
}
while(fgets(buf, sizeof(buf) -1, file)) {
printf(buf);
}
fclose(file);
return(0);
}
/*============================================================================
* Start up - This is a shell function to select the configuration source
*/
int startup(void)
{
char buf[256];
int err = 0;
int res = 0;
int found = 0;
DIR *dir;
struct dirent *dentry;
struct stat file_stat;
if(conf_file != NULL ) {
/* Method I. Observe given config file name
*/
return(configure());
}else{
/* Method II. Scan /proc/net/wanrouter for device names
*/
/* Open directory */
dir = opendir(router_dir);
if(dir == NULL) {
err = ERR_SYSTEM;
show_error(err);
return(err);
}
while( (dentry = readdir(dir)) ) {
if( strlen(dentry->d_name) > WAN_DRVNAME_SZ)
continue;
/* skip directory dots */
if( strcmp(dentry->d_name, ".") == 0 \
|| strcmp(dentry->d_name, "..") == 0)
continue;
/* skip /prroc/net/wanrouter/{status,config} */
if( strcmp(dentry->d_name, "status") == 0 \
|| strcmp(dentry->d_name, "config") == 0)
continue;
/* skip interfaces we are not configuring */
if( card_name != NULL && strcmp(dentry->d_name, card_name) != 0 )
continue;
snprintf(buf, sizeof(buf), "%s/%s.conf", conf_dir, dentry->d_name);
/* Stat config file to see if it is there */
res = stat(buf, &file_stat);
if( res < 0 ) {
if( errno == ENOENT )
continue;
show_error(ERR_SYSTEM);
closedir(dir);
exit(ERR_SYSTEM);
}
found = 1;
conf_file = buf;
err = configure();
}
closedir(dir);
}
if (!found){
/* Method III. Use default configuration file */
conf_file = def_conf_file;
err = configure();
}
return(err);
}
/*============================================================================
* Shut down link.
*/
int wp_shutdown (void)
{
int err = 0;
DIR *dir;
struct dirent *dentry;
if (conf_file){
err = conf_file_down();
}else if( card_name != NULL && dev_name == NULL ) {
err = router_down(card_name, 0);
}else if( card_name != NULL && dev_name != NULL ) {
err = router_ifdel(card_name, dev_name);
}else{
/* Open directory */
dir = opendir(router_dir);
if(dir == NULL) {
err = ERR_SYSTEM;
show_error(err);
return(err);
}
while( (dentry = readdir(dir)) ) {
int res = 0;
if( strlen(dentry->d_name) > WAN_DRVNAME_SZ)
continue;
if( strcmp(dentry->d_name, ".") == 0 \
|| strcmp(dentry->d_name, "..") == 0)
continue;
res = router_down(dentry->d_name, 1);
if(res){
err = res;
}
}
closedir(dir);
}
return err;
}
int router_down (char *devname, int ignore_error)
{
char filename[sizeof(router_dir) + WAN_DRVNAME_SZ + 2];
int dev, err=0;
link_def_t def;
def.linkconf = malloc(sizeof(wandev_conf_t));
if (!def.linkconf){
printf("%s: Error failed to allocated memory on router down\n",
devname);
return -ENOMEM;
}
if (verbose)
printf(" * Shutting down WAN device %s ...\n", devname);
if (strlen(devname) > WAN_DRVNAME_SZ) {
show_error(ERR_SYNTAX);
return -EINVAL;
}
#if defined(WAN_HWEC)
// FIXME: We don't know if wanpipe has HWEC enabled or not....
//wanconfig_hwec_release(devname, NULL);
#endif
#if defined(__LINUX__)
snprintf(filename, sizeof(filename), "%s/%s", router_dir, devname);
#else
snprintf(filename, sizeof(filename), "%s", WANDEV_NAME);
#endif
dev = open(filename, O_RDONLY);
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
strlcpy(config.devname, &devname[0], WAN_DRVNAME_SZ);
def.linkconf->magic = ROUTER_MAGIC;
config.arg = (void*)def.linkconf;
if ((dev < 0) || (ioctl(dev, ROUTER_DOWN, &config) < 0
&& ( !ignore_error || errno != ENOTTY))) {
#else
if ((dev < 0) || (ioctl(dev, ROUTER_DOWN, def.linkconf) < 0
&& ( !ignore_error || errno != ENOTTY))) {
#endif
err = ERR_SYSTEM;
fprintf(stderr, "\n\n\t%s: WAN device %s did not shutdown\n", prognamed, devname);
fprintf(stderr, "\t%s: ioctl(%s,ROUTER_DOWN) failed:\n",
progname_sp, devname);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n");
fprintf(stderr, "\n\tIf you router was not running ignore this message\n !!");
fprintf(stderr, "\tOtherwise, check the %s and \n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf( stderr, "\n" );
if(dev >=0){
close (dev);
}
return errno;
}
if (def.linkconf->config_id == WANCONFIG_ADSL){
update_adsl_vci_vpi_list(&def.linkconf->u.adsl.vcivpi_list[0],
def.linkconf->u.adsl.vcivpi_num);
}
free(def.linkconf);
def.linkconf=NULL;
if (dev >= 0){
close(dev);
}
return 0;
}
int router_ifdel (char *card_name, char *dev_name)
{
char filename[sizeof(router_dir) + WAN_DRVNAME_SZ + 2];
char devicename[WAN_IFNAME_SZ +2];
int dev, err=0;
if (verbose)
printf(" * Shutting down WAN device %s ...\n", card_name);
if (strlen(card_name) > WAN_DRVNAME_SZ) {
show_error(ERR_SYNTAX);
return -EINVAL;
}
#if defined(__LINUX__)
snprintf(filename, sizeof(filename), "%s/%s", router_dir, card_name);
#else
snprintf(filename, sizeof(filename), "%s", WANDEV_NAME);
#endif
if (strlen(dev_name) > WAN_IFNAME_SZ) {
show_error(ERR_SYNTAX);
return -EINVAL;
}
#if defined(WAN_HWEC)
//FIXME : We don't know if wanpipe has HWEC enabled or not....
//wanconfig_hwec_release(card_name, dev_name);
#endif
#if defined(__LINUX__)
snprintf(devicename, sizeof(devicename), "%s", dev_name);
#else
strlcpy(config.devname, dev_name, WAN_DRVNAME_SZ);
config.arg = NULL;
#endif
dev = open(filename, O_RDONLY);
#if defined(__LINUX__)
if ((dev < 0) || (ioctl(dev, ROUTER_IFDEL, devicename) < 0)) {
#else
if ((dev < 0) || (ioctl(dev, ROUTER_IFDEL, &config) < 0)) {
#endif
err = errno;
fprintf(stderr, "\n\n\t%s: Interface %s not destroyed\n", prognamed, devicename);
fprintf(stderr, "\t%s: ioctl(%s,ROUTER_IFDEL,%s) failed:\n",
progname_sp, card_name, devicename);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n");
fprintf(stderr, "\n\tIf you router was not running ignore this message\n !!");
fprintf(stderr, "\tOtherwise, check the %s and \n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf( stderr, "\n" );
if(dev >=0){
close (dev);
}
return errno;
}
if (dev >= 0){
close(dev);
}
return 0;
}
/*============================================================================
* Configure router.
* o parse configuration file
* o configure links
* o configure logical channels (interfaces)
*/
int configure (void)
{
int err = 0;
int res;
/* Parse configuration file */
if (verbose)
printf(" * Parsing configuration file %s ...\n", conf_file);
err = parse_conf_file(conf_file);
if (err) return err;
if (link_defs == NULL) {
if (verbose) printf(" * No link definitions found...\n");
return 0;
}
if( card_name != NULL && strcmp(card_name, link_defs->name) != 0 )
return ERR_CONFIG;
if (verbose) printf(
" * Configuring device %s (%s)\n",
link_defs->name,
"no description");
res = configure_link(link_defs,0);
if (res) {
return res;
}
free_linkdefs();
return err;
}
/*============================================================================
* Parse configuration file.
* Read configuration file and create lists of link and channel
* definitions.
*/
int parse_conf_file (char* fname)
{
int err = 0;
FILE* file;
file = fopen(fname, "r");
if (file == NULL) {
fprintf(stderr, "\nError: %s not found in %s directory\n",
fname, conf_dir);
show_error(ERR_SYSTEM);
return ERR_SYSTEM;
}
/* Build a list of link and channel definitions */
err = build_linkdef_list(file);
if (!err && link_defs)
err = build_chandef_list(file);
fclose(file);
return err;
}
/*============================================================================
* Build a list of link definitions.
*/
int build_linkdef_list (FILE* file)
{
int err = 0;
char* conf; /* -> section buffer */
char* key; /* -> current configuration record */
int len; /* record length */
char *token[MAX_TOKENS];
/* Read [devices] section */
conf = read_conf_section(file, "devices");
if (conf == NULL) return ERR_CONFIG;
/* For each record in [devices] section create a link definition
* structure and link it to the list of link definitions.
*/
for (key = conf; !err && *key; key += len) {
int toknum;
link_def_t* linkdef; /* -> link definition */
int config_id = 0;
len = strlen(key) + 1;
toknum = tokenize(key, token);
if (toknum < 2) continue;
strupcase(token[1]);
config_id = name2val(token[1], config_id_str);
if (!config_id) {
if (verbose) printf(
" * Media ID %s is invalid!\n", token[1]);
err = ERR_CONFIG;
show_error(err);
break;
}
linkdef = calloc(1, sizeof(link_def_t));
if (linkdef == NULL) {
err = ERR_SYSTEM;
show_error(err);
break;
}
memset(linkdef,0,sizeof(link_def_t));
strncpy(linkdef->name, token[0], WAN_DRVNAME_SZ);
linkdef->config_id = config_id;
if ((toknum > 2) && token[2])
linkdef->descr = strdup(token[2]);
linkdef->conf = read_conf_section(file, linkdef->name);
if (link_defs) {
linkdef->next=link_defs;
link_defs=linkdef;
//link_def_t* last;
//for (last = link_defs; last->next; last = last->next);
//last->next = linkdef;
}
else link_defs = linkdef;
}
free(conf);
return err;
}
/*============================================================================
* Build a list of channel definitions.
*/
int build_chandef_list (FILE* file)
{
int err = 0;
char* conf; /* -> section buffer */
char* key; /* -> current configuration record */
int len; /* record length */
char *token[MAX_TOKENS];
link_def_t* linkdef = link_defs;
if (linkdef == NULL)
return ERR_CONFIG;
/* Read [interfaces] section */
conf = read_conf_section(file, "interfaces");
if (conf == NULL)
return 0;
/* For each record in [interfaces] section create channel definition
* structure and link it to the list of channel definitions for
* appropriate link.
*/
for (key = conf; !err && *key; key += len) {
int toknum;
char *channel_sect;
chan_def_t* chandef; /* -> channel definition */
len = strlen(key) + 1;
toknum = tokenize(key, token);
if (toknum < 4) continue;
/* allocate and initialize channel definition structure */
chandef = calloc(1, sizeof(chan_def_t));
if (chandef == NULL) {
err = ERR_SYSTEM;
show_error(err);
break;
}
memset(chandef,0,sizeof(chan_def_t));
strncpy(chandef->name, token[0], WAN_IFNAME_SZ);
chandef->addr = strdup(token[2]);
chandef->usedby = strdup(token[3]);
chandef->annexg = NO_ANNEXG;
/* These are Anexg Connections */
if (toknum > 5){
if (!strcmp(token[4],"lapb")){
chandef->annexg = ANNEXG_LAPB;
}else if (!strcmp(token[4],"x25")){
chandef->annexg = ANNEXG_X25;
}else if (!strcmp(token[4],"dsp")){
chandef->annexg = ANNEXG_DSP;
}else if (!strcmp(token[4],"fr")){
chandef->annexg = ANNEXG_FR;
chandef->protocol = strdup("MP_FR");
}else if (!strcmp(token[4],"ppp")){
chandef->annexg = ANNEXG_PPP;
chandef->protocol = strdup("MP_PPP");
}else if (!strcmp(token[4],"chdlc")){
chandef->annexg = ANNEXG_CHDLC;
chandef->protocol = strdup("MP_CHDLC");
}else if (!strcmp(token[4],"lip_atm")){
printf("%s: CONIGURING FOR LIP ATM\n",chandef->name);
chandef->annexg = ANNEXG_LIP_ATM;
chandef->protocol = strdup("MP_ATM");
}else if (!strcmp(token[4],"lip_katm")){
printf("%s: CONIGURING FOR LIP KATM\n",chandef->name);
chandef->annexg = ANNEXG_LIP_KATM;
chandef->protocol = strdup("MP_KATM");
}else if (!strcmp(token[4],"lip_x25")){
chandef->annexg = ANNEXG_LIP_X25;
chandef->protocol = strdup("MP_X25");
}else if (!strcmp(token[4],"lip_lapb")){
chandef->annexg = ANNEXG_LIP_LAPB;
chandef->protocol = strdup("MP_LAPB");
}else if (!strcmp(token[4],"lip_xmtp2")){
chandef->annexg = ANNEXG_LIP_XMTP2;
chandef->protocol = strdup("MP_XMTP2");
}else if (!strcmp(token[4],"lip_lapd")){
chandef->annexg = ANNEXG_LIP_LAPD;
chandef->protocol = strdup("MP_LAPD");
}else if (!strcmp(token[4],"lip_hdlc")){
chandef->annexg = ANNEXG_LIP_HDLC;
chandef->protocol = strdup("MP_HDLC");
}else if (!strcmp(token[4],"lip_xdlc")){
chandef->annexg = ANNEXG_LIP_XDLC;
chandef->protocol = strdup("MP_XDLC");
}else if (!strcmp(token[4],"tty")){
chandef->annexg = ANNEXG_LIP_XDLC;
chandef->protocol = strdup("MP_TTY");
}else{
if (verbose) printf(" * %s defined with invalid protocol %s\n",
chandef->name, token[4]);
return ERR_CONFIG;
}
}
if (!(chandef->usedby) ||(( strcmp(chandef->usedby, "WANPIPE") != 0 ) &&
( strcmp(chandef->usedby, "API") != 0 ) &&
( strcmp(chandef->usedby, "API_LEGACY") != 0 ) &&
( strcmp(chandef->usedby, "DATA_API") != 0 ) &&
( strcmp(chandef->usedby, "BRIDGE") != 0 ) &&
( strcmp(chandef->usedby, "SWITCH") != 0 ) &&
( strcmp(chandef->usedby, "PPPoE") != 0 ) &&
( strcmp(chandef->usedby, "STACK") != 0 ) &&
( strcmp(chandef->usedby, "XMTP2_API") != 0 ) &&
( strcmp(chandef->usedby, "NETGRAPH") != 0 ) &&
( strcmp(chandef->usedby, "TTY") != 0 ) &&
( strcmp(chandef->usedby, "BRIDGE_NODE") != 0 ) &&
( strcmp(chandef->usedby, "TDM_VOICE") != 0 ) &&
( strcmp(chandef->usedby, "TDM_VOICE_API") != 0 ) &&
( strcmp(chandef->usedby, "TDM_SPAN_VOICE_API") != 0 ) &&
( strcmp(chandef->usedby, "TDM_CHAN_VOICE_API") != 0 ) &&
( strcmp(chandef->usedby, "MTP2_LSL_API") != 0 ) &&
( strcmp(chandef->usedby, "MTP2_HSL_API") != 0 ) &&
( strcmp(chandef->usedby, "TDM_API") != 0 ) &&
( strcmp(chandef->usedby, "TRUNK") != 0 ) &&
( strcmp(chandef->usedby, "ANNEXG") != 0 )))
{
if (verbose) printf(" * %s to be used by an Invalid entity: %s\n",
chandef->name, chandef->usedby);
return ERR_CONFIG;
}
if (verbose)
printf(" * %s to used by %s\n",
chandef->name, chandef->usedby);
channel_sect=strdup(token[0]);
if (toknum > 5){
char *section=strdup(token[5]);
/* X25_SW */
if (toknum > 7){
if (toknum > 6)
chandef->virtual_addr = strdup(token[6]);
if (toknum > 7)
chandef->real_addr = strdup(token[7]);
if (toknum > 8)
chandef->label = strdup(token[8]);
}else{
if (toknum > 6)
chandef->label = strdup(token[6]);
}
chandef->conf_profile = read_conf_section(file, section);
free(section);
}else{
chandef->conf_profile = NULL;
}
chandef->conf = read_conf_section(file, channel_sect);
free(channel_sect);
/* append channel definition structure to the list */
if (linkdef->chan) {
chan_def_t* last;
for (last = linkdef->chan;
last->next;
last = last->next)
;
last->next = chandef;
}
else linkdef->chan = chandef;
/* Alex */
chandef->link = linkdef;
}
free(conf);
return err;
}
/*============================================================================
* Configure WAN link.
*/
int configure_link (link_def_t* def, char init)
{
key_word_t* conf_table = lookup(def->config_id, conf_def_tables);
int err = 0;
int len = 0, i, max_len = sizeof(router_dir) + WAN_DRVNAME_SZ;
char filename[max_len + 2];
chan_def_t* chandef;
char* conf_rec;
int dev=-1;
unsigned short hi_DLCI = 15;
char *token[MAX_TOKENS];
if (def->conf == NULL) {
show_error(ERR_CONFIG);
return ERR_CONFIG;
}
/* Clear configuration structure */
if (def->linkconf){
if (def->linkconf->data) free(def->linkconf->data);
free(def->linkconf);
def->linkconf=NULL;
}
def->linkconf = malloc(sizeof(wandev_conf_t));
if (!def->linkconf){
printf("%s: Failed to allocated linkconf!\n",prognamed);
return -ENOMEM;
}
memset(def->linkconf, 0, sizeof(wandev_conf_t));
def->linkconf->magic = ROUTER_MAGIC;
def->linkconf->config_id = def->config_id;
/* Parse link configuration */
for (conf_rec = def->conf; *conf_rec; conf_rec += len) {
int toknum;
len = strlen(conf_rec) + 1;
toknum = tokenize(conf_rec, token);
if (toknum < 2) {
show_error(ERR_CONFIG);
return ERR_CONFIG;
}
/* Look up a keyword first in common, then in media-specific
* configuration definition tables.
*/
strupcase(token[0]);
err = set_conf_param(
token[0], token[1], common_conftab,
def->linkconf, sizeof(wandev_conf_t));
if ((err < 0) && (conf_table != NULL))
err = set_conf_param(
token[0], token[1], conf_table,
&def->linkconf->u, sizeof(def->linkconf->u));
if (err < 0) {
printf(" * Unknown parameter %s\n", token[0]);
fprintf(stderr, "\n\n\tERROR in %s !!\n",conf_file);
if(weanie_flag) fprintf(stderr, "\tPlease check %s for errors\n", verbose_log);
fprintf(stderr, "\n");
return ERR_CONFIG;
}
if (err){
fprintf(stderr,"\n\tError parsing %s configuration file. Token (%s = %s)\n", conf_file, token[0], token[1]);
if(weanie_flag) fprintf(stderr,"\tPlease check %s for errors\n", verbose_log);
fprintf(stderr, "\n");
return err;
}
}
/* Open SDLA device and perform link configuration */
snprintf(filename, max_len, "%s/%s", router_dir, def->name);
/* prepare a list of DLCI(s) and place it in the wandev_conf_t structure
* This is done so that we have a list of DLCI(s) available when we
* call the wpf_init() routine in sdla_fr.c (triggered by the ROUTER_
* SETUP ioctl call) for running global SET_DLCI_CONFIGURATION cmd. This
* is only relevant for a station being a NODE, for CPE it polls the
* NODE (auto config DLCI)
*/
if ((def->linkconf->config_id == WANCONFIG_FR)){
i = 0;
if(err)
return err;
for (chandef = def->chan; chandef; chandef = chandef->next){
if (strcmp(chandef->addr,"auto")==0){
continue;
}
if (verbose)
printf(" * Reading DLCI(s) Included : %s\n",
chandef->addr ? chandef->addr : "not specified");
if (chandef->annexg != NO_ANNEXG)
continue;
def->linkconf->u.fr.dlci[i] = dec_to_uint(chandef->addr,0);
if(def->linkconf->u.fr.dlci[i] > hi_DLCI) {
hi_DLCI = def->linkconf->u.fr.dlci[i];
i++;
}else {
fprintf(stderr,"\n\tDLCI(s) specified in %s are not in order\n",conf_file);
fprintf(stderr,"\n\tor duplicate DLCI(s) assigned!\n");
return ERR_SYSTEM;
}
}
}else{
/* Read standard VCI/VPI list and send it */
if ((def->linkconf->config_id == WANCONFIG_ADSL)){
read_adsl_vci_vpi_list(&def->linkconf->u.adsl.vcivpi_list[0],
&def->linkconf->u.adsl.vcivpi_num);
}
}
#if defined(__LINUX__)
dev = open(filename, O_RDONLY);
#else
dev = open(WANDEV_NAME, O_RDONLY);
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
strlcpy(config.devname, def->name, WAN_DRVNAME_SZ);
config.arg = NULL;
#endif
if (conf_file && strstr(conf_file, "ft1.conf") != NULL){
def->linkconf->ft1 = 1;
}else{
def->linkconf->ft1 = 0;
}
if (!init){
/* copy firmware onto S514 card */
def->linkconf->data = firmware_file_buffer;/* must initialize it again here!!! */
err=exec_link_cmd(dev,def);
}
/* Configure logical channels */
if( !err && !nodev_flag ){
for (chandef = def->chan; chandef; chandef = chandef->next) {
switch (chandef->annexg){
case NO_ANNEXG:
strncpy(master_lapb_dev,chandef->name, WAN_IFNAME_SZ);
strncpy(master_lip_dev,chandef->name, WAN_IFNAME_SZ);
break;
case ANNEXG_LAPB:
strncpy(master_x25_dev,chandef->name, WAN_IFNAME_SZ);
break;
case ANNEXG_X25:
strncpy(master_dsp_dev,chandef->name, WAN_IFNAME_SZ);
break;
}
if (!init){
if(dev_name != NULL && strcmp(dev_name, chandef->name) != 0 )
continue;
}
if (verbose) printf(
" * Configuring channel %s (%s). Media address: %s\n",
chandef->name,
"no description",
chandef->addr ? chandef->addr : "not specified");
if (chandef->chanconf){
free(chandef->chanconf);
chandef->chanconf=NULL;
}
chandef->chanconf=malloc(sizeof(wanif_conf_t));
if (!chandef->chanconf){
printf("%s: Failed to allocate chandef\n",prognamed);
close(dev);
return -ENOMEM;
}
memset(chandef->chanconf, 0, sizeof(wanif_conf_t));
chandef->chanconf->magic = ROUTER_MAGIC;
chandef->chanconf->config_id = def->config_id;
err=configure_chan(dev, chandef, init, def->config_id);
if (err){
break;
}
if (strcmp(chandef->usedby, "STACK") == 0){
strncpy(master_lip_dev,chandef->name, WAN_IFNAME_SZ);
}
}
}
/* clean up */
close(dev);
return err;
}
int exec_link_cmd(int dev, link_def_t *def)
{
if (!def->linkconf){
printf("%s: Error: Device %s has no config structure\n",
prognamed,def->name);
return -EFAULT;
}
{
char wanpipe_version[50];
memset(wanpipe_version,0,sizeof(wanpipe_version));
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
config.arg = wanpipe_version;
if ((dev < 0) || (ioctl(dev, ROUTER_VER, &config))){
#else
if ((dev < 0) || (ioctl(dev, ROUTER_VER, wanpipe_version))){
#endif
fprintf(stderr, "\n\n\t%s: WAN device %s driver load failed !!\n",
prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(%s,ROUTER_VER) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
fprintf(stderr, "\n");
switch (errno){
case EPERM:
fprintf(stderr, "\n\t%s: Wanpipe Driver Security Check Failure!\n",
progname_sp);
fprintf(stderr, "\n\t%s: Linux headers used to compile Wanpipe\n",
progname_sp);
fprintf(stderr, "\n\t%s: Drivers, do not match the Kernel Image\n",
progname_sp);
fprintf(stderr, "\n\t%s: Please call Sangoma Tech Support\n",
progname_sp);
break;
default:
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
fprintf(stderr, "\n\t%s: Wanpipe Module Installation Failure!\n",
progname_sp);
fprintf(stderr, "\n\t%s: 1. New Wanpipe modules failed to install\n",
progname_sp);
fprintf(stderr, "\n\t%s: during wanpipe installation.\n",
progname_sp);
fprintf(stderr, "\n\t%s: 2. Wanpipe device doesn't exists in a list.\n",
progname_sp);
fprintf(stderr, "\n\t%s: 3. Wanpipe data structure is corrupted.\n",
progname_sp);
#else
fprintf(stderr, "\n\t%s: Wanpipe Module Installation Failure!\n",
progname_sp);
fprintf(stderr, "\n\t%s: New Wanpipe modules failed to install during\n",
progname_sp);
fprintf(stderr, "\n\t%s: wanpipe installation. Current wanpipe modules\n",
progname_sp);
fprintf(stderr, "\n\t%s: (lsmod) are obselete.\n",
progname_sp);
fprintf(stderr, "\n\t%s: Please check linux source name vs the name\n",
progname_sp);
fprintf(stderr, "\n\t%s: of the currently running image.\n",
progname_sp);
fprintf(stderr, "\n\t%s: Then proceed to install Wanpipe again!\n",
progname_sp);
#endif
break;
}
fprintf(stderr, "\n");
return -EINVAL;
}
if (strstr(wanpipe_version, wan_version) == NULL){
fprintf(stderr, "\n\n\t%s: WAN device %s driver load failed !!\n",
prognamed, def->name);
fprintf(stderr, "\n\t%s: Wanpipe version mismatch between utilites\n",
progname_sp);
fprintf(stderr, "\t%s: and kernel drivers:\n",
progname_sp);
fprintf(stderr, "\t%s: \tUtil Ver=%s, Driver Ver=%s\n",
progname_sp,wan_version,wanpipe_version);
fprintf(stderr, "\n");
return -EINVAL;
}
}
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
config.arg = def->linkconf;
if ((dev < 0) || (ioctl(dev, ROUTER_SETUP, &config) < 0
&& ( dev_name == NULL || errno != EBUSY ))) {
#else
if ((dev < 0) || (ioctl(dev, ROUTER_SETUP, def->linkconf) < 0
&& ( dev_name == NULL || errno != EBUSY ))) {
#endif
fprintf(stderr, "\n\n\t%s: WAN device %s driver load failed !!\n", prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(%s,ROUTER_SETUP) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n");
fprintf(stderr, "\n\tWanpipe driver did not load properly\n");
fprintf(stderr, "\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf(stderr, "\n");
return errno;
}
return 0;
}
/*============================================================================
* Configure WAN logical channel.
*/
int configure_chan (int dev, chan_def_t* def, char init, int id)
{
int err = 0;
int len = 0;
char* conf_rec;
char *token[MAX_TOKENS];
key_word_t* conf_annexg_table=NULL;
key_word_t* conf_table = lookup(id, conf_if_def_tables);
if (def->annexg && def->protocol){
conf_annexg_table=lookup(def->annexg, conf_annexg_def_tables);
if (conf_annexg_table){
set_conf_param(
"PROTOCOL", def->protocol, chan_conftab,
def->chanconf, sizeof(wanif_conf_t));
}
}
/* Prepare configuration data */
strncpy(def->chanconf->name, def->name, WAN_IFNAME_SZ);
if (def->addr)
strncpy(def->chanconf->addr, def->addr, WAN_ADDRESS_SZ);
if (def->usedby)
strncpy(def->chanconf->usedby, def->usedby, USED_BY_FIELD);
if (def->label){
if (conf_annexg_table){
set_conf_param(
"LABEL", def->label, conf_annexg_table,
&def->chanconf->u, sizeof(def->chanconf->u));
}else{
memcpy(def->chanconf->label,def->label,WAN_IF_LABEL_SZ);
}
}
if (def->virtual_addr){
if (conf_annexg_table){
set_conf_param(
"VIRTUAL_ADDR",def->virtual_addr, conf_annexg_table,
&def->chanconf->u, sizeof(def->chanconf->u));
}
}
if (def->real_addr){
if (def->annexg){
if (conf_annexg_table){
set_conf_param(
"REAL_ADDR",def->real_addr, conf_annexg_table,
&def->chanconf->u,sizeof(def->chanconf->u));
}
}
}
if (def->conf) for (conf_rec = def->conf; *conf_rec; conf_rec += len) {
int toknum;
len = strlen(conf_rec) + 1;
toknum = tokenize(conf_rec, token);
if (toknum < 2) {
show_error(ERR_CONFIG);
return -EINVAL;
}
/* Look up a keyword first in common, then media-specific
* configuration definition tables.
*/
strupcase(token[0]);
if (set_conf_param(token[0], token[1], chan_conftab, def->chanconf,sizeof(wanif_conf_t))) {
if (def->annexg && conf_annexg_table){
if (!conf_annexg_table ||
set_conf_param(token[0], token[1], conf_annexg_table, &def->chanconf->u, sizeof(def->chanconf->u))) {
printf("Invalid Annexg/Lip parameter %s\n", token[0]);
show_error(ERR_CONFIG);
return ERR_CONFIG;
}
}else if (conf_table){
if (set_conf_param(token[0], token[1], conf_table, &def->chanconf->u, sizeof(def->chanconf->u))) {
printf("Invalid Iface parameter %s\n", token[0]);
show_error(ERR_CONFIG);
return ERR_CONFIG;
}
}else{
printf("Invalid config table !!! parameter %s\n", token[0]);
printf("Conf_table %p %p\n",
conf_table,
bitstrm_if_conftab);
show_error(ERR_CONFIG);
return ERR_CONFIG;
}
}else{
if (strcmp(token[0], "ACTIVE_CH") == 0){
strlcpy(def->active_ch, token[1], 50);
}
}
}
len=0;
if (def->annexg){
conf_annexg_table=lookup(def->annexg, conf_annexg_def_tables);
if (def->conf_profile) for (conf_rec = def->conf_profile; *conf_rec; conf_rec += len) {
int toknum;
len = strlen(conf_rec) + 1;
toknum = tokenize(conf_rec, token);
if (toknum < 2) {
show_error(ERR_CONFIG);
return -EINVAL;
}
/* Look up a keyword first in common, then media-specific
* configuration definition tables.
*/
strupcase(token[0]);
if (!conf_annexg_table ||
set_conf_param(token[0], token[1], conf_annexg_table, &def->chanconf->u, sizeof(def->chanconf->u))) {
if (set_conf_param(token[0], token[1], chan_conftab, def->chanconf, sizeof(wanif_conf_t))) {
printf("Invalid parameter %s\n", token[0]);
show_error(ERR_CONFIG);
return ERR_CONFIG;
}
}
}
}
err=0;
if (init){
return err;
}
return exec_chan_cmd(dev,def);
}
int exec_chan_cmd(int dev, chan_def_t *def)
{
#if defined(WAN_HWEC)
int err;
#endif
if (!def->chanconf){
printf("%s: Error: Device %s has no config structure\n",
prognamed,def->name);
return -EFAULT;
}
fflush(stdout);
switch (def->annexg){
case NO_ANNEXG:
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
config.arg = (void*)def->chanconf;
if (ioctl(dev, ROUTER_IFNEW, &config) < 0) {
#else
if (ioctl(dev, ROUTER_IFNEW, def->chanconf) < 0) {
#endif
fprintf(stderr, "\n\n\t%s: Interface %s setup failed\n", prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(ROUTER_IFNEW,%s) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n\tWanpipe drivers could not setup network interface\n");
fprintf(stderr, "\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf(stderr, "\n");
return errno;
}
#if defined(WAN_HWEC)
if ((err = wanconfig_hwec(def))){
fprintf(stderr, "\n\n\t%s: HWEC configuration failed on %s\n", prognamed, def->name);
fprintf(stderr, "\n\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors.\n", krnl_log_file);
fprintf(stderr, "\n");
return err;
}
#endif
break;
#if defined(__LINUX__)
case ANNEXG_LAPB:
strncpy((char*)def->chanconf->master,(char*)master_lapb_dev, WAN_IFNAME_SZ);
if (ioctl(dev, ROUTER_IFNEW_LAPB, def->chanconf) < 0) {
fprintf(stderr, "\n\n\t%s: Interface %s setup failed\n", prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(ROUTER_IFNEW_LAPB,%s) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n\tWanpipe drivers could not setup network interface\n");
fprintf(stderr, "\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf(stderr, "\n");
return errno;
}
break;
case ANNEXG_X25:
strncpy((char*)def->chanconf->master, (char*)master_x25_dev, WAN_IFNAME_SZ);
if (ioctl(dev, ROUTER_IFNEW_X25, def->chanconf) < 0) {
fprintf(stderr, "\n\n\t%s: Interface %s setup failed\n", prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(ROUTER_IFNEW_X25,%s) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n\tWanpipe drivers could not setup network interface\n");
fprintf(stderr, "\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf(stderr, "\n");
return errno;
}
break;
// DSP_20
case ANNEXG_DSP:
strncpy((char*)def->chanconf->master, (char*)master_dsp_dev, WAN_IFNAME_SZ);
if (ioctl(dev, ROUTER_IFNEW_DSP, def->chanconf) < 0) {
fprintf(stderr, "\n\n\t%s: Interface %s setup failed\n", prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(ROUTER_IFNEW_DSP,%s) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n\tWanpipe drivers could not setup network interface\n");
fprintf(stderr, "\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf(stderr, "\n");
return errno;
}
break;
#endif
case ANNEXG_FR:
case ANNEXG_PPP:
case ANNEXG_CHDLC:
case ANNEXG_LIP_LAPB:
case ANNEXG_LIP_XDLC:
case ANNEXG_LIP_TTY:
case ANNEXG_LIP_XMTP2:
case ANNEXG_LIP_LAPD:
case ANNEXG_LIP_X25:
case ANNEXG_LIP_ATM:
case ANNEXG_LIP_KATM:
case ANNEXG_LIP_HDLC:
strncpy((char*)def->chanconf->master, (char*)master_lip_dev, WAN_IFNAME_SZ);
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
config.arg = (void*)def->chanconf;
if (ioctl(dev, ROUTER_IFNEW_LIP, &config) < 0) {
#else
if (ioctl(dev, ROUTER_IFNEW_LIP, def->chanconf) < 0) {
#endif
fprintf(stderr, "\n\n\t%s: Interface %s setup failed\n", prognamed, def->name);
fprintf(stderr, "\t%s: ioctl(ROUTER_IFNEW_LIP,%s) failed:\n",
progname_sp, def->name);
fprintf(stderr, "\t%s:\t%d - %s\n", progname_sp, errno, strerror(errno));
if( weanie_flag ) {
fprintf(stderr, "\n\tWanpipe drivers could not setup network interface\n");
fprintf(stderr, "\tPlease check %s and\n", verbose_log);
fprintf(stderr, "\t%s for errors\n", krnl_log_file);
}
fprintf(stderr, "\n");
return errno;
}
break;
default:
show_error(ERR_CONFIG);
return -EINVAL;
}
return 0;
}
#if 0
/*============================================================================
* Set configuration parameter.
* Look up a keyword in configuration description table to find offset
* and data type of the configuration parameter into configuration data
* buffer. Convert parameter to apporriate data type and store it the
* configuration data buffer.
*
* Return: 0 - success
* 1 - error
* -1 - not found
*/
int set_conf_param (char* key, char* val, key_word_t* dtab, void* conf)
{
ulong tmp = 0;
/* Search a keyword in configuration definition table */
for (; dtab->keyword && strcmp(dtab->keyword, key); ++dtab);
if (dtab->keyword == NULL) return -1; /* keyword not found */
/* Interpert parameter value according to its data type */
if (dtab->dtype == DTYPE_FILENAME) {
return read_data_file(
val, (void*)((char*)conf + dtab->offset));
}
if (verbose) printf(" * Setting %s to %s offset %i\n", key, val, dtab->offset);
if (dtab->dtype == DTYPE_STR) {
//wanif_conf_t *chanconf = (wanif_conf_t *)conf;
strcpy((char*)conf + dtab->offset, val);
//???????????????
//if (!strcmp(key,"X25_CALL_STRING"))
// printf ("Setting STRING: %s to %s offset %i\n",
// key,chanconf->x25_call_string,dtab->offset);
return 0;
}
if (!isdigit(*val)) {
look_up_t* sym;
strupcase(val);
for (sym = sym_table;
sym->ptr && strcmp(sym->ptr, val);
++sym)
;
if (sym->ptr == NULL) {
if (verbose) printf(" * invalid term %s ...\n", val);
return 1;
}
else tmp = sym->val;
}
else tmp = strtoul(val, NULL, 0);
switch (dtab->dtype) {
case DTYPE_INT:
*(int*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_UINT:
*(uint*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_LONG:
*(long*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_ULONG:
*(ulong*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_SHORT:
*(short*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_USHORT:
*(ushort*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_CHAR:
*(char*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_UCHAR:
*(unsigned char*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_PTR:
*(void**)((char*)conf + dtab->offset) = (void*)tmp;
break;
}
return 0;
}
#endif
/*============================================================================
* Set configuration parameter.
* Look up a keyword in configuration description table to find offset
* and data type of the configuration parameter into configuration data
* buffer. Convert parameter to apporriate data type and store it the
* configuration data buffer.
*
* Return: 0 - success
* 1 - error
* -1 - not found
*/
int set_conf_param (char* key, char* val, key_word_t* dtab, void* conf, int max_len)
{
unsigned int tmp = 0;
/* Search a keyword in configuration definition table */
for (; dtab->keyword && strcmp(dtab->keyword, key); ++dtab);
if (dtab->keyword == NULL) return -1; /* keyword not found */
/* Interpert parameter value according to its data type */
if (dtab->dtype == DTYPE_FILENAME) {
return read_data_file(
val, (void*)((char*)conf + dtab->offset));
}
/* FIXME: Add code that will parse Octasic Chip configuration file */
if (dtab->dtype == DTYPE_OCT_FILENAME) {
return 0;
}
if (dtab->dtype == DTYPE_OCT_CHAN_CONF) {
return read_oct_chan_config(
key, val, (void*)((char*)conf + dtab->offset));
}
if (verbose) printf(" * Setting %s to %s\n", key, val);
if (strcmp(key, "RTP_TAP_IP") == 0) {
int err;
struct hostent *result = NULL;
#if defined(__LINUX__)
char buf[512];
struct hostent hp;
gethostbyname_r(val, &hp, buf, sizeof(buf), &result, &err);
#else
result = gethostbyname(val);
err = h_errno;
#endif
if (result) {
#if defined(__LINUX__)
memcpy((char*)conf + dtab->offset, hp.h_addr_list[0], hp.h_length);
#else
memcpy((char*)conf + dtab->offset, result->h_addr_list[0], result->h_length);
#endif
} else {
printf("Error: Invalid IP Address %s (%s)\n",
val, hstrerror(err));
memset((char*)conf + dtab->offset, 0, sizeof(unsigned int));
err=1;
}
return err;
}
if (strcmp(key, "RTP_TAP_MAC") == 0) {
char *token;
char *cp = strdup(val);
int cnt=0;
unsigned char *mac =(unsigned char*)conf + dtab->offset;
token=strtok(cp, ":");
if (token) {
mac[cnt] = (unsigned char)strtoul(token,NULL,16);
cnt++;
while ((token=strtok(NULL, ":")) != NULL){
mac[cnt] = strtoul(token,NULL,16);
cnt++;
if (cnt >= 6) {
break;
}
}
}
free(cp);
if (cnt != 6) {
printf("Error: Invalid MAC Address %s\n",val);
return 1;
}
return 0;
}
if (dtab->dtype == DTYPE_STR) {
strlcpy((char*)conf + dtab->offset, val, max_len-dtab->offset);
return 0;
}
if (!(isdigit(*val) || (*val=='-' && isdigit(*(val+1)))) ||
strcmp(key, "TE_ACTIVE_CH") == 0 || strcmp(key, "ACTIVE_CH") == 0 ||
strcmp(key, "TE_LBO") == 0 || strcmp(key, "LBO") == 0 ||
strcmp(key, "FE_MEDIA") == 0 || strcmp(key, "MEDIA") == 0 ||
strcmp(key, "RBS_CH_MAP") == 0 || strcmp(key, "TE_RBS_CH") == 0 ||
strcmp(key, "TDMV_DCHAN") == 0){
look_up_t* sym;
unsigned int tmp_ch;
strupcase(val);
for (sym = sym_table;
sym->ptr && strcmp(sym->ptr, val);
++sym);
if (sym->ptr == NULL) {
int ok_zero=0;
/* TE1 */
if (strcmp(key, "TE_ACTIVE_CH") && strcmp(key, "ACTIVE_CH") &&
strcmp(key, "RBS_CH_MAP") && strcmp(key, "TE_RBS_CH") &&
strcmp(key, "TDMV_DCHAN")) {
if (verbose) printf(" * invalid term %s ...\n", val);
return 1;
}
if (strcmp(key, "TDMV_DCHAN") == 0) {
ok_zero=1;
}
/* TE1 Convert active channel string to UINT */
tmp_ch = parse_active_channel(val);
if (tmp_ch == 0 && !ok_zero){
if (verbose) printf("Illegal active channel range! %s ...\n", val);
fprintf(stderr, "Illegal active channel range! min=1 max=31\n");
return -1;
}
tmp = (unsigned int)tmp_ch;
} else {
tmp = sym->val;
}
} else {
tmp = strtoul(val, NULL, 0);
}
/* SANITY CHECK */
switch (dtab->dtype) {
case DTYPE_INT:
SIZEOFASSERT(dtab, sizeof(int));
*(int*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_UINT:
SIZEOFASSERT(dtab, sizeof(unsigned int));
*(unsigned int*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_LONG:
SIZEOFASSERT(dtab, sizeof(long));
*(long*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_ULONG:
SIZEOFASSERT(dtab, sizeof(unsigned long));
*(unsigned long*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_SHORT:
SIZEOFASSERT(dtab, sizeof(short));
*(short*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_USHORT:
SIZEOFASSERT(dtab, sizeof(unsigned short));
*(ushort*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_CHAR:
SIZEOFASSERT(dtab, sizeof(char));
*(char*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_UCHAR:
SIZEOFASSERT(dtab, sizeof(unsigned char));
*(unsigned char*)((char*)conf + dtab->offset) = tmp;
break;
case DTYPE_PTR:
*(void**)((char*)conf + dtab->offset) = (void*)tmp;
break;
}
return 0;
}
/*============================================================================
* Read configuration file section.
* Return a pointer to memory filled with key entries read from given
* section or NULL if section is not found. Each key is a zero-terminated
* ASCII string with no leading spaces and comments. The last key is
* followed by an empty string.
* Note: memory is allocated dynamically and must be released by the
* caller.
*/
char* read_conf_section (FILE* file, char* section)
{
char key[MAX_CFGLINE]; /* key buffer */
char* buf = NULL;
int found = 0, offs = 0, len, max_len = 0;
rewind(file);
while ((len = read_conf_record(file, key, MAX_CFGLINE)) > 0) {
char* tmp;
if (found) {
if (*key == '[') break; /* end of section */
max_len = len;
if (buf){
max_len += offs;
tmp = realloc(buf, max_len + 1);
}else{
tmp = malloc(max_len + 1);
}
if (tmp) {
buf = tmp;
strlcpy(&buf[offs], key, max_len-offs);
offs += len;
buf[offs] = '\0';
}
else { /* allocation failed */
show_error(ERR_SYSTEM);
break;
}
}
else if (*key == '[') {
tmp = strchr(key, ']');
if (tmp != NULL) {
*tmp = '\0';
if (strcmp(&key[1], section) == 0) {
if (verbose) printf(
" * Reading section [%s]...\n",
section);
found = 1;
}
}
}
}
if (verbose && !found) printf(
" * section [%s] not found!\n", section);
return buf;
}
/*============================================================================
* Read a single record from the configuration file.
* Read configuration file stripping comments and leading spaces until
* non-empty line is read. Copy it to the destination buffer.
*
* Return string length (incl. terminating zero) or 0 if end of file has been
* reached.
*/
int read_conf_record (FILE* file, char* key, int max_len)
{
char buf[MAX_CFGLINE]; /* line buffer */
while (fgets(buf, MAX_CFGLINE, file)) {
char* str;
int len;
/* Strip leading spaces and comments */
for (str = buf; *str && strchr(" \t", *str); ++str);
len = strcspn(str, "#;\n\r");
if (len) {
str[len] = '\0';
strlcpy(key, str, max_len);
return len + 1;
}
}
return 0;
}
/*============================================================================
* Tokenize string.
* Parse a string of the following syntax:
* <tag>=<arg1>,<arg2>,...
* and fill array of tokens with pointers to string elements.
*
* Return number of tokens.
*/
void init_tokens(char **token)
{
int i;
for (i=0;i<MAX_TOKENS;i++){
token[i]=NULL;
}
}
/* Bug Fix by Ren<65>Scharfe <l.s.r@web.de>
* removed strtok
*/
int tokenize (char *str, char **tokens)
{
int cnt = 0;
char *tok;
init_tokens(tokens);
if (!str){
return 0;
}
tok = strchr(str, '=');
if (!tok)
return 0;
*tok='\0';
tokens[cnt] = str;
str=++tok;
while (tokens[cnt] && (cnt < MAX_TOKENS-1)) {
tokens[cnt] = str_strip(tokens[cnt], " \t");
if ((tok = strchr(str, ',')) == NULL){
tokens[++cnt] = str_strip(str, " \t");
goto end_tokenize;
}
*tok='\0';
tokens[++cnt] = str_strip(str, " \t");
str=++tok;
}
end_tokenize:
return ++cnt;
}
/*============================================================================
* Strip leading and trailing spaces off the string str.
*/
char* str_strip (char* str, char* s)
{
char* eos = str + strlen(str); /* -> end of string */
while (*str && strchr(s, *str))
++str; /* strip leading spaces */
while ((eos > str) && strchr(s, *(eos - 1)))
--eos; /* strip trailing spaces */
*eos = '\0';
return str;
}
/*============================================================================
* Uppercase string.
*/
char* strupcase (char* str)
{
char* s;
for(s = str; *s; ++s) *s = toupper(*s);
return str;
}
/*============================================================================
* Get a pointer from a look-up table.
*/
void* lookup (int val, look_up_t* table)
{
while (table->val && (table->val != val)) table++;
return table->ptr;
}
/*============================================================================
* Look up a symbolic name in name table.
* Return a numeric value associated with that name or zero, if name was
* not found.
*/
int name2val (char* name, look_up_t* table)
{
while (table->ptr && strcmp(name, table->ptr)) table++;
return table->val;
}
/*============================================================================
* Create memory image of a file.
*/
int read_data_file (char* name, data_buf_t* databuf)
{
int err = 0;
FILE* file;
unsigned long fsize;
databuf->data = NULL;
databuf->size = 0;
file = fopen(name, "rb");
if (file == NULL) {
if (verbose) printf(" * Can't open data file %s!\n", name);
fprintf(stderr, "%s: Can't open data file %s!\n", prognamed, name);
show_error(ERR_SYSTEM);
return ERR_SYSTEM;
}
fsize = filesize(file);
if (!fsize) {
if (verbose) printf(" * Data file %s is empty!\n", name);
err = ERR_CONFIG;
show_error(err);
}
else {
if (verbose){
printf(" * Reading %lu bytes from %s ...\n",
fsize, name);
}
if (fread(firmware_file_buffer, 1, fsize, file) != fsize) {
err = ERR_SYSTEM;
show_error(err);
goto done;
}
databuf->data = firmware_file_buffer;
databuf->size = fsize;
}
done:
fclose(file);
return err;
}
int read_oct_chan_config (char *key, char *val, wan_custom_conf_t *conf)
{
if ((!conf->param_no && conf->params) || (conf->param_no && conf->params == NULL)){
if (verbose)
printf(" * INTERNAL ERROR [%s:%d]: Reading OCT6100 config param %s:%s!\n",
__FUNCTION__,__LINE__, key,val);
fprintf(stderr, "%s: INTERNAL ERROR [%s:%d]: Reading OCT6100 config param %s:%s!\n",
prognamed,
__FUNCTION__,__LINE__,
key,val);
show_error(ERR_SYSTEM);
return ERR_SYSTEM;
}
if (conf->param_no == 0){
conf->params = malloc(sizeof(wan_custom_param_t));
if (conf->params == NULL){
if (verbose) printf(" * Can't allocate memory for OCT6100 config (%s:%s)!\n",
key,val);
fprintf(stderr, "%s: Can't allocate memory for OCT6100 config (%s:%s)!\n",
prognamed, key, val);
show_error(ERR_SYSTEM);
return ERR_SYSTEM;
}
memset(conf->params, 0, sizeof(wan_custom_param_t));
}
strncpy(conf->params[conf->param_no].name, key, MAX_PARAM_LEN);
strncpy(conf->params[conf->param_no].sValue, val, MAX_VALUE_LEN);
conf->param_no++;
return 0;
}
/*============================================================================
* Get file size
* Return file length or 0 if error.
*/
unsigned long filesize (FILE* file)
{
unsigned long size = 0;
unsigned long cur_pos;
cur_pos = ftell(file);
if ((cur_pos != -1L) && !fseek(file, 0, SEEK_END)) {
size = ftell(file);
fseek(file, cur_pos, SEEK_SET);
}
return size;
}
/*============================================================================
* Convert decimal string to unsigned integer.
* If len != 0 then only 'len' characters of the string are converted.
*/
unsigned int dec_to_uint (char* str, int len)
{
unsigned val;
if (!len) len = strlen((char*)str);
for (val = 0; len && is_digit(*str); ++str, --len)
val = (val * 10) + (*str - (unsigned)'0')
;
return val;
}
unsigned int get_config_data (int argc, char **argv)
{
FILE *fp;
char *device_name=NULL;
fp = fopen (conf_file,"w");
if (fp == NULL){
printf("Could not open file\n");
return 1;
}
get_devices(fp,&argc,&argv,&device_name);
get_interfaces(fp,&argc,&argv,device_name);
get_hardware(fp,&argc,&argv,device_name);
get_intr_setup (fp,&argc,&argv);
fclose(fp);
return 0;
}
int get_devices (FILE *fp, int *argc_ptr, char ***argv_ptr, char **device_name){
int i;
int
start=0, stop=0;
int argc = *argc_ptr;
char **argv = *argv_ptr;
for (i=0;i<argc;i++){
if (!strcmp(argv[i],"[devices]")){
start = i;
continue;
}
if (strstr(argv[i],"[") != NULL){
stop = i;
break;
}
}
if (!stop){
printf("ERROR: No devices found, Incomplete Argument List\n");
return 1;
}
if (stop == 3){
fprintf(fp,"%s\n",argv[start]);
*device_name = argv[start+1];
fprintf(fp,"%s = %s\n",argv[start+1],argv[start+2]);
}else if (stop > 3) {
fprintf(fp,"%s\n",argv[start]);
fprintf(fp,"%s = %s, %s\n",argv[start+1],argv[start+2],argv[start+3]);
}else{
printf("ERROR: No devices found, Too many devices arguments\n");
return 1;
}
*argv_ptr += stop;
*argc_ptr -= stop;
//???????????????
//printf("Start is %i and Stop is %i\n",start,stop);
return 0;
}
int get_interfaces (FILE *fp, int *argc_ptr, char ***argv_ptr, char *device_name){
char **argv = *argv_ptr;
int argc = *argc_ptr;
int i, start=0, stop=0;
for (i=0;i<argc;i++){
//?????????????????????
//printf("INTR: Argv %i is %s\n",i,argv[i]);
if (!strcmp(argv[i],"[interfaces]")){
start = i;
continue;
}
if (strstr(argv[i],"[") != NULL){
stop = i;
break;
}
}
if (!stop){
printf("ERROR: No interfaces found, Incomplete Argument List\n");
return 1;
}
if ((stop-1)%4){
printf("ERROR: Insuficient/Too many Interface arguments\n");
return 1;
}
fprintf(fp, "\n%s\n", argv[start]);
for (i=(start+1);i<stop;i+=4){
fprintf(fp, "%s = %s, ",argv[i],argv[i+1]);
if (!strcmp(argv[i+2],"-")){
fprintf(fp, " ,%s\n",argv[i+3]);
}else{
fprintf(fp, "%s, %s\n",argv[i+2],argv[i+3]);
}
}
*argv_ptr += stop;
*argc_ptr -= stop;
//???????????????
//printf("Interface Start is %i and Stop is %i\n",start,stop);
return 0;
}
int get_hardware (FILE *fp, int *argc_ptr, char ***argv_ptr, char *device_name)
{
char **argv = *argv_ptr;
int argc = *argc_ptr;
int i, start=0, stop=0;
for (i=0;i<argc;i++){
//?????????????????????
//printf("HRDW: Argv %i is %s\n",i,argv[i]);
if (strstr(argv[i],"[wanpipe") != NULL){
start = i;
continue;
}
if (strstr(argv[i],"[") != NULL){
stop = i;
break;
}
}
if (!stop){
stop = argc;
}
if ((stop-1)%2){
printf("ERROR: Insuficient/Too many Hardware arguments\n");
return 1;
}
fprintf(fp, "\n%s\n", argv[start]);
for (i=(start+1);i<stop;i+=2){
fprintf(fp, "%s = %s\n",argv[i],argv[i+1]);
}
*argv_ptr += stop;
*argc_ptr -= stop;
//?????????????????
//printf("Hardware Start is %i and Stop is %i\n",start,stop);
return 0;
}
int get_intr_setup (FILE *fp, int *argc_ptr, char ***argv_ptr)
{
char **argv = *argv_ptr;
int argc = *argc_ptr;
int i, start=0, stop=0, sfound=0;
for (i=0;i<argc;i++){
//?????????????????????
//printf("INTR SETUP: Argv %i is %s\n",i,argv[i]);
if ((strstr(argv[i],"[") != NULL) && !sfound){
start = i;
sfound = 1;
continue;
}
if (strstr(argv[i],"[") != NULL){
stop = i;
break;
}
}
if (!stop){
stop=argc;
}
if ((stop-1)%2){
printf("ERROR: Insuficient/Too many Interface Setup arguments\n");
return 1;
}
fprintf(fp, "\n%s\n", argv[start]);
for (i=(start+1);i<stop;i+=2){
fprintf(fp, "%s = %s\n",argv[i],argv[i+1]);
}
*argv_ptr += stop;
*argc_ptr -= stop;
//?????????????????
//printf("Interface SETUP Start is %i and Stop is %i\n",start,stop);
if (stop != argc){
get_intr_setup (fp, argc_ptr, argv_ptr);
}
return 0;
}
int conf_file_down (void)
{
FILE* file;
char* conf; /* -> section buffer */
char devname[WAN_DRVNAME_SZ];
char *token[MAX_TOKENS];
int toknum, err;
//printf("Shutting down Device %s\n",conf_file);
file = fopen(conf_file, "r");
if (file == NULL) {
show_error(ERR_SYSTEM);
return ERR_SYSTEM;
}
/* Read [devices] section */
conf = read_conf_section(file, "devices");
if (conf == NULL){
fclose(file);
return ERR_CONFIG;
}
toknum = tokenize(conf, token);
if (toknum < 2){
fclose(file);
free(conf);
return 1;
}
strncpy(devname, token[0], WAN_DRVNAME_SZ);
err = router_down (devname,0);
if (!err && verbose)
printf ("Done\n");
free(conf);
fclose(file);
return err;
}
/* ========================================================================
* Part of the Dameon code
*/
#if 0
#define SET_BINARY(f) (void)0
static unsigned long sysv_sum_file (const char *file)
{
int fd;
unsigned char buf[8192];
register unsigned long checksum = 0;
int bytes_read;
fd = open (file, O_RDONLY);
if (fd < 0){
//perror("checksum file: ");
return 0;
}
/* Need binary I/O, or else byte counts and checksums are incorrect. */
SET_BINARY (fd);
while ((bytes_read = safe_read (fd, buf, sizeof buf)) > 0){
register int i;
for (i = 0; i < bytes_read; i++){
checksum += buf[i];
}
}
if (bytes_read < 0){
perror("bytes read: ");
close(fd);
return 0;
}
close(fd);
return checksum;
}
#endif
#define TIME_STRING_BUF 50
char *time_string(time_t t,char *buf)
{
struct tm *local;
local = localtime(&t);
strftime(buf,TIME_STRING_BUF,"%d",local);
return buf;
}
int has_config_changed(link_def_t *linkdef, char *name)
{
char filename[50];
//unsigned long checksum;
time_t modified;
struct stat statbuf;
char timeBuf[TIME_STRING_BUF];
snprintf(filename,50,"/etc/wanpipe/%s.conf",name);
if (lstat(filename,&statbuf)){
return -1;
}
// printf("Access Time : %s %i\n",time_string(statbuf.st_atime,timeBuf),statbuf.st_atime);
// printf("Modified Time: %s %i\n",time_string(statbuf.st_mtime,timeBuf),statbuf.st_mtime);
// printf("Creation Time: %s %i\n",time_string(statbuf.st_ctime,timeBuf),statbuf.st_ctime);
modified = statbuf.st_mtime;
// checksum = sysv_sum_file(filename);
//printf("%s Check sum %u\n",name,checksum);
if (!linkdef){
link_def_t *def;
for (def=link_defs;def;def=def->next){
if (!strcmp(def->name,name)){
linkdef=def;
break;
}
}
if (!linkdef){
return -1;
}
}
// if (linkdef->checksum != checksum){
//
// linkdef->checksum = checksum;
// printf("%s: Configuration file %s changed\n",prognamed,filename);
// return 1;
// }
if (linkdef->modified != modified){
linkdef->modified = modified;
printf("%s: Configuration file %s changed: %s \n",
prognamed,filename,time_string(modified,timeBuf));
return 1;
}
return 0;
}
void free_device_link(char *devname)
{
link_def_t *linkdef,*prev_lnk=link_defs;
for (linkdef = link_defs; linkdef; linkdef = linkdef->next){
if (!strcmp(linkdef->name, devname)){
while (linkdef->chan) {
chan_def_t* chandef = linkdef->chan;
if (chandef->conf) free(chandef->conf);
if (chandef->conf_profile) free(chandef->conf_profile);
if (chandef->addr) free(chandef->addr);
if (chandef->usedby) free(chandef->usedby);
if (chandef->protocol) free(chandef->protocol);
if (chandef->label) free(chandef->label);
if (chandef->virtual_addr) free(chandef->virtual_addr);
if (chandef->real_addr) free(chandef->real_addr);
linkdef->chan = chandef->next;
if (chandef->chanconf){
free(chandef->chanconf);
}
free(chandef);
}
if (linkdef->conf) free(linkdef->conf);
if (linkdef->descr) free(linkdef->descr);
if (linkdef == link_defs){
link_defs = linkdef->next;
}else{
prev_lnk->next = linkdef->next;
}
printf("%s: Freeing Link %s\n",prognamed,linkdef->name);
if (linkdef->linkconf){
free(linkdef->linkconf);
}
free(linkdef);
return;
}
prev_lnk=linkdef;
}
}
void free_linkdefs(void)
{
/* Clear definition list */
while (link_defs != NULL) {
link_def_t* linkdef = link_defs;
while (linkdef->chan) {
chan_def_t* chandef = linkdef->chan;
if (chandef->conf) free(chandef->conf);
if (chandef->conf_profile) free(chandef->conf_profile);
if (chandef->addr) free(chandef->addr);
if (chandef->usedby) free(chandef->usedby);
if (chandef->protocol) free(chandef->protocol);
if (chandef->label) free(chandef->label);
if (chandef->virtual_addr) free(chandef->virtual_addr);
if (chandef->real_addr) free(chandef->real_addr);
linkdef->chan = chandef->next;
if (chandef->chanconf){
free(chandef->chanconf);
}
free(chandef);
}
if (linkdef->conf) free(linkdef->conf);
if (linkdef->descr) free(linkdef->descr);
if (linkdef->linkconf){
free(linkdef->linkconf);
}
link_defs = linkdef->next;
free(linkdef);
}
}
int device_syncup(char *devname)
{
char filename[100];
int err;
free_device_link(devname);
snprintf(filename,100,"%s/%s.conf",conf_dir,devname);
printf("%s: Parsing configuration file %s\n",prognamed,filename);
err = parse_conf_file(filename);
if (err){
return -EINVAL;
}
has_config_changed(link_defs,link_defs->name);
err = configure_link(link_defs,1);
if (err){
return -EINVAL;
}
return 0;
}
void sig_func (int sigio)
{
if (sigio == SIGUSR1){
printf("%s: Rx signal USR1, User prog ok\n",prognamed);
return;
}
if (sigio == SIGUSR2){
time_t time_var;
time(&time_var);
if ((time_var-time_ui) > MAX_WAKEUI_WAIT){
time_ui=time_var;
wakeup_ui=1;
}
//else{
// printf("%s: Ignoring Wakeup UI %i\n",
// prognamed,time_var-time_ui);
//}
return;
}
if (sigio == SIGHUP){
printf("%s: Rx signal HUP: Terminal closed!\n",prognamed);
return;
}
printf("%s: Rx TERM/INT (%i) singal, freeing links\n",prognamed,sigio);
free_linkdefs();
unlink(WANCONFIG_SOCKET);
unlink(WANCONFIG_PID);
exit(1);
}
int start_chan (int dev, link_def_t *def)
{
int err=ERR_SYSTEM;
chan_def_t *chandef;
for (chandef = def->chan; chandef; chandef = chandef->next) {
switch (chandef->annexg){
case NO_ANNEXG:
strncpy(master_lapb_dev,chandef->name, WAN_IFNAME_SZ);
strncpy(master_lip_dev,chandef->name, WAN_IFNAME_SZ);
break;
case ANNEXG_LAPB:
strncpy(master_x25_dev,chandef->name, WAN_IFNAME_SZ);
break;
case ANNEXG_X25:
strncpy(master_dsp_dev,chandef->name, WAN_IFNAME_SZ);
break;
}
if (!dev_name || !strcmp(chandef->name,dev_name)){
if (verbose){
printf(
" * Configuring channel %s (%s). Media address: %s\n",
chandef->name,
"no description",
chandef->addr ? chandef->addr : "not specified");
}
err=exec_chan_cmd(dev,chandef);
if (err){
return err;
}
if (!dev_name){
continue;
}else{
return err;
}
}
}
return err;
}
int start_link (void)
{
link_def_t* linkdef;
int err=-EINVAL;
int dev=-1;
char filename[100];
if (!link_defs){
if (card_name){
err=device_syncup(card_name);
if (err){
return err;
}
}else{
printf("%s: No wanpipe links initialized!\n",prognamed);
return err;
}
}else{
if (card_name){
if (has_config_changed(NULL,card_name)!=0){
err=device_syncup(card_name);
if (err){
return err;
}
}
}else{
start_cfg_chk:
for (linkdef = link_defs; linkdef; linkdef = linkdef->next){
if (has_config_changed(linkdef,linkdef->name)!=0){
err=device_syncup(linkdef->name);
if (err){
return err;
}
goto start_cfg_chk;
}
}
}
}
printf("\n%s: Starting Card %s\n",prognamed,card_name?card_name:"All Cards");
for (linkdef = link_defs; linkdef; linkdef = linkdef->next){
if (!card_name || !strcmp(linkdef->name,card_name)){
if (verbose){
printf(" * Configuring device %s (%s)\n",
linkdef->name,
card_name?card_name:linkdef->name);
}
fflush(stdout);
snprintf(filename, 100,"%s/%s", router_dir, linkdef->name);
dev = open(filename, O_RDONLY);
if (dev<0){
printf("%s: Failed to open file %s\n",prognamed,filename);
return -EIO;
}
linkdef->linkconf->ft1 = 0;
err=exec_link_cmd(dev,linkdef);
if (err){
close(dev);
return err;
}
err=start_chan(dev,linkdef);
if (err){
close(dev);
return err;
}
close(dev);
if (!card_name){
continue;
}else{
break;
}
}
}
return err;
}
int stop_link(void)
{
link_def_t* linkdef;
int err=3;
if (card_name){
if (!dev_name){
return router_down(card_name,0);
}else{
return router_ifdel(card_name,dev_name);
}
}
if (!link_defs){
printf("%s: Stop Link Error: No links initialized!\n",prognamed);
return err;
}
for (linkdef = link_defs; linkdef; linkdef = linkdef->next){
if (verbose){
printf(" * Configuring device %s (%s)\n",
linkdef->name,
dev_name?dev_name:"card");
}
err=router_down(linkdef->name,0);
if (err){
return err;
}
}
return err;
}
/*======================================================
* exec_command
*
* cmd=[sync|start|stop|restart]
* card=<device name> # wanpipe# {#=1,2,3...}
* dev=<interface name> # wp1_fr16
*
*/
int exec_command(char *rx_data)
{
int toknum;
char *card_str=NULL;
char *dev_str=NULL;
int err=-ENOEXEC;
char *token[MAX_TOKENS];
toknum = tokenize((char*)rx_data, token);
if (toknum < 2){
printf("%s: Invalid client cmd = %s\n",prognamed,rx_data);
return -ENOEXEC;
}
//printf("FIRST TOKNUM = %i\n",toknum);
if (!strcmp(token[0],"cmd")){
//printf("Command is %s\n",token[1]);
command=strdup(token[1]);
}else{
printf("%s: Invalid client command syntax : %s!\n",prognamed,rx_data);
goto exec_cmd_exit;
}
if (toknum > 2){
card_str=strdup(token[2]);
}
if (toknum > 3){
dev_str=strdup(token[3]);
}
if (card_str){
toknum = tokenize(card_str, token);
if (toknum < 2){
printf("%s: Invalid client command syntax : %s!\n",prognamed,card_str);
goto exec_cmd_exit;
}
if (!strcmp(token[0],"card")){
card_name=strdup(token[1]);
//printf("Card is %s\n",card_name);
}
if (dev_str){
toknum = tokenize(dev_str, token);
if (toknum < 2){
printf("%s: Invalid client command syntax : %s!\n",prognamed,dev_str);
goto exec_cmd_exit;
}
if (!strcmp(token[0],"dev")){
dev_name=strdup(token[1]);
}
}
}
err=-EINVAL;
if (!strcmp(command,"start")){
err=start_link();
}else if (!strcmp(command,"stop")){
err=stop_link();
}else if (!strcmp(command,"restart")){
err=stop_link();
err=start_link();
}else if (!strcmp(command,"init")){
if (card_name){
err=device_syncup(card_name);
}else{
printf("%s: Error: cmd=init : invalid card name!\n",prognamed);
}
}else{
printf("%s: Error invalid client cmd=%s!\n",prognamed,command);
}
exec_cmd_exit:
fflush(stdout);
if (card_str){
free(card_str);
card_str=NULL;
}
if (dev_str){
free(dev_str);
dev_str=NULL;
}
if (command){
free(command);
command=NULL;
}
if (card_name){
free(card_name);
card_name=NULL;
}
if (dev_name){
free(dev_name);
dev_name=NULL;
}
return err;
}
void catch_signal(int signum,int nomask)
{
struct sigaction sa;
memset(&sa,0,sizeof(sa));
sa.sa_handler=sig_func;
if (nomask){
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
sa.sa_flags |= SA_NODEFER;
#else
sa.sa_flags |= SA_NOMASK;
#endif
}
if (sigaction(signum,&sa,NULL))
perror("sigaction");
}
int start_daemon(void)
{
struct sockaddr_un address;
int sock,conn;
socklen_t addrLength;
char rx_data[100];
int err;
int fp;
struct stat file_stat;
verbose=1;
if (fork() !=0){
exit(0);
}
setsid();
setuid(0); /* set real UID = root */
setgid(getegid());
snprintf(prognamed,20,"wanconfigd[%i]",getpid());
memset(&rx_data[0],0,100);
memset(&address,0,sizeof(struct sockaddr_un));
#if 0
signal(SIGTERM,sig_func);
signal(SIGINT,sig_func);
signal(SIGUSR1,sig_func);
signal(SIGUSR2,sig_func);
#endif
catch_signal(SIGTERM,0);
catch_signal(SIGINT,0);
catch_signal(SIGUSR1,0);
catch_signal(SIGUSR2,0);
catch_signal(SIGHUP,0);
if ((sock=socket(PF_UNIX,SOCK_STREAM,0)) < 0){
perror("socket: ");
return sock;
}
address.sun_family=AF_UNIX;
strlcpy(address.sun_path, WANCONFIG_SOCKET, sizeof(address.sun_path));
addrLength = sizeof(address.sun_family) + strlen(address.sun_path);
if (bind(sock,(struct sockaddr*) &address, addrLength)){
perror("bind: ");
return -1;
}
if (listen(sock,10)){
perror("listen: ");
return -1;
}
fp=open(WANCONFIG_PID,(O_CREAT|O_WRONLY),0644);
if (fp){
char pid_str[10];
snprintf(pid_str,10,"%i",getpid());
write(fp,&pid_str,strlen(pid_str));
close(fp);
}
err = stat(WANCONFIG_PID_FILE, &file_stat);
if (err<0){
printf("\n\nWarning: Failed pid write: rc=%i\n\n",err);
}else{
snprintf(rx_data,100,"echo %i > %s",getpid(),WANCONFIG_PID_FILE);
if ((err=system(rx_data)) != 0){
printf("\n\nWarning: Failed pid write: rc=%i\n\n",err);
}
}
memset(&rx_data[0],0,100);
printf("%s: ready and listening:\n\n",prognamed);
tryagain:
while ((conn=accept(sock,(struct sockaddr*)&address,&addrLength))>=0){
memset(rx_data,0,100);
/* Wait for a command from client */
err=recv(conn,rx_data,100,0);
if (err>0){
printf("\n%s: rx cmdstr: %s\n",
prognamed,rx_data);
}else{
printf("%s: Error: received %i from new descriptor %i !\n",
prognamed,conn,err);
perror("recv: ");
close(conn);
continue;
}
fflush(stdout);
err=exec_command(rx_data);
err=abs(err);
if (err){
printf("%s: Cmd Error err=%i: %s\n\n\n",
prognamed,err,strerror(err));
}else{
printf("%s: Cmd OK err=%i\n\n\n",prognamed,err);
}
/* Reply to client the result of the command */
*((short*)&rx_data[0])=err;
err=send(conn,rx_data,2,0);
if (err != 2){
perror("send: ");
close(conn);
fflush(stdout);
continue;
}
close(conn);
if (wakeup_ui){
wakeup_ui=0;
wakeup_java_ui();
}
fflush(stdout);
}
if (conn<0){
if (errno == EINTR){
if (wakeup_ui){
wakeup_ui=0;
wakeup_java_ui();
}
goto tryagain;
}
printf("%s: Accept err = %i\n",prognamed,errno);
perror("Accept: ");
}
printf("%s: Warning: Tried to exit! conn=%i errno=%i\n",
prognamed,conn,errno);
goto tryagain;
close(sock);
unlink(WANCONFIG_SOCKET);
unlink(WANCONFIG_PID);
return 0;
}
#define UI_JAVA_PID_FILE "/var/run/ui.pid"
static time_t ui_checksum=0;
static pid_t ui_pid=0;
void wakeup_java_ui(void)
{
time_t checksum;
FILE *file;
char buf[50];
struct stat statbuf;
if (lstat(UI_JAVA_PID_FILE,&statbuf)){
return;
}
checksum = statbuf.st_mtime;
if (ui_checksum != checksum){
ui_checksum = checksum;
file = fopen(UI_JAVA_PID_FILE, "r");
if( file == NULL ) {
fprintf( stderr, "%s: cannot open %s\n",
prognamed, UI_JAVA_PID_FILE);
return;
}
fgets(buf, sizeof(buf)-1, file);
ui_pid=atoi(buf);
fclose(file);
}
if (ui_pid){
if (kill(ui_pid,SIGUSR2) == 0){
printf("%s: Kicked Java UI: %u\n",prognamed,ui_pid);
}else{
printf("%s: Failed to kick UI: %u : %s\n",prognamed,ui_pid,strerror(errno));
}
}
return;
}
int show_config(void)
{
int err = 0;
#if defined(__LINUX__)
char statbuf[80];
snprintf(statbuf, sizeof(statbuf), "%s/%s", router_dir, "config");
gencat(statbuf);
#else
int dev;
wan_procfs_t procfs;
dev = open(WANDEV_NAME, O_RDONLY);
if (dev < 0){
show_error(ERR_MODULE);
return errno;
}
config.arg = &procfs;
memset(&procfs, 0, sizeof(wan_procfs_t));
procfs.magic = ROUTER_MAGIC;
procfs.max_len = 2048;
procfs.cmd = WANPIPE_PROCFS_CONFIG;
procfs.data = malloc(2048);
if (procfs.data == NULL){
show_error(ERR_SYSTEM);
return -EINVAL;
}
if (ioctl(dev, ROUTER_PROCFS, &config) < 0){
show_error(ERR_SYSTEM);
goto show_config_end;
}else{
if (procfs.offs){
int i = 0;
for (i=0;i<procfs.offs;i++){
putchar(*((unsigned char *)procfs.data + i));
fflush(stdout);
}
}
}
show_config_end:
if (dev >= 0) close(dev);
free(procfs.data);
#endif
return err;
}
int show_status(void)
{
int err = 0;
#if defined(__LINUX__)
char statbuf[80];
if (card_name != NULL){
snprintf(statbuf, sizeof(statbuf), "%s/%s", router_dir, card_name);
gencat(statbuf);
}else{
snprintf(statbuf, sizeof(statbuf), "%s/%s", router_dir, "status");
gencat(statbuf);
}
#else
int dev;
wan_procfs_t procfs;
dev = open(WANDEV_NAME, O_RDONLY);
if (dev < 0){
show_error(ERR_MODULE);
return -ENODEV;
}
config.arg = &procfs;
memset(&procfs, 0, sizeof(wan_procfs_t));
procfs.magic = ROUTER_MAGIC;
procfs.max_len = 2048;
procfs.cmd = WANPIPE_PROCFS_STATUS;
procfs.data = malloc(2048);
if (procfs.data == NULL){
show_error(ERR_SYSTEM);
return -EINVAL;
}
if (ioctl(dev, ROUTER_PROCFS, &config) < 0){
show_error(ERR_SYSTEM);
goto show_status_end;
}else{
if (procfs.offs){
int i = 0;
for (i=0;i<procfs.offs;i++){
putchar(*((unsigned char *)procfs.data + i));
fflush(stdout);
}
}
}
show_status_end:
if (dev >= 0) close(dev);
free(procfs.data);
#endif
return err;
}
int show_hwprobe(int action)
{
int err = 0;
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
int dev;
wan_procfs_t procfs;
dev = open(WANDEV_NAME, O_RDONLY);
if (dev < 0){
show_error(ERR_MODULE);
return -ENODEV;
}
config.arg = &procfs;
memset(&procfs, 0, sizeof(wan_procfs_t));
procfs.magic = ROUTER_MAGIC;
procfs.max_len = 2048;
procfs.cmd = (action == DO_SHOW_HWPROBE) ? WANPIPE_PROCFS_HWPROBE :
(action == DO_SHOW_HWPROBE_LEGACY) ? WANPIPE_PROCFS_HWPROBE_LEGACY :
WANPIPE_PROCFS_HWPROBE_VERBOSE ;
procfs.data = malloc(2048);
if (procfs.data == NULL){
show_error(ERR_SYSTEM);
err=-EINVAL;
goto show_probe_end;
}
if (ioctl(dev, ROUTER_PROCFS, &config) < 0){
show_error(ERR_SYSTEM);
err=-EINVAL;
goto show_probe_end;
}else{
if (procfs.offs){
int i = 0;
for (i=0;i<procfs.offs;i++){
putchar(*((unsigned char *)procfs.data + i));
fflush(stdout);
}
}
}
show_probe_end:
if (dev >= 0) close(dev);
free(procfs.data);
#endif
return err;
}
int debugging(void)
{
int dev;
int err = 0, max_len = sizeof(router_dir) + WAN_DRVNAME_SZ;
char filename[max_len + 2];
if (dev_name == NULL){
fprintf(stderr, "\n\n\tPlease specify device name!\n");
show_error(ERR_SYSTEM);
return -EINVAL;
}
#if defined(__LINUX__)
snprintf(filename, max_len, "%s/%s", router_dir, dev_name);
#else
snprintf(filename, max_len, "%s", WANDEV_NAME);
#endif
dev = open(filename, O_RDONLY);
if (dev < 0){
fprintf(stderr, "\n\n\tFAILED open device %s!\n",
WANDEV_NAME);
show_error(ERR_MODULE);
return -EINVAL;
}
/* Clear configuration structure */
memset(&u.linkconf, 0, sizeof(wandev_conf_t));
u.linkconf.magic = ROUTER_MAGIC;
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
strlcpy(config.devname, dev_name, WAN_DRVNAME_SZ);
config.arg = NULL;
if (ioctl(dev, ROUTER_DEBUGGING, &config) < 0){
//if (ioctl(dev, ROUTER_DEBUGGING, NULL) < 0){
fprintf(stderr, "\n\n\tROUTER DEBUGGING failed!!\n");
show_error(ERR_SYSTEM);
err=-EINVAL;
}
#else
/* Linux currently doesn't support this option */
err=-EINVAL;
#endif
if (dev >= 0){
close(dev);
}
return err;
}
int debug_read(void)
{
int dev;
int err = 0, max_len = sizeof(router_dir) + WAN_DRVNAME_SZ;
char filename[max_len + 2];
wan_kernel_msg_t wan_kernel_msg;
if (dev_name == NULL){
fprintf(stderr, "\n\n\tPlease specify device name!\n");
show_error(ERR_SYSTEM);
return -EINVAL;
}
#if defined(__LINUX__)
snprintf(filename, max_len, "%s/%s", router_dir, dev_name);
#else
snprintf(filename, max_len, "%s", WANDEV_NAME);
#endif
dev = open(filename, O_RDONLY);
if (dev < 0){
fprintf(stderr, "\n\n\tFAILED open device %s!\n",
WANDEV_NAME);
show_error(ERR_MODULE);
return -EINVAL;
}
/* Clear configuration structure */
memset(&u.linkconf, 0, sizeof(wandev_conf_t));
u.linkconf.magic = ROUTER_MAGIC;
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
strlcpy(config.devname, dev_name, WAN_DRVNAME_SZ);
config.arg = &wan_kernel_msg;
#endif
debug_read_again:
memset(&wan_kernel_msg, 0, sizeof(wan_kernel_msg_t));
wan_kernel_msg.magic = ROUTER_MAGIC;
wan_kernel_msg.max_len = 2048;
wan_kernel_msg.data = malloc(2048);
if (wan_kernel_msg.data == NULL){
show_error(ERR_SYSTEM);
err=-EINVAL;
goto debug_read_end;
}
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
if (ioctl(dev, ROUTER_DEBUG_READ, &config) < 0){
#else
if (ioctl(dev, ROUTER_DEBUG_READ, &wan_kernel_msg) < 0){
#endif
fprintf(stderr, "\n\n\tROUTER DEBUG_READ failed!!\n");
show_error(ERR_SYSTEM);
err=-EINVAL;
}else{
if (wan_kernel_msg.len){
int i = 0;
for (i=0;i<wan_kernel_msg.len;i++){
putchar(*((unsigned char *)wan_kernel_msg.data + i));
fflush(stdout);
}
if (wan_kernel_msg.is_more){
goto debug_read_again;
}
}
}
debug_read_end:
if (dev >= 0){
close(dev);
}
free(wan_kernel_msg.data);
return err;
}
void update_adsl_vci_vpi_list(wan_adsl_vcivpi_t* vcivpi_list, unsigned short vcivpi_num)
{
FILE* file = NULL, *tmp_file = NULL;
char buf[256];
int x = 0;
file = fopen(adsl_file, "r");
tmp_file = fopen(tmp_adsl_file, "w");
if (file == NULL || tmp_file == NULL){
printf(" * ADSL VCI/VPI list file doens't exists (skip)\n");
if (file) fclose(file);
if (tmp_file) fclose(tmp_file);
return;
#if 0
fprintf( stderr, "%s: cannot open %s or %s\n",
prognamed, adsl_file, tmp_adsl_file);
if (file) fclose(file);
if (tmp_file) fclose(tmp_file);
show_error(ERR_SYSTEM);
exit(ERR_SYSTEM);
#endif
}
while(fgets(buf, sizeof(buf) -1, file)){
if (buf[0] != '#'){
break;
}else{
fprintf(tmp_file, buf);
}
}
for(x = 0; x < vcivpi_num; x++){
fprintf(tmp_file, "%d %d\n",
vcivpi_list[x].vci,
vcivpi_list[x].vpi);
}
fclose(file);
fclose(tmp_file);
rename(tmp_adsl_file, adsl_file);
return;
}
void read_adsl_vci_vpi_list(wan_adsl_vcivpi_t* vcivpi_list, unsigned short* vcivpi_num)
{
FILE* file = NULL;
char buf[256];
int num = 0;
int vci, vpi;
file = fopen(adsl_file, "r");
if (file == NULL){
printf(" * ADSL VCI/VPI list file doens't exists (skip)\n");
*vcivpi_num = 0;
return;
#if 0
fprintf( stderr, "%s: cannot open %s\n",
prognamed, adsl_file);
show_error(ERR_SYSTEM);
exit(ERR_SYSTEM);
#endif
}
while(fgets(buf, sizeof(buf) -1, file)){
if (buf[0] != '#'){
sscanf(buf, "%d %d", &vci, &vpi);
vcivpi_list[num].vci = (unsigned short)vci;
vcivpi_list[num].vpi = (unsigned char)vpi;
num++;
if (num >= 100){
break;
}
}
}
*vcivpi_num = num;
fclose(file);
return;
}
/*============================================================================
* TE1
* Parse active channel string.
*
* Return ULONG value, that include 1 in position `i` if channels i is active.
*/
unsigned int parse_active_channel(char* val)
{
#define SINGLE_CHANNEL 0x2
#define RANGE_CHANNEL 0x1
int channel_flag = 0;
char* ptr = val;
int channel = 0, start_channel = 0;
unsigned int tmp = 0;
if (strcmp(val,"ALL") == 0)
return ENABLE_ALL_CHANNELS;
if (strcmp(val,"0") == 0)
return 0;
while(*ptr != '\0') {
//printf("\nMAP DIGIT %c\n", *ptr);
if (isdigit(*ptr)) {
channel = strtoul(ptr, &ptr, 10);
channel_flag |= SINGLE_CHANNEL;
} else {
if (*ptr == '-') {
channel_flag |= RANGE_CHANNEL;
start_channel = channel;
} else {
tmp |= get_active_channels(channel_flag, start_channel, channel);
channel_flag = 0;
}
ptr++;
}
}
if (channel_flag){
tmp |= get_active_channels(channel_flag, start_channel, channel);
}
return tmp;
}
/*============================================================================
* TE1
*/
unsigned int get_active_channels(int channel_flag, int start_channel, int stop_channel)
{
int i = 0;
unsigned int tmp = 0, mask = 0;
/* If the channel map is set to 0 then
* stop_channel will be zero. In this case just return
* 0 */
if (stop_channel < 1) {
return 0;
}
if ((channel_flag & (SINGLE_CHANNEL | RANGE_CHANNEL)) == 0)
return tmp;
if (channel_flag & RANGE_CHANNEL) { /* Range of channels */
for(i = start_channel; i <= stop_channel; i++) {
mask = 1 << (i - 1);
tmp |=mask;
}
} else { /* Single channel */
mask = 1 << (stop_channel - 1);
tmp |= mask;
}
return tmp;
}
//****** End *****************************************************************/