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

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: 
1.1.1.3 ! misho      31:   static int   WebSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1       misho      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 },
1.1.1.3 ! misho      63:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho      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
1.1.1.3 ! misho     160: WebStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     161: {
                    162:   Web          w = &gWeb;
                    163:   char         addrstr[64];
                    164: 
1.1.1.3 ! misho     165:   (void)ac;
        !           166:   (void)av;
        !           167:   (void)arg;
        !           168: 
1.1       misho     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");
1.1.1.2   misho     225:   fprintf(f, "table, pre {background-color: #FFFFFF; }\n");
1.1       misho     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
1.1.1.2   misho     237: WebShowHTMLSummary(FILE *f, int priv)
1.1       misho     238: {
                    239:   int          b,l;
                    240:   Bund         B;
                    241:   Link         L;
                    242:   Rep          R;
                    243:   char         buf[64],buf2[64];
                    244: 
1.1.1.2   misho     245:   fprintf(f, "<h2>Current status summary</h2>\n");
1.1       misho     246:   fprintf(f, "<table>\n");
1.1.1.2   misho     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":"");
1.1       misho     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) {
1.1.1.2   misho     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", 
1.1       misho     257:                L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->name);
1.1.1.2   misho     258:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20lcp\">%s</a></td>\n", 
1.1       misho     259:                L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, FsmStateName(L->lcp.fsm.state));
1.1.1.2   misho     260:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20auth\">%s</a></td>\n", 
1.1       misho     261:                L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->lcp.auth.params.authname);
1.1.1.2   misho     262:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     263:                L->tmpl?"d":PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
1.1.1.2   misho     264:            fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     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));
1.1.1.2   misho     268:                fprintf(f, "<td>%s</td>\n", buf);
                    269:                fprintf(f, "<td>&#160;</td>\n");
1.1       misho     270:                PhysGetCallingNum(L, buf, sizeof(buf));
                    271:                PhysGetCalledNum(L, buf2, sizeof(buf2));
                    272:                if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
1.1.1.2   misho     273:                    fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
1.1       misho     274:                        buf2, buf);
                    275:                } else {
1.1.1.2   misho     276:                    fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
1.1       misho     277:                        buf, buf2);
                    278:                }
                    279:            } else {
1.1.1.2   misho     280:                fprintf(f, "<td>&#160;</td>\n");
                    281:                fprintf(f, "<td>&#160;</td>\n");
                    282:                fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
1.1       misho     283:            }
                    284:            if (priv) {
                    285:                if (!L->tmpl) {
                    286:                    switch (L->state) {
                    287:                        case PHYS_STATE_DOWN:
1.1.1.2   misho     288:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a></td>\n",
1.1       misho     289:                                L->name);
                    290:                            break;
                    291:                        case PHYS_STATE_UP:
1.1.1.2   misho     292:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n",
1.1       misho     293:                                L->name);
                    294:                            break;
                    295:                        default:
1.1.1.2   misho     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", 
1.1       misho     297:                                L->name, L->name);
                    298:                    }
                    299:                } else {
1.1.1.2   misho     300:                    fprintf(f, "<td>&#160;</td>\n");
1.1       misho     301:                }
                    302:            }
1.1.1.2   misho     303:            fprintf(f, "</tr>\n");
1.1       misho     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;
1.1.1.2   misho     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", 
1.1       misho     312:            rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, B->name);
1.1.1.2   misho     313:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20iface\">%s</a></td>\n", 
1.1       misho     314:            rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, B->iface.ifname);
1.1.1.2   misho     315:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20iface\">%s</a></td>\n", 
1.1       misho     316:            rows, B->tmpl?"d":(B->iface.up?"g":"r"), B->name, (B->iface.up?"Up":"Down"));
1.1.1.2   misho     317:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ipcp\">%s</a></td>\n", 
1.1       misho     318:            rows, B->tmpl?"d":FSM_COLOR(B->ipcp.fsm.state), B->name,FsmStateName(B->ipcp.fsm.state));
1.1.1.2   misho     319:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ipv6cp\">%s</a></td>\n", 
1.1       misho     320:            rows, B->tmpl?"d":FSM_COLOR(B->ipv6cp.fsm.state), B->name,FsmStateName(B->ipv6cp.fsm.state));
1.1.1.2   misho     321:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ccp\">%s</a></td>\n", 
1.1       misho     322:            rows, B->tmpl?"d":FSM_COLOR(B->ccp.fsm.state), B->name,FsmStateName(B->ccp.fsm.state));
1.1.1.2   misho     323:        fprintf(f, "<td rowspan=\"%d\" class=\"%s\"><a href=\"/cmd?bund%%20%s&#38;show%%20ecp\">%s</a></td>\n", 
1.1       misho     324:            rows, B->tmpl?"d":FSM_COLOR(B->ecp.fsm.state), B->name,FsmStateName(B->ecp.fsm.state));
                    325:        if (B->n_links == 0) {
1.1.1.2   misho     326:            fprintf(f, "<td colspan=\"11\">&#160;</td>\n</tr>\n");
1.1       misho     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
1.1.1.2   misho     333:                    fprintf(f, "<tr>\n");
                    334:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20link\">%s</a></td>\n", 
1.1       misho     335:                    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->name);
1.1.1.2   misho     336:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20lcp\">%s</a></td>\n", 
1.1       misho     337:                    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, FsmStateName(L->lcp.fsm.state));
1.1.1.2   misho     338:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20auth\">%s</a></td>\n", 
1.1       misho     339:                    L->tmpl?"d":FSM_COLOR(L->lcp.fsm.state), L->name, L->lcp.auth.params.authname);
1.1.1.2   misho     340:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     341:                    L->tmpl?"d":PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
1.1.1.2   misho     342:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     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));
1.1.1.2   misho     346:                    fprintf(f, "<td>%s</td>\n", buf);
1.1       misho     347:                    if (L->bund != NULL)
1.1.1.2   misho     348:                        fprintf(f, "<td>%s</td>\n", inet_ntoa(L->bund->ipcp.peer_addr));
1.1       misho     349:                    else
1.1.1.2   misho     350:                        fprintf(f, "<td>&#160;</td>\n");
1.1       misho     351:                    PhysGetCallingNum(L, buf, sizeof(buf));
                    352:                    PhysGetCalledNum(L, buf2, sizeof(buf2));
                    353:                    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
1.1.1.2   misho     354:                            fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
1.1       misho     355:                                buf2, buf);
                    356:                    } else {
1.1.1.2   misho     357:                            fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
1.1       misho     358:                                buf, buf2);
                    359:                    }
                    360:                } else {
1.1.1.2   misho     361:                        fprintf(f, "<td>&#160;</td>\n");
                    362:                        fprintf(f, "<td>&#160;</td>\n");
                    363:                        fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
1.1       misho     364:                }
                    365:                if (priv) {
                    366:                    switch (L->state) {
                    367:                        case PHYS_STATE_DOWN:
1.1.1.2   misho     368:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;open\">[Open]</a></td>\n",
1.1       misho     369:                                L->name);
                    370:                            break;
                    371:                        case PHYS_STATE_UP:
1.1.1.2   misho     372:                            fprintf(f, "<td><a href=\"/cmd?link%%20%s&#38;close\">[Close]</a></td>\n",
1.1       misho     373:                                L->name);
                    374:                            break;
                    375:                        default:
1.1.1.2   misho     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", 
1.1       misho     377:                                L->name, L->name);
                    378:                    }
                    379:                }
1.1.1.2   misho     380:                fprintf(f, "</tr>\n");
1.1       misho     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;
1.1.1.2   misho     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", 
1.1       misho     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)
1.1.1.2   misho     400:                    fprintf(f, "<tr>\n");
                    401:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     402:                    PHYS_COLOR(L->state), L->name, L->name);
1.1.1.2   misho     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", 
1.1       misho     405:                    PHYS_COLOR(L->state), L->name, L->type?L->type->name:"");
1.1.1.2   misho     406:                fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&#38;show%%20device\">%s</a></td>\n", 
1.1       misho     407:                    PHYS_COLOR(L->state), L->name, gPhysStateNames[L->state]);
                    408:                if (L->state != PHYS_STATE_DOWN) {
                    409:                    PhysGetPeerAddr(L, buf, sizeof(buf));
1.1.1.2   misho     410:                    fprintf(f, "<td>%s</td>\n", buf);
1.1       misho     411:                    if (L->bund != NULL)
1.1.1.2   misho     412:                        fprintf(f, "<td>%s</td>\n", inet_ntoa(L->bund->ipcp.peer_addr));
1.1       misho     413:                    else
1.1.1.2   misho     414:                        fprintf(f, "<td>&#160;</td>\n");
1.1       misho     415:                    PhysGetCallingNum(L, buf, sizeof(buf));
                    416:                    PhysGetCalledNum(L, buf2, sizeof(buf2));
                    417:                    if (PhysGetOriginate(L) == LINK_ORIGINATE_REMOTE) {
1.1.1.2   misho     418:                            fprintf(f, "<td>%s</td>\n<td>&#60;=</td>\n<td>%s</td>\n", 
1.1       misho     419:                                buf2, buf);
                    420:                    } else {
1.1.1.2   misho     421:                            fprintf(f, "<td>%s</td>\n<td>=&#62;</td>\n<td>%s</td>\n", 
1.1       misho     422:                                buf, buf2);
                    423:                    }
                    424:                } else {
1.1.1.2   misho     425:                        fprintf(f, "<td>&#160;</td>\n");
                    426:                        fprintf(f, "<td>&#160;</td>\n");
                    427:                        fprintf(f, "<td colspan=\"3\">&#160;</td>\n");
1.1       misho     428:                }
1.1.1.2   misho     429:                fprintf(f, "<td>&#160;</td>\n");
                    430:                fprintf(f, "</tr>\n");
1.1       misho     431:                
                    432:                shown = 1;
                    433:            }
                    434:        }
                    435:        if (!shown) {
1.1.1.2   misho     436:            fprintf(f, "<td colspan=\"11\">&#160;</td>\n");
                    437:            fprintf(f, "</tr>\n");
1.1       misho     438:        }
                    439:     }
                    440:   }
1.1.1.2   misho     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: 
1.1.1.3 ! misho     453:   (void)priv;
1.1.1.2   misho     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: 
1.1.1.3 ! misho     510:        first_l = 1;
1.1.1.2   misho     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: 
1.1.1.3 ! misho     568:        first_l = 1;
1.1.1.2   misho     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");
1.1       misho     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;
1.1.1.3 ! misho     649:        char *av[MAX_CONSOLE_ARGS];
1.1       misho     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;
1.1.1.3 ! misho     660:        rtn = DoCommandTab(&cs->context, gCommands, ac, (const char *const *)av);
1.1       misho     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: 
1.1.1.2   misho     698:     fprintf(f, "<p>\n<a href=\"/\">Back</a>\n</p>\n");
1.1       misho     699: 
                    700:     if (argc == 0) {
1.1.1.2   misho     701:        fprintf(f, "<p>No command cpecified!</p>\n");
1.1       misho     702:        goto done;
                    703:     }
                    704: 
1.1.1.2   misho     705:     fprintf(f, "<pre>\n");
1.1       misho     706:     for (k = 0; k < argc; k++) {
                    707:        int     ac;
1.1.1.3 ! misho     708:        char *av[MAX_CONSOLE_ARGS];
1.1       misho     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);
1.1.1.3 ! misho     722:        DoCommand(&cs->context, ac, (const char *const *)av, NULL, 0);
1.1       misho     723:        Freee(buf1);
                    724:     }
1.1.1.2   misho     725:     fprintf(f, "</pre>\n");
1.1       misho     726: done:
                    727:     Freee(buf);
1.1.1.2   misho     728:     fprintf(f, "<p>\n<a href=\"/\">Back</a>\n</p>\n");
1.1       misho     729:     RESETREF(cs->context.lnk, NULL);
                    730:     RESETREF(cs->context.bund, NULL);
                    731:     RESETREF(cs->context.rep, NULL);
                    732: }
                    733: 
                    734: static void
1.1.1.3 ! misho     735: WebServletRunCleanup(void *cookie) NO_THREAD_SAFETY_ANALYSIS
        !           736: {
        !           737:     (void)cookie;
1.1       misho     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:     
1.1.1.3 ! misho     750:     (void)servlet;
1.1       misho     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);
1.1.1.2   misho     786:     } else if (!strcmp(path,"/bincmd") || !strcmp(path,"/json")) {
1.1       misho     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();
1.1.1.2   misho     793:        
                    794:        if (!strcmp(path,"/bincmd"))
                    795:            WebRunBinCmd(f, query, priv);
                    796:        else if (!strcmp(path,"/json"))
                    797:            WebShowJSONSummary(f, priv);
                    798: 
1.1       misho     799:        GIANT_MUTEX_UNLOCK();
                    800:        pthread_cleanup_pop(0);
1.1.1.2   misho     801: 
1.1       misho     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();
1.1.1.2   misho     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");
1.1       misho     816:     
                    817:        if (!strcmp(path,"/"))
1.1.1.2   misho     818:            WebShowHTMLSummary(f, priv);
1.1       misho     819:        else if (!strcmp(path,"/cmd"))
                    820:            WebRunCmd(f, query, priv);
                    821:            
                    822:        GIANT_MUTEX_UNLOCK();
                    823:        pthread_cleanup_pop(0);
                    824:        
1.1.1.2   misho     825:        fprintf(f, "</body>\n</html>\n");
1.1       misho     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: {
1.1.1.3 ! misho     835:     (void)servlet;
1.1       misho     836: }
                    837: 
                    838: static void
                    839: WebLogger(int sev, const char *fmt, ...)
                    840: {
                    841:   va_list       args;
                    842: 
1.1.1.3 ! misho     843:   (void)sev;
1.1       misho     844:   va_start(args, fmt);
                    845:   vLogPrintf(fmt, args);
                    846:   va_end(args);
                    847: }
                    848: 
                    849: /*
                    850:  * WebSetCommand()
                    851:  */
                    852: 
                    853: static int
1.1.1.3 ! misho     854: WebSetCommand(Context ctx, int ac, const char *const av[], const void *arg) 
1.1       misho     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>