File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / web.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (4 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

    1: 
    2: /*
    3:  * web.c
    4:  *
    5:  * Written by Alexander Motin <mav@FreeBSD.org>
    6:  */
    7: 
    8: #include "ppp.h"
    9: #include "web.h"
   10: #include "util.h"
   11: 
   12: 
   13: /*
   14:  * DEFINITIONS
   15:  */
   16: 
   17:   /* Set menu options */
   18:   enum {
   19:     SET_OPEN,
   20:     SET_CLOSE,
   21:     SET_SELF,
   22:     SET_DISABLE,
   23:     SET_ENABLE
   24:   };
   25: 
   26: 
   27: /*
   28:  * INTERNAL FUNCTIONS
   29:  */
   30: 
   31:   static int	WebSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
   32: 
   33:   static int	WebServletRun(struct http_servlet *servlet,
   34:                          struct http_request *req, struct http_response *resp);
   35:   static void	WebServletDestroy(struct http_servlet *servlet);
   36: 
   37:   static void	WebLogger(int sev, const char *fmt, ...);
   38: 
   39:   static void	WebConsoleSessionWrite(ConsoleSession cs, const char *fmt, ...);
   40:   static void	WebConsoleSessionWriteV(ConsoleSession cs, const char *fmt, va_list vl);
   41:   static void	WebConsoleSessionShowPrompt(ConsoleSession cs);
   42: 
   43:   static void	WebRunBinCmd(FILE *f, const char *query, int priv);
   44:   static void	WebRunCmd(FILE *f, const char *query, int priv);
   45:   static void	WebShowHTMLSummary(FILE *f, int priv);
   46:   static void	WebShowJSONSummary(FILE *f, int priv);
   47: 
   48: /*
   49:  * GLOBAL VARIABLES
   50:  */
   51: 
   52:   const struct cmdtab WebSetCmds[] = {
   53:     { "open",			"Open the web" ,
   54:   	WebSetCommand, NULL, 2, (void *) SET_OPEN },
   55:     { "close",			"Close the web" ,
   56:   	WebSetCommand, NULL, 2, (void *) SET_CLOSE },
   57:     { "self {ip} [{port}]",	"Set web ip and port" ,
   58:   	WebSetCommand, NULL, 2, (void *) SET_SELF },
   59:     { "enable [opt ...]",	"Enable web option" ,
   60:   	WebSetCommand, NULL, 2, (void *) SET_ENABLE },
   61:     { "disable [opt ...]",	"Disable web option" ,
   62:   	WebSetCommand, NULL, 2, (void *) SET_DISABLE },
   63:     { NULL, NULL, NULL, NULL, 0, NULL },
   64:   };
   65: 
   66: 
   67: /*
   68:  * INTERNAL VARIABLES
   69:  */
   70: 
   71:   static const struct confinfo	gConfList[] = {
   72:     { 0,	WEB_AUTH,	"auth"	},
   73:     { 0,	0,		NULL	},
   74:   };
   75: 
   76:   static struct pevent_ctx *gWebCtx = NULL;
   77:     
   78: /*
   79:  * WebInit()
   80:  */
   81: 
   82: int
   83: WebInit(Web w)
   84: {
   85:   /* setup web-defaults */
   86:   memset(w, 0, sizeof(*w));
   87: 
   88:   Enable(&w->options, WEB_AUTH);  
   89:   
   90:   ParseAddr(DEFAULT_WEB_IP, &w->addr, ALLOW_IPV4|ALLOW_IPV6);
   91:   w->port = DEFAULT_WEB_PORT;
   92: 
   93:   return 0;
   94: }
   95: 
   96: /*
   97:  * WebOpen()
   98:  */
   99: 
  100: int
  101: WebOpen(Web w)
  102: {
  103:   char		addrstr[INET6_ADDRSTRLEN];
  104: 
  105:   if (w->srv) {
  106:     Log(LG_ERR, ("web: web already running"));
  107:     return -1;
  108:   }
  109: 
  110:   gWebCtx = pevent_ctx_create(MB_WEB, NULL);
  111:   if (!gWebCtx) {
  112:     Log(LG_ERR, ("%s: error pevent_ctx_create: %d", __FUNCTION__, errno));
  113:     return(-1);
  114:   }
  115:   
  116:   if (!(w->srv = http_server_start(gWebCtx, w->addr.u.ip4,
  117:            w->port, NULL, "mpd web server", WebLogger))) {
  118:     Log(LG_ERR, ("%s: error http_server_start: %d", __FUNCTION__, errno));
  119:     return(-1);
  120:   }
  121: 
  122:   w->srvlet.arg=NULL;
  123:   w->srvlet.hook=NULL;
  124:   w->srvlet.run=WebServletRun;
  125:   w->srvlet.destroy=WebServletDestroy;
  126: 	   
  127:   if (http_server_register_servlet(w->srv, &w->srvlet, NULL, ".*", 10) < 0) {
  128:     Log(LG_ERR, ("%s: error http_server_register_servlet: %d", __FUNCTION__, errno));
  129:     return(-1);
  130:   }
  131:   
  132:   Log(LG_ERR, ("web: listening on %s %d", 
  133: 	u_addrtoa(&w->addr,addrstr,sizeof(addrstr)), w->port));
  134:   return 0;
  135: }
  136: 
  137: /*
  138:  * WebClose()
  139:  */
  140: 
  141: int
  142: WebClose(Web w)
  143: {
  144:   if (!w->srv) {
  145:     Log(LG_ERR, ("web: web is not running"));
  146:     return -1;
  147:   }
  148: 
  149:   http_server_stop(&w->srv);
  150:   if (gWebCtx) pevent_ctx_destroy(&gWebCtx);
  151:   
  152:   return 0;
  153: }
  154: 
  155: /*
  156:  * WebStat()
  157:  */
  158: 
  159: int
  160: WebStat(Context ctx, int ac, const char *const av[], const void *arg)
  161: {
  162:   Web		w = &gWeb;
  163:   char		addrstr[64];
  164: 
  165:   (void)ac;
  166:   (void)av;
  167:   (void)arg;
  168: 
  169:   Printf("Web configuration:\r\n");
  170:   Printf("\tState         : %s\r\n", w->srv ? "OPENED" : "CLOSED");
  171:   Printf("\tIP-Address    : %s\r\n", u_addrtoa(&w->addr,addrstr,sizeof(addrstr)));
  172:   Printf("\tPort          : %d\r\n", w->port);
  173: 
  174:   Printf("Web options:\r\n");
  175:   OptStat(ctx, &w->options, gConfList);
  176: 
  177:   return 0;
  178: }
  179: 
  180: /*
  181:  * ConsoleSessionWriteV()
  182:  */
  183: 
  184: static void 
  185: WebConsoleSessionWriteV(ConsoleSession cs, const char *fmt, va_list vl)
  186: {
  187:   vfprintf((FILE *)(cs->cookie), fmt, vl);
  188: }
  189: 
  190: /*
  191:  * WebConsoleSessionWrite()
  192:  */
  193: 
  194: static void 
  195: WebConsoleSessionWrite(ConsoleSession cs, const char *fmt, ...)
  196: {
  197:   va_list vl;
  198: 
  199:   va_start(vl, fmt);
  200:   WebConsoleSessionWriteV(cs, fmt, vl);
  201:   va_end(vl);
  202: }
  203: 
  204: /*
  205:  * WebConsoleShowPrompt()
  206:  */
  207: 
  208: static void
  209: WebConsoleSessionShowPrompt(ConsoleSession cs)
  210: {
  211:     if (cs->context.lnk)
  212: 	cs->write(cs, "[%s] ", cs->context.lnk->name);
  213:     else if (cs->context.bund)
  214: 	cs->write(cs, "[%s] ", cs->context.bund->name);
  215:     else if (cs->context.rep)
  216: 	cs->write(cs, "[%s] ", cs->context.rep->name);
  217:     else
  218: 	cs->write(cs, "[] ");
  219: }
  220: 
  221: static void
  222: WebShowCSS(FILE *f)
  223: {
  224:   fprintf(f, "body {font-family: Arial, Helvetica, Sans-Serif; background-color: #EEEEEE; }\n");
  225:   fprintf(f, "table, pre {background-color: #FFFFFF; }\n");
  226:   fprintf(f, "th, td {padding: 0 2pt 0 2pt; }\n");
  227:   fprintf(f, "th {background-color: #00B000; }\n");
  228:   fprintf(f, "td {background-color: #EEEEEE; }\n");
  229:   fprintf(f, "td.r {background-color: #EECCCC; }\n");
  230:   fprintf(f, "td.y {background-color: #EEEEBB; }\n");
  231:   fprintf(f, "td.g {background-color: #BBEEBB; }\n");
  232:   fprintf(f, "td.d {background-color: #CCCCCC; }\n");
  233:   fprintf(f, "a, a:visited, a:link { color: blue; }\n");
  234: }
  235: 
  236: static void
  237: WebShowHTMLSummary(FILE *f, int priv)
  238: {
  239:   int		b,l;
  240:   Bund		B;
  241:   Link  	L;
  242:   Rep		R;
  243:   char		buf[64],buf2[64];
  244: 
  245:   fprintf(f, "<h2>Current status summary</h2>\n");
  246:   fprintf(f, "<table>\n");
  247:   fprintf(f, "<thead>\n<tr>\n<th>Bund</th>\n<th colspan=\"2\">Iface</th>\n<th>IPCP</th>\n<th>IPV6CP</th>\n<th>CCP</th>\n<th>ECP</th>\n"
  248: 	     "<th>Link</th>\n<th>LCP</th>\n<th>User</th>\n<th colspan=\"2\">Device</th>\n<th>Peer</th>\n<th>IP</th>\n<th>&#160;</th>\n<th>&#160;</th>\n<th>&#160;</th>\n%s</tr>\n</thead>\n<tbody>\n",
  249: 	     priv?"<th>State</th>\n":"");
  250: #define FSM_COLOR(s) (((s)==ST_OPENED)?"g":(((s)==ST_INITIAL)?"r":"y"))
  251: #define PHYS_COLOR(s) (((s)==PHYS_STATE_UP)?"g":(((s)==PHYS_STATE_DOWN)?"r":"y"))
  252:     for (b = 0; b<gNumLinks; b++) {
  253: 	if ((L=gLinks[b]) != NULL && L->bund == NULL && L->rep == NULL) {
  254: 	    fprintf(f, "<tr>\n");
  255: 	    fprintf(f, "<td colspan=\"7\">&#160;</td>\n");
  256: 	    fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20link\">%s</a></td>\n", 
  257: 	        L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->name);
  258: 	    fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20lcp\">%s</a></td>\n", 
  259: 	        L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, FsmStateName(L->lcp.fsm.state));
  260: 	    fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20auth\">%s</a></td>\n", 
  261: 	        L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->lcp.auth.params.authname);
  262: 	    fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  263: 	        L->tmpl?"d":PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
  264: 	    fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  265: 	        L->tmpl?"d":PHYS_COLOR(L->state), L->name, gPhysStateNames[L->state]);
  266: 	    if (L->state != PHYS_STATE_DOWN) {
  267: 		PhysGetPeerAddr(L, buf, sizeof(buf));
  268: 		fprintf(f, "<td>%s</td>\n", buf);
  269: 		fprintf(f, "<td>&#160;</td>\n");
  270: 		PhysGetCallingNum(L, buf, sizeof(buf));
  271: 		PhysGetCalledNum(L, buf2, sizeof(buf2));
  272: 		if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
  273: 		    fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
  274: 			buf2, buf);
  275: 		} else {
  276: 		    fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
  277: 			buf, buf2);
  278: 		}
  279: 	    } else {
  280: 	    	fprintf(f, "<td>&#160;</td>\n");
  281: 	    	fprintf(f, "<td>&#160;</td>\n");
  282: 	    	fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
  283: 	    }
  284: 	    if (priv) {
  285: 		if (!L->tmpl) {
  286: 		    switch (L->state) {
  287: 			case PHYS_STATE_DOWN:
  288: 			    fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a></td>\n",
  289: 				L->name);
  290: 			    break;
  291: 			case PHYS_STATE_UP:
  292: 			    fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n",
  293: 				L->name);
  294: 			    break;
  295: 			default:
  296: 			    fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a>&#160;<a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n", 
  297: 				L->name, L->name);
  298: 		    }
  299: 		} else {
  300: 		    fprintf(f, "<td>&#160;</td>\n");
  301: 		}
  302: 	    }
  303: 	    fprintf(f, "</tr>\n");
  304: 	}
  305:     }
  306:   for (b = 0; b<gNumBundles; b++) {
  307:     if ((B=gBundles[b]) != NULL) {
  308: 	int rows = B->n_links?B->n_links:1;
  309: 	int first = 1;
  310: 	fprintf(f, "<tr>\n");
  311: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20bund\">%s</a></td>\n", 
  312: 	    rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, B->name);
  313: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20iface\">%s</a></td>\n", 
  314: 	    rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, B->iface.ifname);
  315: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20iface\">%s</a></td>\n", 
  316: 	    rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, (B->iface.up?"Up":"Down"));
  317: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ipcp\">%s</a></td>\n", 
  318: 	    rows, B->tmpl?"d":FSM_COLOR(B->ipcp.fsm.state), B->name,FsmStateName(B->ipcp.fsm.state));
  319: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ipv6cp\">%s</a></td>\n", 
  320: 	    rows, B->tmpl?"d":FSM_COLOR(B->ipv6cp.fsm.state), B->name,FsmStateName(B->ipv6cp.fsm.state));
  321: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ccp\">%s</a></td>\n", 
  322: 	    rows, B->tmpl?"d":FSM_COLOR(B->ccp.fsm.state), B->name,FsmStateName(B->ccp.fsm.state));
  323: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ecp\">%s</a></td>\n", 
  324: 	    rows, B->tmpl?"d":FSM_COLOR(B->ecp.fsm.state), B->name,FsmStateName(B->ecp.fsm.state));
  325: 	if (B->n_links == 0) {
  326: 	    fprintf(f, "<td colspan=\"11\">&#160;</td>\n</tr>\n");
  327: 	}
  328: 	for (l = 0; l < NG_PPP_MAX_LINKS; l++) {
  329: 	    if ((L=B->links[l]) != NULL) {
  330: 		if (first)
  331: 		    first = 0;
  332: 		else
  333: 		    fprintf(f, "<tr>\n");
  334: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20link\">%s</a></td>\n", 
  335: 		    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->name);
  336: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20lcp\">%s</a></td>\n", 
  337: 		    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, FsmStateName(L->lcp.fsm.state));
  338: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20auth\">%s</a></td>\n", 
  339: 		    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->lcp.auth.params.authname);
  340: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  341: 		    L->tmpl?"d":PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
  342: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  343: 		    L->tmpl?"d":PHYS_COLOR(L->state), L->name, gPhysStateNames[L->state]);
  344: 		if (L->state != PHYS_STATE_DOWN) {
  345: 		    PhysGetPeerAddr(L, buf, sizeof(buf));
  346: 		    fprintf(f, "<td>%s</td>\n", buf);
  347: 		    if (L->bund != NULL)
  348: 			fprintf(f, "<td>%s</td>\n", inet_ntoa(L->bund->ipcp.peer_addr));
  349: 		    else
  350: 			fprintf(f, "<td>&#160;</td>\n");
  351: 		    PhysGetCallingNum(L, buf, sizeof(buf));
  352: 		    PhysGetCalledNum(L, buf2, sizeof(buf2));
  353: 		    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
  354: 			    fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
  355: 				buf2, buf);
  356: 		    } else {
  357: 			    fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
  358: 				buf, buf2);
  359: 		    }
  360: 		} else {
  361: 			fprintf(f, "<td>&#160;</td>\n");
  362: 			fprintf(f, "<td>&#160;</td>\n");
  363: 			fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
  364: 		}
  365: 		if (priv) {
  366: 		    switch (L->state) {
  367: 			case PHYS_STATE_DOWN:
  368: 			    fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a></td>\n",
  369: 				L->name);
  370: 			    break;
  371: 			case PHYS_STATE_UP:
  372: 			    fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n",
  373: 				L->name);
  374: 			    break;
  375: 			default:
  376: 			    fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a>&#160;<a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n", 
  377: 				L->name, L->name);
  378: 		    }
  379: 		}
  380: 		fprintf(f, "</tr>\n");
  381: 	    }
  382: 	}
  383:     }
  384:   }
  385:   for (b = 0; b<gNumReps; b++) {
  386:     if ((R=gReps[b]) != NULL) {
  387: 	int shown = 0;
  388: #define FSM_COLOR(s) (((s)==ST_OPENED)?"g":(((s)==ST_INITIAL)?"r":"y"))
  389: #define PHYS_COLOR(s) (((s)==PHYS_STATE_UP)?"g":(((s)==PHYS_STATE_DOWN)?"r":"y"))
  390: 	int rows = (R->links[0]?1:0) + (R->links[1]?1:0);
  391: 	if (rows == 0)
  392: 	    rows = 1;
  393: 	fprintf(f, "<tr>\n");
  394: 	fprintf(f, "<td rowspan=\"%d\" colspan=\"6\">Repeater</td>\n", rows);
  395: 	fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?rep%%20%s&#38;show%%20repeater\">%s</a></td>\n", 
  396: 	     rows, R->p_up?"g":"r", R->name, R->name);
  397: 	for (l = 0; l < 2; l++) {
  398: 	    if ((L=R->links[l]) != NULL) {
  399: 		if (shown)
  400: 		    fprintf(f, "<tr>\n");
  401: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  402: 		    PHYS_COLOR(L->state), L->name, L->name);
  403: 		fprintf(f, "<td colspan=\"2\">&#160;</td>\n");
  404: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  405: 		    PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
  406: 		fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
  407: 		    PHYS_COLOR(L->state), L->name, gPhysStateNames[L->state]);
  408: 		if (L->state != PHYS_STATE_DOWN) {
  409: 		    PhysGetPeerAddr(L, buf, sizeof(buf));
  410: 		    fprintf(f, "<td>%s</td>\n", buf);
  411: 		    if (L->bund != NULL)
  412: 			fprintf(f, "<td>%s</td>\n", inet_ntoa(L->bund->ipcp.peer_addr));
  413: 		    else
  414: 			fprintf(f, "<td>&#160;</td>\n");
  415: 		    PhysGetCallingNum(L, buf, sizeof(buf));
  416: 		    PhysGetCalledNum(L, buf2, sizeof(buf2));
  417: 		    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
  418: 			    fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
  419: 				buf2, buf);
  420: 		    } else {
  421: 			    fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
  422: 				buf, buf2);
  423: 		    }
  424: 		} else {
  425: 			fprintf(f, "<td>&#160;</td>\n");
  426: 			fprintf(f, "<td>&#160;</td>\n");
  427: 			fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
  428: 		}
  429: 		fprintf(f, "<td>&#160;</td>\n");
  430: 		fprintf(f, "</tr>\n");
  431: 		
  432: 		shown = 1;
  433: 	    }
  434: 	}
  435: 	if (!shown) {
  436: 	    fprintf(f, "<td colspan=\"11\">&#160;</td>\n");
  437: 	    fprintf(f, "</tr>\n");
  438: 	}
  439:     }
  440:   }
  441:   fprintf(f, "</tbody>\n</table>\n");
  442: }
  443: 
  444: static void
  445: WebShowJSONSummary(FILE *f, int priv)
  446: {
  447:   int		b,l;
  448:   Bund		B;
  449:   Link  	L;
  450:   Rep		R;
  451:   char		buf[64],buf2[64];
  452: 
  453:   (void)priv;
  454:   int first_l = 1;
  455:   fprintf(f, "{\"links\":[\n");
  456:   for (b = 0; b<gNumLinks; b++) {
  457: 	if ((L=gLinks[b]) != NULL && L->bund == NULL && L->rep == NULL) {
  458: 	    if (first_l) {
  459: 		fprintf(f, "{\n");
  460: 		first_l = 0;
  461: 	    } else
  462: 		fprintf(f, ",\n{\n");
  463: 
  464: 	    fprintf(f, "\"link\": \"%s\",\n", L->name);
  465: 	    fprintf(f, "\"lcp\": \"%s\",\n", FsmStateName(L->lcp.fsm.state));
  466: 	    fprintf(f, "\"auth\": \"%s\",\n", L->lcp.auth.params.authname);
  467: 	    fprintf(f, "\"type\": \"%s\",\n", L->type?L->type->name:"");
  468: 	    fprintf(f, "\"state\": \"%s\",\n", gPhysStateNames[L->state]);
  469: 
  470: 	    if (L->state != PHYS_STATE_DOWN) {
  471: 	        PhysGetPeerAddr(L, buf, sizeof(buf));
  472: 	        fprintf(f, "\"peer_ip\": \"%s\",\n", buf);
  473: 
  474: 		PhysGetCallingNum(L, buf, sizeof(buf));
  475: 		PhysGetCalledNum(L, buf2, sizeof(buf2));
  476: 		if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
  477: 		    fprintf(f, "\"calling_num\": \"%s\",\n", buf);
  478: 		    fprintf(f, "\"called_num\": \"%s\"\n", buf2);
  479: 		} else {
  480: 		    fprintf(f, "\"calling_num\": \"%s\",\n", buf2);
  481: 		    fprintf(f, "\"called_num\": \"%s\"\n", buf);
  482: 		}
  483: 	    } else {
  484: 		fprintf(f, "\"calling_num\": \"%s\",\n", "");
  485: 		fprintf(f, "\"called_num\": \"%s\"\n", "");
  486: 	    }
  487: 	    fprintf(f, "}\n");
  488: 	}
  489:   }
  490:   fprintf(f, "],\n");
  491: 
  492:   int first_b = 1;
  493:   fprintf(f, "\"bundles\":[\n");
  494:   for (b = 0; b<gNumBundles; b++) {
  495:     if ((B=gBundles[b]) != NULL) {
  496: 	if (first_b) {
  497: 	    fprintf(f, "{\n");
  498: 	    first_b = 0;
  499: 	} else
  500: 	    fprintf(f, ",\n{\n");
  501: 
  502: 	fprintf(f, "\"bundle\": \"%s\",\n", B->name);
  503: 	fprintf(f, "\"iface\": \"%s\",\n", B->iface.ifname);
  504: 	fprintf(f, "\"state\": \"%s\",\n", (B->iface.up?"Up":"Down"));
  505: 	fprintf(f, "\"ipcp\": \"%s\",\n", FsmStateName(B->ipcp.fsm.state));
  506: 	fprintf(f, "\"ipv6cp\": \"%s\",\n", FsmStateName(B->ipv6cp.fsm.state));
  507: 	fprintf(f, "\"ccp\": \"%s\",\n", FsmStateName(B->ccp.fsm.state));
  508: 	fprintf(f, "\"ecp\": \"%s\",\n", FsmStateName(B->ecp.fsm.state));
  509: 
  510: 	first_l = 1;
  511: 	fprintf(f, "\"links\":[\n");
  512: 	for (l = 0; l < NG_PPP_MAX_LINKS; l++) {
  513: 	    if ((L=B->links[l]) != NULL) {
  514: 		if (first_l) {
  515: 		    fprintf(f, "{\n");
  516: 		    first_l = 0;
  517: 		} else
  518: 		    fprintf(f, ",\n{\n");
  519: 
  520: 		fprintf(f, "\"link\": \"%s\",\n", L->name);
  521: 		fprintf(f, "\"lcp\": \"%s\",\n", FsmStateName(L->lcp.fsm.state));
  522: 		fprintf(f, "\"auth\": \"%s\",\n", L->lcp.auth.params.authname);
  523: 		fprintf(f, "\"type\": \"%s\",\n", L->type?L->type->name:"");
  524: 		fprintf(f, "\"state\": \"%s\",\n", gPhysStateNames[L->state]);
  525: 
  526: 		if (L->state != PHYS_STATE_DOWN) {
  527: 		    PhysGetPeerAddr(L, buf, sizeof(buf));
  528: 		    fprintf(f, "\"peer_ip\": \"%s\",\n", buf);
  529: 
  530: 		    if (L->bund != NULL)
  531: 			fprintf(f, "\"ipcp_ip\": \"%s\",\n", inet_ntoa(L->bund->ipcp.peer_addr));
  532: 		    else
  533: 			fprintf(f, "\"ipcp_ip\": \"%s\",\n", "");
  534: 
  535: 		    PhysGetCallingNum(L, buf, sizeof(buf));
  536: 		    PhysGetCalledNum(L, buf2, sizeof(buf2));
  537: 		    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
  538: 			fprintf(f, "\"calling_num\": \"%s\",\n", buf);
  539: 			fprintf(f, "\"called_num\": \"%s\"\n", buf2);
  540: 		    } else {
  541: 			fprintf(f, "\"calling_num\": \"%s\",\n", buf2);
  542: 			fprintf(f, "\"called_num\": \"%s\"\n", buf);
  543: 		    }
  544: 		} else {
  545: 			fprintf(f, "\"calling_num\": \"%s\",\n", "");
  546: 			fprintf(f, "\"called_num\": \"%s\"\n", "");
  547: 		}
  548: 		fprintf(f, "}\n");
  549: 	    }
  550: 	}
  551: 	fprintf(f, "]\n}\n");
  552:     }
  553:   }
  554:   fprintf(f, "],\n");
  555: 
  556:   int first_r = 1;
  557:   fprintf(f, "\"repeaters\":[\n");
  558:   for (b = 0; b<gNumReps; b++) {
  559:     if ((R=gReps[b]) != NULL) {
  560: 	if (first_r) {
  561: 	    fprintf(f, "{\n");
  562: 	    first_r = 0;
  563: 	} else
  564: 	    fprintf(f, ",\n{\n");
  565: 
  566: 	fprintf(f, "\"repeater\": \"%s\",\n", R->name);
  567: 
  568: 	first_l = 1;
  569: 	fprintf(f, "\"links\":[\n");
  570: 	for (l = 0; l < 2; l++) {
  571: 	    if ((L=R->links[l]) != NULL) {
  572: 		if (first_l) {
  573: 		    fprintf(f, "{\n");
  574: 		    first_l = 0;
  575: 		} else
  576: 		    fprintf(f, ",\n{\n");
  577: 
  578: 		fprintf(f, "\"link\": \"%s\",\n", L->name);
  579: 		fprintf(f, "\"type\": \"%s\",\n", L->type?L->type->name:"");
  580: 		fprintf(f, "\"state\": \"%s\",\n", gPhysStateNames[L->state]);
  581: 
  582: 		if (L->state != PHYS_STATE_DOWN) {
  583: 		    PhysGetPeerAddr(L, buf, sizeof(buf));
  584: 		    fprintf(f, "\"peer_ip\": \"%s\",\n", buf);
  585: 
  586: 		    if (L->bund != NULL)
  587: 			fprintf(f, "\"ipcp_ip\": \"%s\",\n", inet_ntoa(L->bund->ipcp.peer_addr));
  588: 		    else
  589: 			fprintf(f, "\"ipcp_ip\": \"%s\",\n", "");
  590: 
  591: 		    PhysGetCallingNum(L, buf, sizeof(buf));
  592: 		    PhysGetCalledNum(L, buf2, sizeof(buf2));
  593: 		    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
  594: 			fprintf(f, "\"calling_num\": \"%s\",\n", buf);
  595: 			fprintf(f, "\"called_num\": \"%s\"\n", buf2);
  596: 		    } else {
  597: 			fprintf(f, "\"calling_num\": \"%s\",\n", buf2);
  598: 			fprintf(f, "\"called_num\": \"%s\"\n", buf);
  599: 		    }
  600: 		} else {
  601: 		    fprintf(f, "\"calling_num\": \"%s\",\n", "");
  602: 		    fprintf(f, "\"called_num\": \"%s\"\n", "");
  603: 		}
  604: 		fprintf(f, "}\n");
  605: 	    }
  606: 	}
  607: 	fprintf(f, "]\n");
  608: 
  609:         if (b == (gNumReps - 1)) {
  610: 	    fprintf(f, "}\n");
  611: 	} else {
  612: 	    fprintf(f, "},\n");
  613: 	}
  614:     }
  615:   }
  616:   fprintf(f, "]}\n");
  617: }
  618: 
  619: static void 
  620: WebRunBinCmd(FILE *f, const char *query, int priv)
  621: {
  622:     Console		c = &gConsole;
  623:     struct console_session css;
  624:     ConsoleSession	cs = &css;
  625:     char		*buf;
  626:     char		*tmp;
  627:     int			argc, k;
  628:     char		*argv[MAX_CONSOLE_ARGS];
  629:   
  630:     memset(cs, 0, sizeof(*cs));
  631: 
  632:     cs->cookie = f;
  633:     cs->console = c;
  634:     cs->close = NULL;
  635:     cs->write = WebConsoleSessionWrite;
  636:     cs->writev = WebConsoleSessionWriteV;
  637:     cs->prompt = WebConsoleSessionShowPrompt;
  638:     cs->context.cs = cs;
  639:     cs->context.priv = priv;
  640: 
  641:     tmp = buf = Mstrdup(MB_WEB, query);
  642:     for (argc = 0; (argv[argc] = strsep(&tmp, "&")) != NULL;)
  643: 	if (argv[argc][0] != '\0')
  644:     	    if (++argc >= MAX_CONSOLE_ARGS)
  645:         	break;
  646: 
  647:     for (k = 0; k < argc; k++) {
  648: 	int	ac, rtn;
  649: 	char *av[MAX_CONSOLE_ARGS];
  650: 	char	*buf1;
  651: 
  652: 	buf1 = Malloc(MB_WEB, strlen(argv[k]) + 1);
  653: 	http_request_url_decode(argv[k], buf1);
  654:         Log2(LG_CONSOLE, ("[%s] WEB: %s", 
  655: 	    cs->context.lnk ? cs->context.lnk->name :
  656: 		(cs->context.bund? cs->context.bund->name : ""), 
  657: 	    buf1));
  658: 	ac = ParseLine(buf1, av, sizeof(av) / sizeof(*av), 0);
  659: 	cs->context.errmsg[0] = 0;
  660: 	rtn = DoCommandTab(&cs->context, gCommands, ac, (const char *const *)av);
  661: 	Freee(buf1);
  662: 	fprintf(f, "RESULT: %d %s\n", rtn, cs->context.errmsg);
  663:     }
  664:     Freee(buf);
  665:     RESETREF(cs->context.lnk, NULL);
  666:     RESETREF(cs->context.bund, NULL);
  667:     RESETREF(cs->context.rep, NULL);
  668: }
  669: 
  670: static void 
  671: WebRunCmd(FILE *f, const char *query, int priv)
  672: {
  673:     Console		c = &gConsole;
  674:     struct console_session css;
  675:     ConsoleSession	cs = &css;
  676:     char		*buf;
  677:     char		*tmp;
  678:     int			argc, k;
  679:     char		*argv[MAX_CONSOLE_ARGS];
  680:   
  681:     memset(cs, 0, sizeof(*cs));
  682: 
  683:     cs->cookie = f;
  684:     cs->console = c;
  685:     cs->close = NULL;
  686:     cs->write = WebConsoleSessionWrite;
  687:     cs->writev = WebConsoleSessionWriteV;
  688:     cs->prompt = WebConsoleSessionShowPrompt;
  689:     cs->context.cs = cs;
  690:     cs->context.priv = priv;
  691: 
  692:     tmp = buf = Mstrdup(MB_WEB, query);
  693:     for (argc = 0; (argv[argc] = strsep(&tmp, "&")) != NULL;)
  694: 	if (argv[argc][0] != '\0')
  695:     	    if (++argc >= MAX_CONSOLE_ARGS)
  696:         	break;
  697: 
  698:     fprintf(f, "<p>\n<a href=\"/\">Back</a>\n</p>\n");
  699: 
  700:     if (argc == 0) {
  701: 	fprintf(f, "<p>No command cpecified!</p>\n");
  702: 	goto done;
  703:     }
  704: 
  705:     fprintf(f, "<pre>\n");
  706:     for (k = 0; k < argc; k++) {
  707: 	int	ac;
  708: 	char *av[MAX_CONSOLE_ARGS];
  709: 	char	*buf1;
  710: 
  711: 	buf1 = Malloc(MB_WEB, strlen(argv[k]) + 1);
  712: 	http_request_url_decode(argv[k], buf1);
  713:         Log2(LG_CONSOLE, ("[%s] WEB: %s", 
  714: 	    cs->context.lnk ? cs->context.lnk->name :
  715: 		(cs->context.bund? cs->context.bund->name : ""), 
  716: 	    buf1));
  717: 
  718: 	cs->prompt(cs);
  719: 	cs->write(cs, "%s\n", buf1);
  720:     
  721: 	ac = ParseLine(buf1, av, sizeof(av) / sizeof(*av), 0);
  722: 	DoCommand(&cs->context, ac, (const char *const *)av, NULL, 0);
  723: 	Freee(buf1);
  724:     }
  725:     fprintf(f, "</pre>\n");
  726: done:
  727:     Freee(buf);
  728:     fprintf(f, "<p>\n<a href=\"/\">Back</a>\n</p>\n");
  729:     RESETREF(cs->context.lnk, NULL);
  730:     RESETREF(cs->context.bund, NULL);
  731:     RESETREF(cs->context.rep, NULL);
  732: }
  733: 
  734: static void
  735: WebServletRunCleanup(void *cookie) NO_THREAD_SAFETY_ANALYSIS
  736: {
  737:     (void)cookie;
  738:     GIANT_MUTEX_UNLOCK();
  739: }
  740: 
  741: static int	
  742: WebServletRun(struct http_servlet *servlet,
  743:                          struct http_request *req, struct http_response *resp)
  744: {
  745:     FILE *f;
  746:     const char *path;
  747:     const char *query;
  748:     int priv = 0;
  749:     
  750:     (void)servlet;
  751:     if (Enabled(&gWeb.options, WEB_AUTH)) {
  752: 	const char *username;
  753: 	const char *password;
  754: 	ConsoleUser		u;
  755: 	struct console_user	iu;
  756: 
  757: 	/* Get username and password */
  758: 	if ((username = http_request_get_username(req)) == NULL)
  759:     	    username = "";
  760: 	if ((password = http_request_get_password(req)) == NULL)
  761:     	    password = "";
  762: 
  763: 	strlcpy(iu.username, username, sizeof(iu.username));
  764: 	RWLOCK_RDLOCK(gUsersLock);
  765: 	u = ghash_get(gUsers, &iu);
  766: 	RWLOCK_UNLOCK(gUsersLock);
  767: 
  768: 	if ((u == NULL) || strcmp(u->password, password)) {
  769: 		http_response_send_basic_auth(resp, "Access Restricted");
  770: 		return (1);
  771: 	}
  772: 	priv = u->priv;
  773:     }
  774: 
  775:     if (!(f = http_response_get_output(resp, 1))) {
  776: 	return 0;
  777:     }
  778:     if (!(path = http_request_get_path(req)))
  779: 	return 0;
  780:     if (!(query = http_request_get_query_string(req)))
  781: 	return 0;
  782: 
  783:     if (!strcmp(path,"/mpd.css")) {
  784: 	http_response_set_header(resp, 0, "Content-Type", "text/css");
  785: 	WebShowCSS(f);
  786:     } else if (!strcmp(path,"/bincmd") || !strcmp(path,"/json")) {
  787: 	http_response_set_header(resp, 0, "Content-Type", "text/plain");
  788: 	http_response_set_header(resp, 1, "Pragma", "no-cache");
  789: 	http_response_set_header(resp, 1, "Cache-Control", "no-cache, must-revalidate");
  790: 	
  791: 	pthread_cleanup_push(WebServletRunCleanup, NULL);
  792: 	GIANT_MUTEX_LOCK();
  793: 	
  794: 	if (!strcmp(path,"/bincmd"))
  795: 	    WebRunBinCmd(f, query, priv);
  796: 	else if (!strcmp(path,"/json"))
  797: 	    WebShowJSONSummary(f, priv);
  798: 
  799: 	GIANT_MUTEX_UNLOCK();
  800: 	pthread_cleanup_pop(0);
  801: 
  802:     } else if (!strcmp(path,"/") || !strcmp(path,"/cmd")) {
  803: 	http_response_set_header(resp, 0, "Content-Type", "text/html");
  804: 	http_response_set_header(resp, 1, "Pragma", "no-cache");
  805: 	http_response_set_header(resp, 1, "Cache-Control", "no-cache, must-revalidate");
  806: 	
  807: 	pthread_cleanup_push(WebServletRunCleanup, NULL);
  808: 	GIANT_MUTEX_LOCK();
  809: 
  810: 	fprintf(f, "<!DOCTYPE html>\n");
  811: 	fprintf(f, "<html>\n");
  812: 	fprintf(f, "<head>\n<title>Multi-link PPP Daemon for FreeBSD (mpd)</title>\n");
  813: 	fprintf(f, "<link rel=\"stylesheet\" href=\"/mpd.css\" type=\"text/css\"/>\n");
  814: 	fprintf(f, "</head>\n<body>\n");
  815: 	fprintf(f, "<h1>Multi-link PPP Daemon for FreeBSD</h1>\n");
  816:     
  817: 	if (!strcmp(path,"/"))
  818: 	    WebShowHTMLSummary(f, priv);
  819: 	else if (!strcmp(path,"/cmd"))
  820: 	    WebRunCmd(f, query, priv);
  821: 	    
  822: 	GIANT_MUTEX_UNLOCK();
  823: 	pthread_cleanup_pop(0);
  824: 	
  825: 	fprintf(f, "</body>\n</html>\n");
  826:     } else {
  827: 	http_response_send_error(resp, 404, NULL);
  828:     }
  829:     return 1;
  830: }
  831: 
  832: static void	
  833: WebServletDestroy(struct http_servlet *servlet)
  834: {
  835:     (void)servlet;
  836: }
  837: 
  838: static void
  839: WebLogger(int sev, const char *fmt, ...)
  840: {
  841:   va_list       args;
  842: 
  843:   (void)sev;
  844:   va_start(args, fmt);
  845:   vLogPrintf(fmt, args);
  846:   va_end(args);
  847: }
  848: 
  849: /*
  850:  * WebSetCommand()
  851:  */
  852: 
  853: static int
  854: WebSetCommand(Context ctx, int ac, const char *const av[], const void *arg) 
  855: {
  856:   Web	 		w = &gWeb;
  857:   int			port;
  858: 
  859:   switch ((intptr_t)arg) {
  860: 
  861:     case SET_OPEN:
  862:       WebOpen(w);
  863:       break;
  864: 
  865:     case SET_CLOSE:
  866:       WebClose(w);
  867:       break;
  868: 
  869:     case SET_ENABLE:
  870: 	EnableCommand(ac, av, &w->options, gConfList);
  871:       break;
  872: 
  873:     case SET_DISABLE:
  874: 	DisableCommand(ac, av, &w->options, gConfList);
  875:       break;
  876: 
  877:     case SET_SELF:
  878:       if (ac < 1 || ac > 2)
  879: 	return(-1);
  880: 
  881:       if (!ParseAddr(av[0],&w->addr, ALLOW_IPV4)) 
  882: 	Error("Bogus IP address given %s", av[0]);
  883: 
  884:       if (ac == 2) {
  885:         port =  strtol(av[1], NULL, 10);
  886:         if (port < 1 || port > 65535)
  887: 	    Error("Bogus port given %s", av[1]);
  888:         w->port=port;
  889:       }
  890:       break;
  891: 
  892:     default:
  893:       return(-1);
  894: 
  895:   }
  896: 
  897:   return 0;
  898: }

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