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

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