File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / command.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:44:29 2013 UTC (11 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_7p0, v5_7, HEAD
5.7

    1: 
    2: /*
    3:  * command.c
    4:  *
    5:  * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
    6:  * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
    7:  * See ``COPYRIGHT.iij''
    8:  * 
    9:  * Rewritten by Archie Cobbs <archie@freebsd.org>
   10:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
   11:  * See ``COPYRIGHT.whistle''
   12:  */
   13: 
   14: #include "msg.h"
   15: #include "ppp.h"
   16: #include "console.h"
   17: #ifndef NOWEB
   18: #include "web.h"
   19: #endif
   20: #include "radsrv.h"
   21: #include "command.h"
   22: #include "ccp.h"
   23: #include "iface.h"
   24: #include "radius.h"
   25: #include "bund.h"
   26: #include "link.h"
   27: #include "lcp.h"
   28: #ifdef	USE_NG_NAT
   29: #include "nat.h"
   30: #endif
   31: #include "ipcp.h"
   32: #include "ip.h"
   33: #include "ippool.h"
   34: #include "devices.h"
   35: #include "netgraph.h"
   36: #include "ngfunc.h"
   37: #ifdef CCP_MPPC
   38: #include "ccp_mppc.h"
   39: #endif
   40: #include "util.h"
   41: #ifdef USE_FETCH
   42: #include <fetch.h>
   43: #endif
   44: #ifdef USE_NG_NETFLOW
   45: #include <netgraph/netflow/ng_netflow.h>
   46: #endif
   47: 
   48: /*
   49:  * DEFINITIONS
   50:  */
   51: 
   52:   struct layer {
   53:     const char	*name;
   54:     int		(*opener)(Context ctx);
   55:     int		(*closer)(Context ctx);
   56:     int		(*admit)(Context ctx, CmdTab cmd);
   57:     const char	*desc;
   58:   };
   59:   typedef struct layer	*Layer;
   60: 
   61:   #define DEFAULT_OPEN_LAYER	"link"
   62: 
   63:   /* Set menu options */
   64:   enum {
   65:     SET_ENABLE,
   66:     SET_DISABLE,
   67: #ifdef USE_IPFW
   68:     SET_RULE,
   69:     SET_QUEUE,
   70:     SET_PIPE,
   71:     SET_TABLE,
   72: #endif
   73: #ifdef PHYSTYPE_PPTP
   74:     SET_PPTPTO,
   75:     SET_PPTPLIMIT,
   76: #endif
   77: #ifdef PHYSTYPE_L2TP
   78:     SET_L2TPTO,
   79:     SET_L2TPLIMIT,
   80: #endif
   81:     SET_MAX_CHILDREN,
   82:     SET_QTHRESHOLD,
   83: #ifdef USE_NG_BPF
   84:     SET_FILTER
   85: #endif
   86:   };
   87: 
   88:   enum {
   89:     SHOW_IFACE,
   90:     SHOW_IP,
   91:     SHOW_USER,
   92:     SHOW_SESSION,
   93:     SHOW_MSESSION,
   94:     SHOW_BUNDLE,
   95:     SHOW_LINK,
   96:     SHOW_PEER
   97:   };
   98: 
   99: /*
  100:  * INTERNAL FUNCTIONS
  101:  */
  102: 
  103:   /* Commands */
  104:   static int	ShowVersion(Context ctx, int ac, char *av[], void *arg);
  105:   static int	ShowLayers(Context ctx, int ac, char *av[], void *arg);
  106:   static int	ShowTypes(Context ctx, int ac, char *av[], void *arg);
  107:   static int	ShowSummary(Context ctx, int ac, char *av[], void *arg);
  108:   static int	ShowSessions(Context ctx, int ac, char *av[], void *arg);
  109:   static int	ShowCustomer(Context ctx, int ac, char *av[], void *arg);
  110:   static int	ShowEvents(Context ctx, int ac, char *av[], void *arg);
  111:   static int	ShowGlobal(Context ctx, int ac, char *av[], void *arg);
  112:   static int	OpenCommand(Context ctx, int ac, char *av[], void *arg);
  113:   static int	CloseCommand(Context ctx, int ac, char *av[], void *arg);
  114:   static int	LoadCommand(Context ctx, int ac, char *av[], void *arg);
  115:   static int	ExitCommand(Context ctx, int ac, char *av[], void *arg);
  116:   static int	QuitCommand(Context ctx, int ac, char *av[], void *arg);
  117:   static int	GlobalSetCommand(Context ctx, int ac, char *av[], void *arg);
  118:   static int	SetDebugCommand(Context ctx, int ac, char *av[], void *arg);
  119: 
  120:   /* Other stuff */
  121:   static Layer	GetLayer(const char *name);
  122: 
  123: /*
  124:  * INTERNAL VARIABLES
  125:  */
  126: 
  127:   const struct cmdtab GlobalSetCmds[] = {
  128:     { "enable {opt ...}", 		"Enable option" ,
  129:        	GlobalSetCommand, NULL, 2, (void *) SET_ENABLE },
  130:     { "disable {opt ...}", 		"Disable option" ,
  131:        	GlobalSetCommand, NULL, 2, (void *) SET_DISABLE },
  132: #ifdef USE_IPFW
  133:     { "startrule {num}",		"Initial ipfw rule number" ,
  134:        	GlobalSetCommand, NULL, 2, (void *) SET_RULE },
  135:     { "startqueue {num}", 		"Initial ipfw queue number" ,
  136:        	GlobalSetCommand, NULL, 2, (void *) SET_QUEUE },
  137:     { "startpipe {num}",		"Initial ipfw pipe number" ,
  138:        	GlobalSetCommand, NULL, 2, (void *) SET_PIPE },
  139:     { "starttable {num}", 		"Initial ipfw table number" ,
  140:        	GlobalSetCommand, NULL, 2, (void *) SET_TABLE },
  141: #endif /* USE_IPFW */
  142: #ifdef PHYSTYPE_L2TP
  143:     { "l2tptimeout {sec}", 		"L2TP tunnel unused timeout" ,
  144:        	GlobalSetCommand, NULL, 2, (void *) SET_L2TPTO },
  145:     { "l2tplimit {num}", 		"Calls per L2TP tunnel limit" ,
  146:        	GlobalSetCommand, NULL, 2, (void *) SET_L2TPLIMIT },
  147: #endif
  148: #ifdef PHYSTYPE_PPTP
  149:     { "pptptimeout {sec}", 		"PPTP tunnel unused timeout" ,
  150:        	GlobalSetCommand, NULL, 2, (void *) SET_PPTPTO },
  151:     { "pptplimit {num}", 		"Calls per PPTP tunnel limit" ,
  152:        	GlobalSetCommand, NULL, 2, (void *) SET_PPTPLIMIT },
  153: #endif
  154:     { "max-children {num}",		"Max number of children",
  155: 	GlobalSetCommand, NULL, 2, (void *) SET_MAX_CHILDREN },
  156:     { "qthreshold {min} {max}",		"Message queue limit thresholds",
  157:         GlobalSetCommand, NULL, 2, (void *) SET_QTHRESHOLD },
  158: #ifdef USE_NG_BPF
  159:     { "filter {num} add|clear [\"{flt}\"]",	"Global traffic filters management",
  160: 	GlobalSetCommand, NULL, 2, (void *) SET_FILTER },
  161: #endif
  162:     { NULL },
  163:   };
  164: 
  165:   static const struct confinfo	gGlobalConfList[] = {
  166: #ifdef USE_WRAP
  167:     { 0,	GLOBAL_CONF_TCPWRAPPER,	"tcp-wrapper"	},
  168: #endif
  169:     { 0,	GLOBAL_CONF_ONESHOT,	"one-shot"	},
  170:     { 0,	0,			NULL		},
  171:   };
  172: 
  173:   static const struct cmdtab CreateCommands[] = {
  174:     { "link [template|static] {name} {template|type}",	"Create link/template",
  175: 	LinkCreate, NULL, 2, NULL },
  176:     { "bundle [template|static] {name} {template}",	"Create bundle/template",
  177: 	BundCreate, NULL, 2, NULL },
  178:     { NULL },
  179:   };
  180: 
  181:   static const struct cmdtab DestroyCommands[] = {
  182:     { "link [{name}]",			"Destroy link/template",
  183: 	LinkDestroy, NULL, 2, NULL },
  184:     { "bundle [{name}]",		"Destroy bundle/template",
  185: 	BundDestroy, NULL, 2, NULL },
  186:     { NULL },
  187:   };
  188: 
  189:   static const struct cmdtab ShowSessCmds[] = {
  190:     { "iface {name}",			"Filter by iface name",
  191: 	ShowSessions, NULL, 0, (void *) SHOW_IFACE },
  192:     { "ip {ip}",			"Filter by IP address",
  193: 	ShowSessions, NULL, 0, (void *) SHOW_IP },
  194:     { "user {name}",			"Filter by user name",
  195: 	ShowSessions, NULL, 0, (void *) SHOW_USER },
  196:     { "session {ID}",			"Filter by session ID",
  197: 	ShowSessions, NULL, 0, (void *) SHOW_SESSION },
  198:     { "msession {ID}",			"Filter by msession ID",
  199: 	ShowSessions, NULL, 0, (void *) SHOW_MSESSION },
  200:     { "bundle {name}",			"Filter by bundle name",
  201: 	ShowSessions, NULL, 0, (void *) SHOW_BUNDLE },
  202:     { "link {name}",			"Filter by link name",
  203: 	ShowSessions, NULL, 0, (void *) SHOW_LINK },
  204:     { "peer {name}",			"Filter by peer name",
  205: 	ShowSessions, NULL, 0, (void *) SHOW_PEER },
  206:     { NULL },
  207:   };
  208: 
  209:   static const struct cmdtab ShowCommands[] = {
  210:     { "bundle [{name}]",		"Bundle status",
  211: 	BundStat, AdmitBund, 0, NULL },
  212:     { "customer",			"Customer summary",
  213: 	ShowCustomer, NULL, 0, NULL },
  214:     { "repeater [{name}]",		"Repeater status",
  215: 	RepStat, AdmitRep, 0, NULL },
  216:     { "ccp",				"CCP status",
  217: 	CcpStat, AdmitBund, 0, NULL },
  218: #ifdef CCP_MPPC
  219:     { "mppc",				"MPPC status",
  220: 	MppcStat, AdmitBund, 0, NULL },
  221: #endif
  222:     { "ecp",				"ECP status",
  223: 	EcpStat, AdmitBund, 0, NULL },
  224:     { "eap",				"EAP status",
  225: 	EapStat, AdmitLink, 0, NULL },
  226:     { "events",				"Current events",
  227: 	ShowEvents, NULL, 0, NULL },
  228:     { "ipcp",				"IPCP status",
  229: 	IpcpStat, AdmitBund, 0, NULL },
  230:     { "ipv6cp",				"IPV6CP status",
  231: 	Ipv6cpStat, AdmitBund, 0, NULL },
  232:     { "ippool",				"IP pool status",
  233: 	IPPoolStat, NULL, 0, NULL },
  234:     { "iface",				"Interface status",
  235: 	IfaceStat, AdmitBund, 0, NULL },
  236:     { "routes",				"IP routing table",
  237: 	IpShowRoutes, NULL, 0, NULL },
  238:     { "layers",				"Layers to open/close",
  239: 	ShowLayers, NULL, 0, NULL },
  240:     { "device",				"Physical device status",
  241: 	PhysStat, AdmitLink, 0, NULL },
  242: #ifdef PHYSTYPE_PPTP
  243:     { "pptp",				"PPTP tunnels status",
  244: 	PptpsStat, NULL, 0, NULL },
  245: #endif
  246: #ifdef PHYSTYPE_L2TP
  247:     { "l2tp",				"L2TP tunnels status",
  248: 	L2tpsStat, NULL, 0, NULL },
  249: #endif
  250:     { "link",				"Link status",
  251: 	LinkStat, AdmitLink, 0, NULL },
  252:     { "auth",				"Auth status",
  253: 	AuthStat, AdmitLink, 0, NULL },
  254:     { "radius",				"RADIUS status",
  255: 	RadStat, AdmitLink, 0, NULL },
  256: #ifdef RAD_COA_REQUEST
  257:     { "radsrv",				"RADIUS server status",
  258: 	RadsrvStat, NULL, 0, NULL },
  259: #endif
  260:     { "lcp",				"LCP status",
  261: 	LcpStat, AdmitLink, 0, NULL },
  262: #ifdef	USE_NG_NAT
  263:     { "nat",				"NAT status",
  264: 	NatStat, AdmitBund, 0, NULL },
  265: #endif
  266:     { "mem",				"Memory map",
  267: 	MemStat, NULL, 0, NULL },
  268:     { "console",			"Console status",
  269: 	ConsoleStat, NULL, 0, NULL },
  270: #ifndef NOWEB
  271:     { "web",				"Web status",
  272: 	WebStat, NULL, 0, NULL },
  273: #endif
  274:     { "user",				"Console users" ,
  275:       	UserStat, NULL, 0, NULL },
  276:     { "global",				"Global settings",
  277: 	ShowGlobal, NULL, 0, NULL },
  278:     { "types",				"Supported device types",
  279: 	ShowTypes, NULL, 0, NULL },
  280:     { "version",			"Version string",
  281: 	ShowVersion, NULL, 0, NULL },
  282:     { "sessions [ {param} {value} ]",	"Active sessions",
  283: 	CMD_SUBMENU, NULL, 0, (void *) ShowSessCmds},
  284:     { "summary",			"Daemon status summary",
  285: 	ShowSummary, NULL, 0, NULL },
  286: #ifdef USE_NG_NETFLOW
  287:     { "netflow",			"Netflow settings",
  288: 	ShowNetflow, NULL, 0, NULL },
  289: #endif
  290:     { NULL },
  291:   };
  292: 
  293:   static const struct cmdtab UnSetCommands[] = {
  294:    { "radius ...",			"RADIUS specific stuff",
  295: 	CMD_SUBMENU, AdmitLink, 2, (void *) RadiusUnSetCmds },
  296: #ifdef NG_NAT_DESC_LENGTH
  297:    { "nat ...",			"NAT specific stuff",
  298: 	CMD_SUBMENU, AdmitBund, 2, (void *) NatUnSetCmds },
  299: #endif
  300: 	{ NULL },
  301:   };
  302:   
  303:   static const struct cmdtab SetCommands[] = {
  304:     { "bundle ...",			"Bundle specific stuff",
  305: 	CMD_SUBMENU, AdmitBund, 2, (void *) BundSetCmds },
  306:     { "link ...",			"Link specific stuff",
  307: 	CMD_SUBMENU, AdmitLink, 2, (void *) LinkSetCmds },
  308:     { "iface ...",			"Interface specific stuff",
  309: 	CMD_SUBMENU, AdmitBund, 2, (void *) IfaceSetCmds },
  310:     { "ipcp ...",			"IPCP specific stuff",
  311: 	CMD_SUBMENU, AdmitBund, 2, (void *) IpcpSetCmds },
  312:     { "ipv6cp ...",			"IPV6CP specific stuff",
  313: 	CMD_SUBMENU, AdmitBund, 2, (void *) Ipv6cpSetCmds },
  314:     { "ippool ...",			"IP pool specific stuff",
  315: 	CMD_SUBMENU, NULL, 2, (void *) IPPoolSetCmds },
  316:     { "ccp ...",			"CCP specific stuff",
  317: 	CMD_SUBMENU, AdmitBund, 2, (void *) CcpSetCmds },
  318: #ifdef CCP_MPPC
  319:     { "mppc ...",			"MPPC specific stuff",
  320: 	CMD_SUBMENU, AdmitBund, 2, (void *) MppcSetCmds },
  321: #endif
  322:     { "ecp ...",			"ECP specific stuff",
  323: 	CMD_SUBMENU, AdmitBund, 2, (void *) EcpSetCmds },
  324:     { "eap ...",			"EAP specific stuff",
  325: 	CMD_SUBMENU, AdmitLink, 2, (void *) EapSetCmds },
  326:     { "auth ...",			"Auth specific stuff",
  327: 	CMD_SUBMENU, AdmitLink, 2, (void *) AuthSetCmds },
  328:     { "radius ...",			"RADIUS specific stuff",
  329: 	CMD_SUBMENU, AdmitLink, 2, (void *) RadiusSetCmds },
  330: #ifdef RAD_COA_REQUEST
  331:     { "radsrv ...",			"RADIUS server specific stuff",
  332: 	CMD_SUBMENU, NULL, 2, (void *) RadsrvSetCmds },
  333: #endif
  334:     { "console ...",			"Console specific stuff",
  335: 	CMD_SUBMENU, NULL, 0, (void *) ConsoleSetCmds },
  336: #ifndef NOWEB
  337:     { "web ...",			"Web specific stuff",
  338: 	CMD_SUBMENU, NULL, 2, (void *) WebSetCmds },
  339: #endif
  340:     { "user {name} {password} [{priv}]",	"Add console user" ,
  341:       	UserCommand, NULL, 2, NULL },
  342:     { "global ...",			"Global settings",
  343: 	CMD_SUBMENU, NULL, 2, (void *) GlobalSetCmds },
  344: #ifdef USE_NG_NETFLOW
  345:     { "netflow ...", 			"NetFlow settings",
  346: 	CMD_SUBMENU, NULL, 2, (void *) NetflowSetCmds },
  347: #endif
  348: #ifdef	USE_NG_NAT
  349:     { "nat ...", 			"Nat settings",
  350: 	CMD_SUBMENU, NULL, 2, (void *) NatSetCmds },
  351: #endif
  352:     { "debug level",			"Set netgraph debug level",
  353: 	SetDebugCommand, NULL, 2, NULL },
  354: #define _WANT_DEVICE_CMDS
  355: #include "devices.h"
  356:     { NULL },
  357:   };
  358: 
  359:   const struct cmdtab gCommands[] = {
  360:     { "authname {name}",		"Choose link by auth name",
  361: 	AuthnameCommand, NULL, 0, NULL },
  362:     { "bundle [{name}]",		"Choose/list bundles",
  363: 	BundCommand, NULL, 0, NULL },
  364:     { "close [{layer}]",		"Close a layer",
  365: 	CloseCommand, NULL, 1, NULL },
  366:     { "create ...",			"Create new item",
  367:     	CMD_SUBMENU, NULL, 2, (void *) CreateCommands },
  368:     { "destroy ...",			"Destroy item",
  369:     	CMD_SUBMENU, NULL, 2, (void *) DestroyCommands },
  370:     { "exit",				"Exit console",
  371: 	ExitCommand, NULL, 0, NULL },
  372:     { "iface {iface}",			"Choose bundle by iface",
  373: 	IfaceCommand, NULL, 0, NULL },
  374:     { "help ...",			"Help on any command",
  375: 	HelpCommand, NULL, 0, NULL },
  376:     { "link {name}",			"Choose link",
  377: 	LinkCommand, NULL, 0, NULL },
  378:     { "load [{file}] {label}",		"Read from config file",
  379: 	LoadCommand, NULL, 0, NULL },
  380:     { "log [+/-{opt} ...]",		"Set/view log options",
  381: 	LogCommand, NULL, 2, NULL },
  382:     { "msession {msesid}",		"Ch. bundle by msession-id",
  383: 	MSessionCommand, NULL, 0, NULL },
  384:     { "open [{layer}]",			"Open a layer",
  385: 	OpenCommand, NULL, 1, NULL },
  386:     { "quit",				"Quit program",
  387: 	QuitCommand, NULL, 2, NULL },
  388:     { "repeater [{name}]",		"Choose/list repeaters",
  389: 	RepCommand, NULL, 0, NULL },
  390:     { "session {sesid}",		"Choose link by session-id",
  391: 	SessionCommand, NULL, 0, NULL },
  392:     { "set ...",			"Set parameters",
  393: 	CMD_SUBMENU, NULL, 0, (void *) SetCommands },
  394: 	{ "unset ...",			"Unset parameters",
  395: 	CMD_SUBMENU, NULL, 0, (void *) UnSetCommands },
  396:     { "show ...",			"Show status",
  397: 	CMD_SUBMENU, NULL, 0, (void *) ShowCommands },
  398:     { NULL },
  399:   };
  400: 
  401: 
  402: 
  403: /*
  404:  * Layers
  405:  */
  406: 
  407:   struct layer	gLayers[] = {
  408:     { "iface",
  409:       IfaceOpenCmd,
  410:       IfaceCloseCmd,
  411:       AdmitBund,
  412:       "System interface"
  413:     },
  414:     { "ipcp",
  415:       IpcpOpenCmd,
  416:       IpcpCloseCmd,
  417:       AdmitBund,
  418:       "IPCP: IP control protocol"
  419:     },
  420:     { "ipv6cp",
  421:       Ipv6cpOpenCmd,
  422:       Ipv6cpCloseCmd,
  423:       AdmitBund,
  424:       "IPV6CP: IPv6 control protocol"
  425:     },
  426:     { "ccp",
  427:       CcpOpenCmd,
  428:       CcpCloseCmd,
  429:       AdmitBund,
  430:       "CCP: compression ctrl prot."
  431:     },
  432:     { "ecp",
  433:       EcpOpenCmd,
  434:       EcpCloseCmd,
  435:       AdmitBund,
  436:       "ECP: encryption ctrl prot."
  437:     },
  438:     { "bund",
  439:       BundOpenCmd,
  440:       BundCloseCmd,
  441:       AdmitBund,
  442:       "Multilink bundle"
  443:     },
  444:     { "link",
  445:       LinkOpenCmd,
  446:       LinkCloseCmd,
  447:       AdmitLink,
  448:       "Link layer"
  449:     },
  450:     { "device",
  451:       PhysOpenCmd,
  452:       PhysCloseCmd,
  453:       AdmitLink,
  454:       "Physical link layer"
  455:     },
  456:   };
  457: 
  458:   #define NUM_LAYERS	(sizeof(gLayers) / sizeof(*gLayers))
  459: 
  460: /*
  461:  * DoCommand()
  462:  *
  463:  * Executes command. Returns TRUE if user wants to quit.
  464:  */
  465: 
  466: int
  467: DoCommand(Context ctx, int ac, char *av[], const char *file, int line)
  468: {
  469:     int		rtn, i;
  470:     char	filebuf[100], cmd[256];
  471: 
  472:     ctx->errmsg[0] = 0;
  473:     rtn = DoCommandTab(ctx, gCommands, ac, av);
  474: 
  475:     if (rtn) {
  476: 	if (file) {
  477: 	    snprintf(filebuf,sizeof(filebuf),"%s:%d: ", file, line);
  478: 	} else {
  479: 	    filebuf[0] = 0;
  480: 	}
  481: 	cmd[0] = 0;
  482: 	for (i = 0; i < ac; i++) {
  483: 	    if (i)
  484: 		strlcat(cmd, " ", sizeof(cmd));
  485: 	    strlcat(cmd, av[i], sizeof(cmd));
  486: 	}
  487:     }
  488: 
  489:     switch (rtn) {
  490: 	case 0:
  491: 	    break;
  492:     
  493: 	default:
  494: 	case CMD_ERR_USAGE:
  495: 	case CMD_ERR_UNFIN:
  496: 	    HelpCommand(ctx, ac, av, filebuf);
  497: 	    Log2(LG_ERR, ("%sError in '%s'", filebuf, cmd));
  498: 	    break;
  499: 	case CMD_ERR_UNDEF:
  500:     	    Printf("%sUnknown command: '%s'. Try \"help\".\r\n", filebuf, cmd);
  501: 	    Log2(LG_ERR, ("%sUnknown command: '%s'. Try \"help\".", filebuf, cmd));
  502: 	    break;
  503: 	case CMD_ERR_AMBIG:
  504:     	    Printf("%sAmbiguous command: '%s'. Try \"help\".\r\n", filebuf, cmd);
  505: 	    Log2(LG_ERR, ("%sAmbiguous command: '%s'. Try \"help\".", filebuf, cmd));
  506: 	    break;
  507: 	case CMD_ERR_RECUR:
  508:     	    Printf("%sRecursion detected for: '%s'!\r\n", filebuf, cmd);
  509: 	    Log2(LG_ERR, ("%sRecursion detected for: '%s'!", filebuf, cmd));
  510: 	    break;
  511: 	case CMD_ERR_NOCTX:
  512:     	    Printf("%sIncorrect context for: '%s'\r\n", filebuf, cmd);
  513: 	    Log2(LG_ERR, ("%sIncorrect context for: '%s'", filebuf, cmd));
  514: 	    break;
  515: 	case CMD_ERR_OTHER:
  516:     	    Printf("%sError in '%s': %s\r\n", filebuf, cmd, ctx->errmsg);
  517: 	    Log2(LG_ERR, ("%sError in '%s': %s", filebuf, cmd, ctx->errmsg));
  518: 	    break;
  519:     }
  520:   
  521:     return(rtn);
  522: }
  523: 
  524: /*
  525:  * DoCommandTab()
  526:  *
  527:  * Execute command from given command menu
  528:  */
  529: 
  530: int
  531: DoCommandTab(Context ctx, CmdTab cmdlist, int ac, char *av[])
  532: {
  533:     CmdTab	cmd;
  534:     int		rtn = 0;
  535: 
  536:     /* Huh? */
  537:     if (ac <= 0)
  538: 	return(CMD_ERR_UNFIN);
  539: 
  540:     /* Find command */
  541:     if ((rtn = FindCommand(ctx, cmdlist, av[0], &cmd)))
  542: 	return(rtn);
  543: 
  544:     /* Check command admissibility */
  545:     if (cmd->admit && !(cmd->admit)(ctx, cmd))
  546: 	return(CMD_ERR_NOCTX);
  547: 
  548:     /* Find command and either execute or recurse into a submenu */
  549:     if (cmd->func == CMD_SUBMENU) {
  550:         if ((intptr_t)cmd->arg == (intptr_t)ShowSessCmds) {
  551:             if (ac > 1)
  552: 	        rtn = DoCommandTab(ctx, (CmdTab) cmd->arg, ac - 1, av + 1);
  553:             else
  554:                 rtn = ShowSessions(ctx, 0, NULL, NULL);
  555:         } else
  556:             rtn = DoCommandTab(ctx, (CmdTab) cmd->arg, ac - 1, av + 1);
  557:     } else
  558: 	rtn = (cmd->func)(ctx, ac - 1, av + 1, cmd->arg);
  559: 
  560:     return(rtn);
  561: }
  562: 
  563: /*
  564:  * FindCommand()
  565:  */
  566: 
  567: int
  568: FindCommand(Context ctx, CmdTab cmds, char *str, CmdTab *cmdp)
  569: {
  570:     int		nmatch;
  571:     int		len = strlen(str);
  572: 
  573:     for (nmatch = 0; cmds->name; cmds++) {
  574: 	if (cmds->name && !strncmp(str, cmds->name, len) &&
  575: 	  cmds->priv <= ctx->priv) {
  576: 	    *cmdp = cmds;
  577:     	    nmatch++;
  578: 	}
  579:     }
  580:     switch (nmatch) {
  581: 	case 0:
  582:     	    return(CMD_ERR_UNDEF);
  583: 	case 1:
  584:     	    return(0);
  585: 	default:
  586:     	    return(CMD_ERR_AMBIG);
  587:     }
  588: }
  589: 
  590: /********** COMMANDS **********/
  591: 
  592: 
  593: /*
  594:  * GlobalSetCommand()
  595:  */
  596: 
  597: static int
  598: GlobalSetCommand(Context ctx, int ac, char *av[], void *arg) 
  599: {
  600:     int val;
  601: 
  602:   if (ac == 0)
  603:     return(-1);
  604: 
  605:   switch ((intptr_t)arg) {
  606:     case SET_ENABLE:
  607:       EnableCommand(ac, av, &gGlobalConf.options, gGlobalConfList);
  608:       break;
  609: 
  610:     case SET_DISABLE:
  611:       DisableCommand(ac, av, &gGlobalConf.options, gGlobalConfList);
  612:       break;
  613: 
  614: #ifdef USE_IPFW
  615:     case SET_RULE:
  616: 	if (rule_pool) 
  617: 	    Error("Rule pool is not empty. Impossible to set initial number");
  618: 	else {
  619: 	    val = atoi(*av);
  620: 	    if (val <= 0 || val>=65535)
  621: 		Error("Incorrect rule number");
  622: 	    else
  623: 		rule_pool_start = val;
  624: 	}
  625:       break;
  626: 
  627:     case SET_QUEUE:
  628: 	if (queue_pool) 
  629: 	    Error("Queue pool is not empty. Impossible to set initial number");
  630: 	else {
  631: 	    val = atoi(*av);
  632: 	    if (val <= 0 || val>=65535)
  633: 		Error("Incorrect queue number");
  634: 	    else
  635: 		queue_pool_start = val;
  636: 	}
  637:       break;
  638: 
  639:     case SET_PIPE:
  640: 	if (pipe_pool) 
  641: 	    Error("Pipe pool is not empty. Impossible to set initial number");
  642: 	else {
  643: 	    val = atoi(*av);
  644: 	    if (val <= 0 || val>=65535)
  645: 		Error("Incorrect pipe number");
  646: 	    else
  647: 		pipe_pool_start = val;
  648: 	}
  649:       break;
  650: 
  651:     case SET_TABLE:
  652: 	if (table_pool) 
  653: 	    Error("Table pool is not empty. Impossible to set initial number");
  654: 	else {
  655: 	    val = atoi(*av);
  656: 	    if (val <= 0 || val>127) /* table 0 is usually possible but we deny it */
  657: 		Error("Incorrect table number");
  658: 	    else
  659: 		table_pool_start = val;
  660: 	}
  661:       break;
  662: #endif /* USE_IPFW */
  663: 
  664: #ifdef PHYSTYPE_L2TP
  665:     case SET_L2TPTO:
  666: 	val = atoi(*av);
  667: 	if (val < 0 || val > 1000000)
  668: 	    Error("Incorrect L2TP timeout");
  669: 	else
  670: 	    gL2TPto = val;
  671:       break;
  672: 
  673:     case SET_L2TPLIMIT:
  674: 	val = atoi(*av);
  675: 	if (val < 0 || val > 65536)
  676: 	    Error("Incorrect L2TP call limit");
  677: 	else
  678: 	    gL2TPtunlimit = val;
  679:       break;
  680: #endif
  681: 
  682: #ifdef PHYSTYPE_PPTP
  683:     case SET_PPTPTO:
  684: 	val = atoi(*av);
  685: 	if (val < 0 || val > 1000000)
  686: 	    Error("Incorrect PPTP timeout");
  687: 	else
  688: 	    gPPTPto = val;
  689:       break;
  690: 
  691:     case SET_PPTPLIMIT:
  692: 	val = atoi(*av);
  693: 	if (val <= 0 || val > 65536)
  694: 	    Error("Incorrect PPTP call limit");
  695: 	else
  696: 	    gPPTPtunlimit = val;
  697:       break;
  698: #endif
  699: 
  700:     case SET_MAX_CHILDREN:
  701: 	val = atoi(*av);
  702: 	if (val < 0 || val > 65536)
  703: 	    Error("Incorrect children links limit");
  704: 	else
  705: 	    gMaxChildren = val;
  706:       break;
  707: 
  708: #ifdef USE_NG_BPF
  709:     case SET_FILTER:
  710: 	if (ac == 4 && strcasecmp(av[1], "add") == 0) {
  711: 	    struct acl	**acls, *acls1;
  712: 	    int		i;
  713: 	    
  714: 	    i = atol(av[0]);
  715: 	    if (i <= 0 || i > ACL_FILTERS)
  716: 		Error("Wrong filter number\r\n");
  717: 	    acls = &(acl_filters[i - 1]);
  718: 	    
  719: 	    i = atol(av[2]);
  720: 	    if (i <= 0)
  721: 	        Error("Wrong acl number: %i\r\n", i);
  722: 
  723: 	    acls1 = Malloc(MB_AUTH, sizeof(struct acl) + strlen(av[3]));
  724: 	    acls1->number = i;
  725: 	    acls1->real_number = 0;
  726: 	    strcpy(acls1->rule, av[3]);
  727: 	    while ((*acls != NULL) && ((*acls)->number < acls1->number))
  728: 	      acls = &((*acls)->next);
  729: 
  730: 	    if (*acls == NULL) {
  731: 	        acls1->next = NULL;
  732: 	    } else if ((*acls)->number == acls1->number) {
  733: 		Freee(acls1);
  734: 	        Error("Duplicate acl\r\n");
  735: 	    } else {
  736: 	        acls1->next = *acls;
  737: 	    }
  738: 	    *acls = acls1;
  739: 
  740: 	} else if (ac == 2 && strcasecmp(av[1], "clear") == 0) {
  741: 	    struct acl          *acls, *acls1;
  742: 	    int i;
  743: 	    
  744: 	    i = atoi(av[0]);
  745: 	    if (i <= 0 || i > ACL_FILTERS)
  746: 		Error("Wrong filter number\r\n");
  747: 	    	    
  748: 	    acls = acl_filters[i - 1];
  749: 	    while (acls != NULL) {
  750: 	        acls1 = acls->next;
  751: 	        Freee(acls);
  752: 	        acls = acls1;
  753: 	    };
  754: 	    acl_filters[i - 1] = NULL;
  755: 	} else
  756: 	    return(-1);
  757: 	break;
  758: #endif /* USE_NG_BPF */
  759: 	
  760:     case SET_QTHRESHOLD:
  761:         if (ac == 2) {
  762:             int val_max;
  763: 
  764:             val = atoi(av[0]);
  765:             if (val < 0 || val >= MSG_QUEUE_LEN-1)
  766:                 Error("Incorrect minimum threshold for message queue, "
  767:                       "must be between 0 and %d", MSG_QUEUE_LEN-1);
  768:             val_max = atoi(av[1]);
  769:             if (val_max <= val || val_max >= MSG_QUEUE_LEN)
  770:                 Error("Incorrect maximum threshold for message queue, "
  771:                       "must be greater than minimum and less than %d",
  772:                       MSG_QUEUE_LEN);
  773:             gQThresMin = val;
  774:             gQThresMax = val_max;
  775:             gQThresDiff = val_max - val;
  776:         }
  777:         else
  778:             return (-1);
  779:         break;
  780:     default:
  781:       return(-1);
  782:   }
  783: 
  784:   return 0;
  785: }
  786: 
  787: /*
  788:  * HelpCommand()
  789:  */
  790: 
  791: int
  792: HelpCommand(Context ctx, int ac, char *av[], void *arg)
  793: {
  794:   int		depth, i;
  795:   CmdTab	menu, cmd;
  796:   char		*mark, *mark_save;
  797:   const char	*errfmt;
  798:   char		buf[256];
  799:   int		err;
  800: 
  801:   for (mark = buf, depth = *buf = 0, menu = gCommands;
  802:       depth < ac;
  803:       depth++, menu = (CmdTab) cmd->arg) {
  804:     if ((err = FindCommand(ctx, menu, av[depth], &cmd))) {
  805:       int k;
  806: 
  807:       for (*buf = k = 0; k <= depth; k++)
  808: 	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s%c",
  809: 	  av[k], k == depth ? '\0' : ' ');
  810:       if (err == CMD_ERR_AMBIG)
  811: 	  errfmt = "%sAmbiguous command: '%s'.\r\n";
  812:       else 
  813:           errfmt = "%sUnknown command: '%s'.\r\n";
  814:       if (arg) {
  815:         Printf(errfmt, (char*)arg, buf);
  816:       } else {
  817:         Printf(errfmt, "", buf);
  818:       }
  819:       return(0);
  820:     }
  821:     sprintf(mark, depth ? " %s" : "%s", cmd->name);
  822:     mark_save = mark;
  823:     if ((mark = strchr(mark + 1, ' ')) == NULL)
  824:       mark = mark_save + strlen(mark_save);
  825:     if (cmd->func != CMD_SUBMENU)
  826:     {
  827:       Printf("Usage: %s\r\n", buf);
  828:       return(0);
  829:     }
  830:   }
  831: 
  832:     /* Show list of available commands in this submenu */
  833:     *mark = 0;
  834:     if (!*buf)
  835: 	Printf("Available commands:\r\n");
  836:     else
  837: 	Printf("Commands available under \"%s\":\r\n", buf);
  838:     i = 0;
  839:     for (cmd = menu; cmd->name; cmd++) {
  840: 	if (cmd->priv > ctx->priv)
  841: 	    continue;
  842: 	strlcpy(buf, cmd->name, sizeof(buf));
  843: 	if ((mark = strchr(buf, ' ')))
  844:     	    *mark = 0;
  845: 	Printf(" %-9s: %-20s%s", buf, cmd->desc,
  846:     	    (i & 1)? "\r\n" : "\t");
  847: 	i++;
  848:     }
  849:     if (i & 1)
  850: 	Printf("\r\n");
  851:     return(0);
  852: }
  853: 
  854: /*
  855:  * SetDebugCommand()
  856:  */
  857: 
  858: static int
  859: SetDebugCommand(Context ctx, int ac, char *av[], void *arg)
  860: {
  861:   switch (ac) {
  862:     case 1:
  863:       NgSetDebug(atoi(av[0]));
  864:       break;
  865:     default:
  866:       return(-1);
  867:   }
  868:   return(0);
  869: }
  870: 
  871: /*
  872:  * ShowVersion()
  873:  */
  874: 
  875: static int
  876: ShowVersion(Context ctx, int ac, char *av[], void *arg)
  877: {
  878:   Printf("MPD version: %s\r\n", gVersion);
  879:   Printf("  Available features:\r\n");
  880: #ifdef	USE_IPFW
  881:   Printf("	ipfw rules	: yes\r\n");
  882: #else
  883:   Printf("	ipfw rules	: no\r\n");
  884: #endif
  885: #ifdef	USE_FETCH
  886:   Printf("	config fetch	: yes\r\n");
  887: #else
  888:   Printf("	config fetch	: no\r\n");
  889: #endif
  890: #ifdef	USE_NG_BPF
  891:   Printf("	ng_bpf		: yes\r\n");
  892: #else
  893:   Printf("	ng_bpf		: no\r\n");
  894: #endif
  895: #ifdef	USE_NG_CAR
  896:   Printf("	ng_car		: yes\r\n");
  897: #else
  898:   Printf("	ng_car		: no\r\n");
  899: #endif
  900: #ifdef	USE_NG_DEFLATE
  901:   Printf("	ng_deflate	: yes\r\n");
  902: #else
  903:   Printf("	ng_deflate	: no\r\n");
  904: #endif
  905: #ifdef	USE_NG_IPACCT
  906:   Printf("	ng_ipacct	: yes\r\n");
  907: #else
  908:   Printf("	ng_ipacct	: no\r\n");
  909: #endif
  910: #ifdef  CCP_MPPC
  911:   Printf("	ng_mppc (MPPC)	: %s\r\n", MPPCPresent?"yes":"no");
  912:   Printf("	ng_mppc (MPPE)	: %s\r\n", MPPEPresent?"yes":"no");
  913: #else
  914:   Printf("	ng_mppc (MPPC)	: no\r\n");
  915:   Printf("	ng_mppc (MPPE)	: no\r\n");
  916: #endif
  917: #ifdef	USE_NG_NAT
  918:   Printf("	ng_nat		: yes\r\n");
  919: #ifdef NG_NAT_DESC_LENGTH
  920:   Printf("	nat redirect	: yes\r\n");
  921: #else
  922:   Printf("	nat redirect	: no\r\n");
  923: #endif
  924: #else
  925:   Printf("	ng_nat		: no\r\n");
  926: #endif
  927: #ifdef	USE_NG_NETFLOW
  928:   Printf("	ng_netflow	: yes\r\n");
  929: #if NGM_NETFLOW_COOKIE >= 1309868867
  930:   Printf("	netflow v9	: yes\r\n");
  931: #else
  932:   Printf("	netflow v9	: no\r\n");
  933: #endif
  934: #else
  935:   Printf("	ng_netflow	: no\r\n");
  936: #endif
  937: #ifdef	USE_NG_PRED1
  938:   Printf("	ng_pred1	: yes\r\n");
  939: #else
  940:   Printf("	ng_pred1	: emulated\r\n");
  941: #endif
  942: #ifdef	USE_NG_TCPMSS
  943:   Printf("	ng_tcpmss	: yes\r\n");
  944: #else
  945:   Printf("	ng_tcpmss	: emulated\r\n");
  946: #endif
  947:   return(0);
  948: }
  949: 
  950: /*
  951:  * ShowEvents()
  952:  */
  953: 
  954: static int
  955: ShowEvents(Context ctx, int ac, char *av[], void *arg)
  956: {
  957:   EventDump(ctx, "mpd events");
  958:   return(0);
  959: }
  960: 
  961: /*
  962:  * ShowGlobal()
  963:  */
  964: 
  965: static int
  966: ShowGlobal(Context ctx, int ac, char *av[], void *arg)
  967: {
  968: #ifdef USE_NG_BPF
  969:     int	k;
  970: #endif
  971: 
  972:     Printf("Global settings:\r\n");
  973: #ifdef USE_IPFW
  974:     Printf("	startrule	: %d\r\n", rule_pool_start);
  975:     Printf("	startpipe	: %d\r\n", pipe_pool_start);
  976:     Printf("	startqueue	: %d\r\n", queue_pool_start);
  977:     Printf("	starttable	: %d\r\n", table_pool_start);
  978: #endif
  979: #ifdef PHYSTYPE_L2TP
  980:     Printf("	l2tptimeout	: %d\r\n", gL2TPto);
  981:     Printf("	l2tplimit	: %d\r\n", gL2TPtunlimit);
  982: #endif
  983: #ifdef PHYSTYPE_PPTP
  984:     Printf("	pptptimeout	: %d\r\n", gPPTPto);
  985:     Printf("	pptplimit	: %d\r\n", gPPTPtunlimit);
  986: #endif
  987:     Printf("	max-children	: %d\r\n", gMaxChildren);
  988:     Printf("	qthreshold	: %d %d\r\n", gQThresMin, gQThresMax);
  989:     Printf("Global options:\r\n");
  990:     OptStat(ctx, &gGlobalConf.options, gGlobalConfList);
  991: #ifdef USE_NG_BPF
  992:     Printf("Global traffic filters:\r\n");
  993:     for (k = 0; k < ACL_FILTERS; k++) {
  994:         struct acl *a = acl_filters[k];
  995:         while (a) {
  996:     	    Printf("\t%d#%d\t: '%s'\r\n", (k + 1), a->number, a->rule);
  997:     	    a = a->next;
  998: 	}
  999:     }
 1000: #endif
 1001:     Printf("Global state:\r\n");
 1002:     Printf("	children	: %d\r\n", gChildren);
 1003:   return 0;
 1004: }
 1005: 
 1006: 
 1007: /*
 1008:  * ExitCommand()
 1009:  */
 1010: 
 1011: static int
 1012: ExitCommand(Context ctx, int ac, char *av[], void *arg)
 1013: {
 1014:     if (ctx->cs)
 1015: 	ctx->cs->exit = TRUE;
 1016:     return(0);
 1017: }
 1018: 
 1019: /*
 1020:  * QuitCommand()
 1021:  */
 1022: 
 1023: static int
 1024: QuitCommand(Context ctx, int ac, char *av[], void *arg)
 1025: {
 1026:     if (ctx->cs)
 1027: 	ctx->cs->exit = TRUE;
 1028:     SendSignal(SIGTERM);
 1029:     return(0);
 1030: }
 1031: 
 1032: /*
 1033:  * LoadCommand()
 1034:  */
 1035: 
 1036: static int
 1037: LoadCommand(Context ctx, int ac, char *av[], void *arg)
 1038: {
 1039:     char filename[128];
 1040: #ifdef USE_FETCH
 1041:     char buf[1024];
 1042:     FILE *f = NULL;
 1043:     FILE *rf = NULL;
 1044:     int fetch = 0;
 1045: #endif
 1046: 
 1047:     if (ac < 1 || ac > 2)
 1048: 	return(-1);
 1049:     else {
 1050: 	if (ctx->depth > 20)
 1051:     	    return(CMD_ERR_RECUR);
 1052: 	ctx->depth++;
 1053: 
 1054: 	if (ac == 1)
 1055: 	    strlcpy(filename, gConfigFile, sizeof(filename));
 1056: 	else {
 1057: #ifdef USE_FETCH
 1058: 	    if (strncmp(av[0], "http://", 7) == 0 ||
 1059: 		strncmp(av[0], "https://", 8) == 0 ||
 1060: 		strncmp(av[0], "ftp://", 6) == 0) {
 1061: 		    fetch = 1;
 1062: 		strcpy(filename, "/tmp/mpd.conf.XXXXXX");
 1063: 		mkstemp(filename);
 1064: 		f = fopen(filename, "w");
 1065: 		if (f == NULL) {
 1066: 		    Printf("Can't create temporal file\r\n");
 1067: 		    goto out;
 1068: 		}
 1069: 		rf = fetchGetURL(av[0], "");
 1070: 		if (rf == NULL) {
 1071: 		    Printf("Can't fetch '%s'\r\n", av[0]);
 1072: 		    fclose(f);
 1073: 		    goto out;
 1074: 		}
 1075: 		Printf("Fetching '%s' ...", av[0]);
 1076: 		while (!feof(rf)) {
 1077: 		    int b = fread(buf, 1, sizeof(buf), rf);
 1078: 		    fwrite(buf, b, 1, f);
 1079: 		}
 1080: 		Printf(" done\r\n");
 1081: 		fclose(f);
 1082: 	    } else
 1083: #endif
 1084: 		strlcpy(filename, av[0], sizeof(filename));
 1085: 	}
 1086: 	if (ReadFile(filename, av[ac - 1], DoCommand, ctx) < 0)
 1087: 	    Printf("can't read configuration for \"%s\" from \"%s\"\r\n",
 1088: 		av[ac -1], filename);
 1089: #ifdef USE_FETCH
 1090: out:	if (fetch)
 1091: 	    unlink(filename);
 1092: #endif
 1093: 	ctx->depth--;
 1094:     }
 1095:     return(0);
 1096: }
 1097: 
 1098: /*
 1099:  * OpenCommand()
 1100:  */
 1101: 
 1102: static int
 1103: OpenCommand(Context ctx, int ac, char *av[], void *arg)
 1104: {
 1105:     Layer	layer;
 1106:     const char	*name;
 1107: 
 1108:     switch (ac) {
 1109:     case 0:
 1110:         name = DEFAULT_OPEN_LAYER;
 1111:         break;
 1112:     case 1:
 1113:         name = av[0];
 1114:         break;
 1115:     default:
 1116:         return(-1);
 1117:     }
 1118:     if ((layer = GetLayer(name)) != NULL) {
 1119: 	/* Check command admissibility */
 1120: 	if (!layer->admit || (layer->admit)(ctx, NULL))
 1121: 	    return (*layer->opener)(ctx);
 1122: 	else
 1123: 	    return (CMD_ERR_NOCTX);
 1124:     }
 1125:     return(-1);
 1126: }
 1127: 
 1128: /*
 1129:  * CloseCommand()
 1130:  */
 1131: 
 1132: static int
 1133: CloseCommand(Context ctx, int ac, char *av[], void *arg)
 1134: {
 1135:     Layer	layer;
 1136:     const char	*name;
 1137: 
 1138:     switch (ac) {
 1139:     case 0:
 1140:       name = DEFAULT_OPEN_LAYER;
 1141:       break;
 1142:     case 1:
 1143:       name = av[0];
 1144:       break;
 1145:     default:
 1146:       return(-1);
 1147:     }
 1148:     if ((layer = GetLayer(name)) != NULL) {
 1149: 	/* Check command admissibility */
 1150: 	if (!layer->admit || (layer->admit)(ctx, NULL))
 1151: 	    return (*layer->closer)(ctx);
 1152: 	else
 1153: 	    return (CMD_ERR_NOCTX);
 1154:     }
 1155:     return(-1);
 1156: }
 1157: 
 1158: /*
 1159:  * GetLayer()
 1160:  */
 1161: 
 1162: static Layer
 1163: GetLayer(const char *name)
 1164: {
 1165:   int	k, found;
 1166: 
 1167:   if (name == NULL)
 1168:     name = "iface";
 1169:   for (found = -1, k = 0; k < NUM_LAYERS; k++) {
 1170:     if (!strncasecmp(name, gLayers[k].name, strlen(name))) {
 1171:       if (found > 0) {
 1172: 	Log(LG_ERR, ("%s: ambiguous", name));
 1173: 	return(NULL);
 1174:       } else
 1175: 	found = k;
 1176:     }
 1177:   }
 1178:   if (found < 0) {
 1179:     Log(LG_ERR, ("unknown layer \"%s\": try \"show layers\"", name));
 1180:     return(NULL);
 1181:   }
 1182:   return(&gLayers[found]);
 1183: }
 1184: 
 1185: /*
 1186:  * ShowLayers()
 1187:  */
 1188: 
 1189: static int
 1190: ShowLayers(Context ctx, int ac, char *av[], void *arg)
 1191: {
 1192:   int	k;
 1193: 
 1194:   Printf("\tName\t\tDescription\r\n");
 1195:   Printf("\t----\t\t-----------\r\n");
 1196:   for (k = 0; k < NUM_LAYERS; k++)
 1197:     Printf("\t%s\t\t%s\r\n", gLayers[k].name, gLayers[k].desc);
 1198:   return(0);
 1199: }
 1200: 
 1201: /*
 1202:  * ShowTypes()
 1203:  */
 1204: 
 1205: static int
 1206: ShowTypes(Context ctx, int ac, char *av[], void *arg)
 1207: {
 1208:   PhysType	pt;
 1209:   int		k;
 1210: 
 1211:   Printf("\tName\t\tDescription\r\n");
 1212:   Printf("\t----\t\t-----------\r\n");
 1213:   for (k = 0; (pt = gPhysTypes[k]); k++)
 1214:     Printf("\t%s\t\t%s\r\n", pt->name, pt->descr);
 1215:   return(0);
 1216: }
 1217: 
 1218: /*
 1219:  * ShowSummary()
 1220:  */
 1221: 
 1222: static int
 1223: ShowSummary(Context ctx, int ac, char *av[], void *arg)
 1224: {
 1225:   int		b, l, f;
 1226:   Bund		B;
 1227:   Link  	L;
 1228:   Rep		R;
 1229:   char	buf[64];
 1230: 
 1231:   Printf("Current daemon status summary\r\n");
 1232:   Printf("Iface\tBund\t\tLink\tLCP\tDevice\t\tUser\t\tFrom\r\n");
 1233:   for (b = 0; b<gNumLinks; b++) {
 1234:     if ((L=gLinks[b]) != NULL && L->bund == NULL && L->rep == NULL) {
 1235: 	Printf("\t\t\t");
 1236: 	Printf("%s\t%s\t", 
 1237: 	    L->name,
 1238: 	    FsmStateName(L->lcp.fsm.state));
 1239: 	PhysGetPeerAddr(L, buf, sizeof(buf));
 1240: 	Printf("%s\t%s\t%8s\t%s", 
 1241: 	    (L->type?L->type->name:""),
 1242: 	    gPhysStateNames[L->state],
 1243: 	    L->lcp.auth.params.authname,
 1244: 	    buf
 1245: 	);
 1246: 	Printf("\r\n");
 1247:     }
 1248:   }
 1249:   for (b = 0; b<gNumBundles; b++) {
 1250:     if ((B=gBundles[b]) != NULL) {
 1251: 	Printf("%s\t%s\t%s\t", B->iface.ifname, B->name, (B->iface.up?"Up":"Down"));
 1252: 	f = 1;
 1253: 	if (B->n_links == 0)
 1254: 	    Printf("\r\n");
 1255: 	else for (l = 0; l < NG_PPP_MAX_LINKS; l++) {
 1256: 	    if ((L=B->links[l]) != NULL) {
 1257: 		if (f == 1)
 1258: 		    f = 0;
 1259: 		else
 1260: 		    Printf("\t\t\t");
 1261: 		PhysGetPeerAddr(L, buf, sizeof(buf));
 1262: 		Printf("%s\t%s\t%s\t%s\t%8s\t%s", 
 1263: 		    L->name,
 1264: 		    FsmStateName(L->lcp.fsm.state),
 1265: 		    (L->type?L->type->name:""),
 1266: 		    gPhysStateNames[L->state],
 1267: 		    L->lcp.auth.params.authname,
 1268: 		    buf
 1269: 		    );
 1270: 		Printf("\r\n");
 1271: 	    }
 1272: 	}
 1273:     }
 1274:   }
 1275:   for (b = 0; b < gNumReps; b++) {
 1276:     if ((R = gReps[b]) != NULL) {
 1277: 	Printf("Repeater\t%s\t", R->name);
 1278: 	f = 1;
 1279: 	for (l = 0; l < 2; l++) {
 1280: 	    if ((L = R->links[l])!= NULL) {
 1281: 		if (f)
 1282: 		    f = 0;
 1283: 		else
 1284: 		    Printf("\t\t\t");
 1285: 		PhysGetPeerAddr(L, buf, sizeof(buf));
 1286: 		Printf("%s\t%s\t%s\t%s\t%8s\t%s", 
 1287: 		    L->name,
 1288: 		    "",
 1289: 		    (L->type?L->type->name:""),
 1290: 		    gPhysStateNames[L->state],
 1291: 		    "",
 1292: 		    buf
 1293: 		    );
 1294: 		Printf("\r\n");
 1295: 	    }
 1296: 	}
 1297: 	if (f)
 1298: 	    Printf("\r\n");
 1299:     }
 1300:   }
 1301:   return(0);
 1302: }
 1303: 
 1304: /*
 1305:  * ShowSessions()
 1306:  */
 1307: 
 1308: static int
 1309: ShowSessions(Context ctx, int ac, char *av[], void *arg)
 1310: {
 1311:     int		l;
 1312:     Bund	B;
 1313:     Link  	L;
 1314:     char	peer[64], addr[64];
 1315: 
 1316:     if (ac != 0 && ac != 1)
 1317: 	return (-1);
 1318: 
 1319:     for (l = 0; l < gNumLinks; l++) {
 1320: 	if ((L=gLinks[l]) != NULL && L->session_id[0] && L->bund) {
 1321: 	    B = L->bund;
 1322: 	    u_addrtoa(&B->iface.peer_addr, addr, sizeof(addr));
 1323: 	    PhysGetPeerAddr(L, peer, sizeof(peer));
 1324: 	    if (ac == 0)
 1325: 	        goto out;
 1326: 	    switch ((intptr_t)arg) {
 1327: 		case SHOW_IFACE:
 1328: 		    if (strcmp(av[0], B->iface.ifname))
 1329: 			continue;
 1330: 		    break;
 1331: 		case SHOW_IP:
 1332: 		    if (strcmp(av[0], addr))
 1333: 			continue;
 1334: 		    break;
 1335: 		case SHOW_USER:
 1336: 		    if (strcmp(av[0], L->lcp.auth.params.authname))
 1337: 			continue;
 1338: 		    break;
 1339: 		case SHOW_MSESSION:
 1340: 		    if (strcmp(av[0], B->msession_id))
 1341: 			continue;
 1342: 		    break;
 1343: 		case SHOW_SESSION:
 1344: 		    if (strcmp(av[0], L->session_id))
 1345: 			continue;
 1346: 		    break;
 1347: 		case SHOW_BUNDLE:
 1348: 		    if (strcmp(av[0], B->name))
 1349: 			continue;
 1350: 		    break;
 1351: 		case SHOW_LINK:
 1352: 		    if (av[0][0] == '[') {
 1353: 			int k;
 1354: 			if (sscanf(av[0], "[%x]", &k) != 1)
 1355: 			    return (-1);
 1356: 			else {
 1357: 			    if (L->id != k)
 1358: 				continue;
 1359: 			}
 1360: 		    } else {
 1361: 			if (strcmp(av[1], L->name))
 1362: 			    continue;
 1363: 		    }
 1364: 		    break;
 1365: 		case SHOW_PEER:
 1366: 		    if (strcmp(av[0], peer))
 1367: 			continue;
 1368: 			break;
 1369: 		default:
 1370: 		    return (-1);
 1371: 	    }
 1372: out:
 1373: 	    Printf("%s\t%s\t%s\t%s\t", B->iface.ifname,
 1374: 		addr, B->name, B->msession_id);
 1375: 	    Printf("%s\t%d\t%s\t%s\t%s", 
 1376: 		L->name,
 1377: 		L->id,
 1378: 		L->session_id,
 1379: 		L->lcp.auth.params.authname,
 1380: 		peer
 1381: 	    );
 1382: 	    Printf("\r\n");
 1383: 	}
 1384:     }
 1385:     return(0);
 1386: }
 1387: 
 1388: /*
 1389:  * ShowCustomer()
 1390:  */
 1391: 
 1392: static int
 1393: ShowCustomer(Context ctx, int ac, char *av[], void *arg)
 1394: {
 1395:     Link	l = ctx->lnk;
 1396:     Bund	b = ctx->bund;
 1397:     IfaceState	iface;
 1398:     IfaceRoute	r;
 1399:     int		j;
 1400:     char	buf[64];
 1401: #if defined(USE_NG_BPF) || defined(USE_IPFW)
 1402:     struct acl	*a;
 1403: #endif
 1404: 
 1405:     if (b && b->iface.ifname[0]) {
 1406: 	iface = &b->iface;
 1407: 	Printf("Interface:\r\n");
 1408: 	Printf("\tName            : %s\r\n", iface->ifname);
 1409: 	Printf("\tStatus          : %s\r\n", iface->up ? (iface->dod?"DoD":"UP") : "DOWN");
 1410: 	if (iface->up) {
 1411: 	    Printf("\tSession time    : %ld seconds\r\n", (long int)(time(NULL) - iface->last_up));
 1412: #ifdef USE_NG_BPF
 1413: 	    if (b->params.idle_timeout || iface->idle_timeout)
 1414: 		Printf("\tIdle timeout    : %d seconds\r\n", b->params.idle_timeout?b->params.idle_timeout:iface->idle_timeout);
 1415: #endif
 1416: 	    if (b->params.session_timeout || iface->session_timeout)
 1417: 		Printf("\tSession timeout : %d seconds\r\n", b->params.session_timeout?b->params.session_timeout:iface->session_timeout);
 1418: 	    Printf("\tMTU             : %d bytes\r\n", iface->mtu);
 1419: 	}
 1420: 	if (iface->ip_up && !u_rangeempty(&iface->self_addr)) {
 1421: 	    Printf("\tIP Addresses    : %s -> ", u_rangetoa(&iface->self_addr,buf,sizeof(buf)));
 1422: 	    Printf("%s\r\n", u_addrtoa(&iface->peer_addr,buf,sizeof(buf)));
 1423: 	}
 1424: 	if (iface->ipv6_up && !u_addrempty(&iface->self_ipv6_addr)) {
 1425: 	    Printf("\tIPv6 Addresses  : %s%%%s -> ", 
 1426: 		u_addrtoa(&iface->self_ipv6_addr,buf,sizeof(buf)), iface->ifname);
 1427: 	    Printf("%s%%%s\r\n", u_addrtoa(&iface->peer_ipv6_addr,buf,sizeof(buf)), iface->ifname);
 1428: 	}
 1429: 	if (iface->up) {
 1430: 	    if (!SLIST_EMPTY(&iface->routes) || !SLIST_EMPTY(&b->params.routes)) {
 1431:     		Printf("\tRoutes via peer :\r\n");
 1432: 		SLIST_FOREACH(r, &iface->routes, next)
 1433: 		    Printf("\t\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)));
 1434: 		SLIST_FOREACH(r, &b->params.routes, next)
 1435: 		    Printf("\t\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)));
 1436: 	    }
 1437: #ifdef USE_IPFW
 1438: 	    if (b->params.acl_pipe) {
 1439: 		Printf("\tIPFW pipes      :\r\n");
 1440: 		a = b->params.acl_pipe;
 1441: 		while (a) {
 1442: 		    Printf("\t\t%d (%d)\t'%s'\r\n", a->number, a->real_number, a->rule);
 1443: 		    a = a->next;
 1444: 		}
 1445: 	    }
 1446: 	    if (b->params.acl_queue) {
 1447: 		Printf("\tIPFW queues     :\r\n");
 1448: 		a = b->params.acl_queue;
 1449: 		while (a) {
 1450: 		    Printf("\t\t%d (%d)\t'%s'\r\n", a->number, a->real_number, a->rule);
 1451: 	    	    a = a->next;
 1452: 		}
 1453: 	    }
 1454: 	    if (b->params.acl_table) {
 1455: 		Printf("\tIPFW tables     :\r\n");
 1456: 		a = b->params.acl_table;
 1457: 		while (a) {
 1458: 		    if (a->number != 0)
 1459: 			Printf("\t\t%d (%d)\t'%s'\r\n", a->number, a->real_number, a->rule);
 1460: 		    else
 1461: 			Printf("\t\t(%d)\t'%s'\r\n", a->real_number, a->rule);
 1462: 		    a = a->next;
 1463: 		}
 1464: 	    }
 1465: 	    if (b->params.acl_rule) {
 1466: 		Printf("\tIPFW rules      :\r\n");
 1467: 		a = b->params.acl_rule;
 1468: 		while (a) {
 1469: 	    	    Printf("\t\t%d (%d)\t'%s'\r\n", a->number, a->real_number, a->rule);
 1470: 	    	    a = a->next;
 1471: 		}
 1472: 	    }
 1473: #endif /* USE_IPFW */
 1474: #ifdef USE_NG_BPF
 1475: 	    if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
 1476: 		int k;
 1477: 		Printf("\tTraffic filters :\r\n");
 1478: 		for (k = 0; k < ACL_FILTERS; k++) {
 1479: 		    a = b->params.acl_filters[k];
 1480: 		    if (a == NULL)
 1481: 			a = acl_filters[k];
 1482: 		    while (a) {
 1483: 			Printf("\t\t%d#%d\t'%s'\r\n", (k + 1), a->number, a->rule);
 1484: 			a = a->next;
 1485: 		    }
 1486: 		}
 1487: 		Printf("\tTraffic limits  :\r\n");
 1488: 		for (k = 0; k < 2; k++) {
 1489: 		    a = b->params.acl_limits[k];
 1490: 		    while (a) {
 1491: 			Printf("\t\t%s#%d%s%s\t'%s'\r\n", (k?"out":"in"), a->number,
 1492: 			    ((a->name[0])?"#":""), a->name, a->rule);
 1493: 			a = a->next;
 1494: 		    }
 1495: 		}
 1496: 	    }
 1497: #endif /* USE_NG_BPF */
 1498: 	}
 1499:     }
 1500:     if (b) {
 1501: 	Printf("Bundle %s%s:\r\n", b->name, b->tmpl?" (template)":(b->stay?" (static)":""));
 1502: 	Printf("\tStatus          : %s\r\n", b->open ? "OPEN" : "CLOSED");
 1503: 	Printf("\tMulti Session Id: %s\r\n", b->msession_id);
 1504: 	Printf("\tPeer authname   : \"%s\"\r\n", b->params.authname);
 1505: 	if (b->n_up)
 1506:     	    Printf("\tSession time    : %ld seconds\r\n", (long int)(time(NULL) - l->last_up));
 1507: 
 1508: 	if (b->peer_mrru) {
 1509: 	    Printf("\tMultilink PPP:\r\n");
 1510:     	    Printf("\t\tPeer auth name : \"%s\"\r\n", b->params.authname);
 1511:     	    Printf("\t\tPeer discrimin.: %s\r\n", MpDiscrimText(&b->peer_discrim, buf, sizeof(buf)));
 1512: 	}
 1513: 
 1514: 	if (!b->tmpl) {
 1515: 	    /* Show stats */
 1516: 	    BundUpdateStats(b);
 1517: 	    Printf("\tTraffic stats:\r\n");
 1518: 
 1519: 	    Printf("\t\tInput octets   : %llu\r\n", (unsigned long long)b->stats.recvOctets);
 1520: 	    Printf("\t\tInput frames   : %llu\r\n", (unsigned long long)b->stats.recvFrames);
 1521: 	    Printf("\t\tOutput octets  : %llu\r\n", (unsigned long long)b->stats.xmitOctets);
 1522: 	    Printf("\t\tOutput frames  : %llu\r\n", (unsigned long long)b->stats.xmitFrames);
 1523: 	    Printf("\t\tBad protocols  : %llu\r\n", (unsigned long long)b->stats.badProtos);
 1524: 	    Printf("\t\tRunts          : %llu\r\n", (unsigned long long)b->stats.runts);
 1525: 	}
 1526:     }
 1527:     for (j = 0; j < NG_PPP_MAX_LINKS; j++) {
 1528: 	if (b)
 1529: 	    l = b->links[j];
 1530: 	else if (j != 0)
 1531: 	    l = NULL;
 1532: 	if (l) {
 1533: 	    char	buf[64];
 1534: 	    Printf("Link %s:\r\n", l->name);
 1535: 	    Printf("\tDevice type     : %s\r\n", l->type?l->type->name:"");
 1536: 	    Printf("\tStatus          : %s/%s\r\n",
 1537: 		FsmStateName(l->lcp.fsm.state),
 1538: 		gPhysStateNames[l->state]);
 1539: 	    Printf("\tSession Id      : %s\r\n", l->session_id);
 1540: 	    Printf("\tPeer ident      : %s\r\n", l->lcp.peer_ident);
 1541: 	    if (l->state == PHYS_STATE_UP)
 1542:     		Printf("\tSession time    : %ld seconds\r\n", (long int)(time(NULL) - l->last_up));
 1543: 
 1544: 	    PhysGetSelfAddr(l, buf, sizeof(buf));
 1545: 	    Printf("\tSelf addr (name): %s", buf);
 1546: 	    PhysGetSelfName(l, buf, sizeof(buf));
 1547: 	    Printf(" (%s)\r\n", buf);
 1548: 	    PhysGetPeerAddr(l, buf, sizeof(buf));
 1549: 	    Printf("\tPeer addr (name): %s", buf);
 1550: 	    PhysGetPeerName(l, buf, sizeof(buf));
 1551: 	    Printf(" (%s)\r\n", buf);
 1552: 	    PhysGetPeerMacAddr(l, buf, sizeof(buf));
 1553: 	    Printf("\tPeer MAC address: %s\r\n", buf);
 1554: 	    PhysGetPeerIface(l, buf, sizeof(buf));
 1555: 	    Printf("\tPeer iface      : %s\r\n", buf);
 1556: 	    PhysGetCallingNum(l, buf, sizeof(buf));
 1557: 	    Printf("\tCalling         : %s\r\n", buf);
 1558: 	    PhysGetCalledNum(l, buf, sizeof(buf));
 1559: 	    Printf("\tCalled          : %s\r\n", buf);
 1560: 
 1561: 	    if (l->bund) {
 1562: 		LinkUpdateStats(l);
 1563: 		Printf("\tTraffic stats:\r\n");
 1564: 		Printf("\t\tInput octets   : %llu\r\n", (unsigned long long)l->stats.recvOctets);
 1565: 		Printf("\t\tInput frames   : %llu\r\n", (unsigned long long)l->stats.recvFrames);
 1566: 		Printf("\t\tOutput octets  : %llu\r\n", (unsigned long long)l->stats.xmitOctets);
 1567: 	        Printf("\t\tOutput frames  : %llu\r\n", (unsigned long long)l->stats.xmitFrames);
 1568: 	        Printf("\t\tBad protocols  : %llu\r\n", (unsigned long long)l->stats.badProtos);
 1569: 	        Printf("\t\tRunts          : %llu\r\n", (unsigned long long)l->stats.runts);
 1570: 	    }
 1571: 	}
 1572:     }
 1573: 
 1574:     return(0);
 1575: }
 1576: 
 1577: /*
 1578:  * AdmitBund()
 1579:  */
 1580: 
 1581: int
 1582: AdmitBund(Context ctx, CmdTab cmd)
 1583: {
 1584:     if (!ctx->bund)
 1585: 	return(FALSE);
 1586:     return(TRUE);
 1587: }
 1588: 
 1589: /*
 1590:  * AdmitLink()
 1591:  */
 1592: 
 1593: int
 1594: AdmitLink(Context ctx, CmdTab cmd)
 1595: {
 1596:     if (!ctx->lnk)
 1597: 	return(FALSE);
 1598:     return(TRUE);
 1599: }
 1600: 
 1601: /*
 1602:  * AdmitRep()
 1603:  */
 1604: 
 1605: int
 1606: AdmitRep(Context ctx, CmdTab cmd)
 1607: {
 1608:     if (!ctx->rep)
 1609: 	return(FALSE);
 1610:     return(TRUE);
 1611: }
 1612: 
 1613: /*
 1614:  * AdmitDev()
 1615:  */
 1616: 
 1617: int
 1618: AdmitDev(Context ctx, CmdTab cmd)
 1619: {
 1620:     if (!cmd)
 1621: 	return(FALSE);
 1622:     if (!ctx->lnk)
 1623: 	return(FALSE);
 1624:     if (strncmp(cmd->name, ctx->lnk->type->name, strlen(ctx->lnk->type->name)))
 1625: 	return(FALSE);
 1626:     return(TRUE);
 1627: }
 1628: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>