File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / command.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

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

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