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> </th>\n<th> </th>\n<th> </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\"> </td>\n");
256: fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&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&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&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&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&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> </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><=</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>=></td>\n<td>%s</td>\n",
1.1 misho 277: buf, buf2);
278: }
279: } else {
1.1.1.2 misho 280: fprintf(f, "<td> </td>\n");
281: fprintf(f, "<td> </td>\n");
282: fprintf(f, "<td colspan=\"3\"> </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&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&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&open\">[Open]</a> <a href=\"/cmd?link%%20%s&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> </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&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&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&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&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&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&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&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\"> </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&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&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&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&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&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> </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><=</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>=></td>\n<td>%s</td>\n",
1.1 misho 358: buf, buf2);
359: }
360: } else {
1.1.1.2 misho 361: fprintf(f, "<td> </td>\n");
362: fprintf(f, "<td> </td>\n");
363: fprintf(f, "<td colspan=\"3\"> </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&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&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&open\">[Open]</a> <a href=\"/cmd?link%%20%s&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&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&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\"> </td>\n");
404: fprintf(f, "<td class=\"%s\"><a href=\"/cmd?link%%20%s&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&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> </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><=</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>=></td>\n<td>%s</td>\n",
1.1 misho 422: buf, buf2);
423: }
424: } else {
1.1.1.2 misho 425: fprintf(f, "<td> </td>\n");
426: fprintf(f, "<td> </td>\n");
427: fprintf(f, "<td colspan=\"3\"> </td>\n");
1.1 misho 428: }
1.1.1.2 misho 429: fprintf(f, "<td> </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\"> </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>