Annotation of embedaddon/mpd/src/web.c, revision 1.1.1.2

1.1       misho       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);
1.1.1.2 ! misho      45:   static void  WebShowHTMLSummary(FILE *f, int priv);
        !            46:   static void  WebShowJSONSummary(FILE *f, int priv);
1.1       misho      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");
1.1.1.2 ! misho     221:   fprintf(f, "table, pre {background-color: #FFFFFF; }\n");
1.1       misho     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
1.1.1.2 ! misho     233: WebShowHTMLSummary(FILE *f, int priv)
1.1       misho     234: {
                    235:   int          b,l;
                    236:   Bund         B;
                    237:   Link         L;
                    238:   Rep          R;
                    239:   char         buf[64],buf2[64];
                    240: 
1.1.1.2 ! misho     241:   fprintf(f, "<h2>Current status summary</h2>\n");
1.1       misho     242:   fprintf(f, "<table>\n");
1.1.1.2 ! misho     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":"");
1.1       misho     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) {
1.1.1.2 ! misho     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", 
1.1       misho     253:                L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->name);
1.1.1.2 ! misho     254:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20lcp\">%s</a></td>\n", 
1.1       misho     255:                L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, FsmStateName(L->lcp.fsm.state));
1.1.1.2 ! misho     256:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20auth\">%s</a></td>\n", 
1.1       misho     257:                L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->lcp.auth.params.authname);
1.1.1.2 ! misho     258:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     259:                L->tmpl?"d":PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
1.1.1.2 ! misho     260:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     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));
1.1.1.2 ! misho     264:                fprintf(f, "<td>%s</td>\n", buf);
        !           265:                fprintf(f, "<td>&#160;</td>\n");
1.1       misho     266:                PhysGetCallingNum(L, buf, sizeof(buf));
                    267:                PhysGetCalledNum(L, buf2, sizeof(buf2));
                    268:                if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
1.1.1.2 ! misho     269:                    fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
1.1       misho     270:                        buf2, buf);
                    271:                } else {
1.1.1.2 ! misho     272:                    fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
1.1       misho     273:                        buf, buf2);
                    274:                }
                    275:            } else {
1.1.1.2 ! misho     276:                fprintf(f, "<td>&#160;</td>\n");
        !           277:                fprintf(f, "<td>&#160;</td>\n");
        !           278:                fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
1.1       misho     279:            }
                    280:            if (priv) {
                    281:                if (!L->tmpl) {
                    282:                    switch (L->state) {
                    283:                        case PHYS_STATE_DOWN:
1.1.1.2 ! misho     284:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a></td>\n",
1.1       misho     285:                                L->name);
                    286:                            break;
                    287:                        case PHYS_STATE_UP:
1.1.1.2 ! misho     288:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n",
1.1       misho     289:                                L->name);
                    290:                            break;
                    291:                        default:
1.1.1.2 ! misho     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", 
1.1       misho     293:                                L->name, L->name);
                    294:                    }
                    295:                } else {
1.1.1.2 ! misho     296:                    fprintf(f, "<td>&#160;</td>\n");
1.1       misho     297:                }
                    298:            }
1.1.1.2 ! misho     299:            fprintf(f, "</tr>\n");
1.1       misho     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;
1.1.1.2 ! misho     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", 
1.1       misho     308:            rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, B->name);
1.1.1.2 ! misho     309:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20iface\">%s</a></td>\n", 
1.1       misho     310:            rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, B->iface.ifname);
1.1.1.2 ! misho     311:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20iface\">%s</a></td>\n", 
1.1       misho     312:            rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, (B->iface.up?"Up":"Down"));
1.1.1.2 ! misho     313:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ipcp\">%s</a></td>\n", 
1.1       misho     314:            rows, B->tmpl?"d":FSM_COLOR(B->ipcp.fsm.state), B->name,FsmStateName(B->ipcp.fsm.state));
1.1.1.2 ! misho     315:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ipv6cp\">%s</a></td>\n", 
1.1       misho     316:            rows, B->tmpl?"d":FSM_COLOR(B->ipv6cp.fsm.state), B->name,FsmStateName(B->ipv6cp.fsm.state));
1.1.1.2 ! misho     317:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ccp\">%s</a></td>\n", 
1.1       misho     318:            rows, B->tmpl?"d":FSM_COLOR(B->ccp.fsm.state), B->name,FsmStateName(B->ccp.fsm.state));
1.1.1.2 ! misho     319:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ecp\">%s</a></td>\n", 
1.1       misho     320:            rows, B->tmpl?"d":FSM_COLOR(B->ecp.fsm.state), B->name,FsmStateName(B->ecp.fsm.state));
                    321:        if (B->n_links == 0) {
1.1.1.2 ! misho     322:            fprintf(f, "<td colspan=\"11\">&#160;</td>\n</tr>\n");
1.1       misho     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
1.1.1.2 ! misho     329:                    fprintf(f, "<tr>\n");
        !           330:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20link\">%s</a></td>\n", 
1.1       misho     331:                    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->name);
1.1.1.2 ! misho     332:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20lcp\">%s</a></td>\n", 
1.1       misho     333:                    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, FsmStateName(L->lcp.fsm.state));
1.1.1.2 ! misho     334:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20auth\">%s</a></td>\n", 
1.1       misho     335:                    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->lcp.auth.params.authname);
1.1.1.2 ! misho     336:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     337:                    L->tmpl?"d":PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
1.1.1.2 ! misho     338:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     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));
1.1.1.2 ! misho     342:                    fprintf(f, "<td>%s</td>\n", buf);
1.1       misho     343:                    if (L->bund != NULL)
1.1.1.2 ! misho     344:                        fprintf(f, "<td>%s</td>\n", inet_ntoa(L->bund->ipcp.peer_addr));
1.1       misho     345:                    else
1.1.1.2 ! misho     346:                        fprintf(f, "<td>&#160;</td>\n");
1.1       misho     347:                    PhysGetCallingNum(L, buf, sizeof(buf));
                    348:                    PhysGetCalledNum(L, buf2, sizeof(buf2));
                    349:                    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
1.1.1.2 ! misho     350:                            fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
1.1       misho     351:                                buf2, buf);
                    352:                    } else {
1.1.1.2 ! misho     353:                            fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
1.1       misho     354:                                buf, buf2);
                    355:                    }
                    356:                } else {
1.1.1.2 ! misho     357:                        fprintf(f, "<td>&#160;</td>\n");
        !           358:                        fprintf(f, "<td>&#160;</td>\n");
        !           359:                        fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
1.1       misho     360:                }
                    361:                if (priv) {
                    362:                    switch (L->state) {
                    363:                        case PHYS_STATE_DOWN:
1.1.1.2 ! misho     364:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a></td>\n",
1.1       misho     365:                                L->name);
                    366:                            break;
                    367:                        case PHYS_STATE_UP:
1.1.1.2 ! misho     368:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n",
1.1       misho     369:                                L->name);
                    370:                            break;
                    371:                        default:
1.1.1.2 ! misho     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", 
1.1       misho     373:                                L->name, L->name);
                    374:                    }
                    375:                }
1.1.1.2 ! misho     376:                fprintf(f, "</tr>\n");
1.1       misho     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;
1.1.1.2 ! misho     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", 
1.1       misho     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)
1.1.1.2 ! misho     396:                    fprintf(f, "<tr>\n");
        !           397:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     398:                    PHYS_COLOR(L->state), L->name, L->name);
1.1.1.2 ! misho     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", 
1.1       misho     401:                    PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
1.1.1.2 ! misho     402:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     403:                    PHYS_COLOR(L->state), L->name, gPhysStateNames[L->state]);
                    404:                if (L->state != PHYS_STATE_DOWN) {
                    405:                    PhysGetPeerAddr(L, buf, sizeof(buf));
1.1.1.2 ! misho     406:                    fprintf(f, "<td>%s</td>\n", buf);
1.1       misho     407:                    if (L->bund != NULL)
1.1.1.2 ! misho     408:                        fprintf(f, "<td>%s</td>\n", inet_ntoa(L->bund->ipcp.peer_addr));
1.1       misho     409:                    else
1.1.1.2 ! misho     410:                        fprintf(f, "<td>&#160;</td>\n");
1.1       misho     411:                    PhysGetCallingNum(L, buf, sizeof(buf));
                    412:                    PhysGetCalledNum(L, buf2, sizeof(buf2));
                    413:                    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
1.1.1.2 ! misho     414:                            fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
1.1       misho     415:                                buf2, buf);
                    416:                    } else {
1.1.1.2 ! misho     417:                            fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
1.1       misho     418:                                buf, buf2);
                    419:                    }
                    420:                } else {
1.1.1.2 ! misho     421:                        fprintf(f, "<td>&#160;</td>\n");
        !           422:                        fprintf(f, "<td>&#160;</td>\n");
        !           423:                        fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
1.1       misho     424:                }
1.1.1.2 ! misho     425:                fprintf(f, "<td>&#160;</td>\n");
        !           426:                fprintf(f, "</tr>\n");
1.1       misho     427:                
                    428:                shown = 1;
                    429:            }
                    430:        }
                    431:        if (!shown) {
1.1.1.2 ! misho     432:            fprintf(f, "<td colspan=\"11\">&#160;</td>\n");
        !           433:            fprintf(f, "</tr>\n");
1.1       misho     434:        }
                    435:     }
                    436:   }
1.1.1.2 ! misho     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");
1.1       misho     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: 
1.1.1.2 ! misho     693:     fprintf(f, "<p>\n<a href=\"/\">Back</a>\n</p>\n");
1.1       misho     694: 
                    695:     if (argc == 0) {
1.1.1.2 ! misho     696:        fprintf(f, "<p>No command cpecified!</p>\n");
1.1       misho     697:        goto done;
                    698:     }
                    699: 
1.1.1.2 ! misho     700:     fprintf(f, "<pre>\n");
1.1       misho     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:     }
1.1.1.2 ! misho     720:     fprintf(f, "</pre>\n");
1.1       misho     721: done:
                    722:     Freee(buf);
1.1.1.2 ! misho     723:     fprintf(f, "<p>\n<a href=\"/\">Back</a>\n</p>\n");
1.1       misho     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);
1.1.1.2 ! misho     778:     } else if (!strcmp(path,"/bincmd") || !strcmp(path,"/json")) {
1.1       misho     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();
1.1.1.2 ! misho     785:        
        !           786:        if (!strcmp(path,"/bincmd"))
        !           787:            WebRunBinCmd(f, query, priv);
        !           788:        else if (!strcmp(path,"/json"))
        !           789:            WebShowJSONSummary(f, priv);
        !           790: 
1.1       misho     791:        GIANT_MUTEX_UNLOCK();
                    792:        pthread_cleanup_pop(0);
1.1.1.2 ! misho     793: 
1.1       misho     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();
1.1.1.2 ! misho     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");
1.1       misho     808:     
                    809:        if (!strcmp(path,"/"))
1.1.1.2 ! misho     810:            WebShowHTMLSummary(f, priv);
1.1       misho     811:        else if (!strcmp(path,"/cmd"))
                    812:            WebRunCmd(f, query, priv);
                    813:            
                    814:        GIANT_MUTEX_UNLOCK();
                    815:        pthread_cleanup_pop(0);
                    816:        
1.1.1.2 ! misho     817:        fprintf(f, "</body>\n</html>\n");
1.1       misho     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>