vde_autolink: Add missing null entry in getopt_long array.
[vde.git] / vdetelweb / web.c
blob6b99da52d24f111fce14f5d1e489df044d197e04
1 /*
2 * VDETELWEB: VDE telnet and WEB interface
4 * web.c: http micro server for vde mgmt
5 *
6 * Copyright 2005 Virtual Square Team University of Bologna - Italy
7 * written by Renzo Davoli 2005
8 * management of sha1 Marco Dalla Via 2008
9 * modified by Renzo Davoli 2008
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * $Id$
28 #include <config.h>
29 #include <stdio.h>
30 #define __USE_GNU
31 #include <signal.h>
32 #include <stdarg.h>
33 #include <syslog.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <ctype.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/poll.h>
41 #include <sys/ioctl.h>
42 #include <linux/un.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <string.h>
46 #include <getopt.h>
47 #include "vdetelweb.h"
48 #include <lwipv6.h>
50 #define WEB_TCP_PORT 80
51 #define WEB_IDENTIFY 0x0
52 #define WEB_AUTHORIZED 0x1
53 #define WEB_UNAUTHORIZED 0x2
54 #define WEB_OP_GET 0x0
55 #define WEB_OP_POST 0x1
56 #define WEB_OP_POSTDATA 0x2
58 const char b64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60 //static char *base64passwd;
61 struct webstat {
62 unsigned char status;
63 unsigned char op;
64 unsigned int bodylen;
65 char linebuf[BUFSIZE];
66 char path[BUFSIZE];
67 int bufindex;
70 static void lowercase(char *s)
72 while (*s != 0) {
73 *s = tolower(*s);
74 s++;
78 void encode64(const char *from, char *to, int tosize) {
80 int convbuf;
81 int n = strlen(from);
83 while ((n > 0) && (tosize > 3)) {
85 convbuf = *from;
86 from++;
87 n--;
88 convbuf <<= 8;
89 if (n > 0)
90 convbuf |= *from;
91 from++;
92 n--;
93 convbuf <<= 8;
94 if (n > 0)
95 convbuf |= *from;
96 from++;
97 n--;
98 *(to++) = b64_chars[convbuf >> 18];
99 *(to++) = b64_chars[(convbuf >> 12) & 0x3f];
100 *(to++) = (n < -1) ? '=' : b64_chars[(convbuf >> 6) & 0x3f];
101 *(to++) = (n < 0) ? '=' : b64_chars[convbuf & 0x3f];
102 tosize -= 4;
104 *to = 0;
107 void decode64(const char *src, char *dest, int dest_size) {
109 int convbuf;
110 int l = strlen(src);
111 char c_src[l];
112 char *c;
114 int i, j;
116 strcpy(c_src, src);
118 /* Sostitute '=' (paddings) with 0 ['A'] */
119 while ((c = strchr(c_src, '=')) != NULL)
120 *c = 'A';
122 /* Convert 4 byte in 6 bit (64) to 3 byte in 8 bit */
123 for (i = 0, j = 0; i < l; i += 4, j += 3) {
125 convbuf = (((int)(strchr(b64_chars, c_src[i]) - b64_chars) << 18) +
126 ((int)(strchr(b64_chars, c_src[i + 1]) - b64_chars) << 12) +
127 ((int)(strchr(b64_chars, c_src[i + 2]) - b64_chars) << 6) +
128 ((int)(strchr(b64_chars, c_src[i + 3]) - b64_chars)));
129 dest[j] = ((convbuf >> 16) & 255);
130 dest[j + 1] = ((convbuf >> 8) & 255);
131 dest[j + 2] = ((convbuf & 255));
134 dest[j] = '\0';
137 #if 0
138 static void createbase64passwd()
140 char buf[BUFSIZE];
141 char buf64[BUFSIZE*4/3];
142 snprintf(buf,BUFSIZE,"admin:%s",passwd);
143 encode64(buf,buf64,BUFSIZE*4/3);
144 base64passwd=strdup(buf64);
146 #endif
148 static void lwip_printf(int fd, const char *format, ...)
150 char outbuf[BUFSIZE];
151 va_list arg;
152 va_start (arg, format);
153 vsnprintf(outbuf,BUFSIZE,format,arg);
154 lwip_write(fd,outbuf,strlen(outbuf));
157 static void web_close(int fn,int fd)
159 //printf("web_close %d %d\n",fn,fd);
160 free(status[fn]);
161 delpfd(fn);
162 lwip_close(fd);
165 static int vde_getanswer(voidfun f,void *arg,int vdefd)
167 char buf[BUFSIZE];
168 char linebuf[BUFSIZE+1];
169 int n=0,ib=0,il=0,indata=0,eoa=0;
170 do {
171 n=read(vdefd,buf,BUFSIZE);
172 if (n==0)
173 exit(0);
174 for(ib=0;ib<n;ib++)
176 linebuf[il++]=buf[ib];
177 if (buf[ib] == '\n') {
178 linebuf[il-1]='\r';
179 linebuf[il]='\n';
180 linebuf[il+1]=0;
181 il++;
182 if (indata) {
183 if (linebuf[0]=='.' && linebuf[1]=='\r')
184 indata=0;
185 else
186 f(arg,linebuf,il,indata,0);
187 } else if (strncmp(linebuf,"0000",4)==0)
188 indata=1;
189 else {
190 if(linebuf[0]=='1' &&
191 linebuf[1] >= '0' && linebuf[1] <= '9' &&
192 linebuf[2] >= '0' && linebuf[2] <= '9' &&
193 linebuf[3] >= '0' && linebuf[3] <= '9') {
194 f(arg,linebuf+5,il-5,0,atoi(linebuf));
195 eoa=atoi(linebuf);
198 il=0;
201 } while (!eoa);
202 return(eoa);
205 struct vdesub {
206 char *name;
207 char *descr;
208 char *syntax;
209 struct vdesub *next;
212 struct vdemenu {
213 char *name;
214 char *descr;
215 struct vdesub *sub;
216 struct vdemenu *next;
219 static struct vdemenu *menuhead;
221 static struct vdemenu *vde_findmenu(struct vdemenu *head,char *name)
223 if (head == NULL)
224 return NULL;
225 else
226 if (strcmp(head->name,name)==0)
227 return head;
228 else
229 return vde_findmenu(head->next,name);
232 static void vde_addsub(struct vdesub **headp,char *name,char *syntax,char *help)
234 if (*headp == NULL) {
235 *headp=malloc(sizeof(struct vdesub));
236 if (*headp != NULL) {
237 (*headp)->name=name;
238 (*headp)->descr=help;
239 (*headp)->syntax=syntax;
240 (*headp)->next=NULL;
242 } else
243 vde_addsub(&((*headp)->next),name,syntax,help);
246 static void vde_addcmd(struct vdemenu *head,char *menu,char *name,char *syntax,char *help)
248 if (head != NULL) {
249 if (strcmp(head->name,menu) == 0)
250 vde_addsub(&(head->sub),name,syntax,help);
251 else
252 vde_addcmd(head->next,menu,name,syntax,help);
256 static void vde_addmenu(struct vdemenu **headp,char *name,char *help)
258 if (*headp == NULL) {
259 *headp=malloc(sizeof(struct vdemenu));
260 if (*headp != NULL) {
261 (*headp)->name=name;
262 (*headp)->descr=help;
263 (*headp)->sub=NULL;
264 (*headp)->next=NULL;
266 } else
267 vde_addmenu(&((*headp)->next),name,help);
270 static void vde_helpline(struct vdemenu **headp,char *buf,int len,int indata,int rv)
272 static int nl=0;
273 static int syntaxpos,helppos;
274 nl++;
275 if (nl==2) {
276 int i;
277 for (i=0;i<len && buf[i]=='-';i++) ;
278 for (;i<len && buf[i]==' ';i++) ;
279 syntaxpos=i;
280 for (;i<len && buf[i]=='-';i++) ;
281 for (;i<len && buf[i]==' ';i++) ;
282 helppos=i;
284 else if (nl > 2 && indata && (strncmp(buf,"debug",5) !=0 )) {
285 char *name;
286 char *syntax;
287 char *help;
288 int namelen;
289 for (namelen=0;namelen<syntaxpos && buf[namelen]!=' ';namelen++) ;
290 if (strncmp(buf+syntaxpos,"======",5) ==0) {
291 /* MENU */
292 name=strndup(buf,namelen);
293 help=strndup(buf+helppos,len-helppos-2);
294 vde_addmenu(headp,name,help);
295 } else {
296 int slash;
297 for (slash=0;slash<namelen && buf[slash]!='/';slash++) ;
298 if (slash<namelen) {
299 int synlen;
300 buf[slash]=0;slash++;
301 namelen-=slash;
302 for (synlen=helppos-syntaxpos; synlen>0 && buf[syntaxpos+synlen-1]==' ';synlen--) ;
303 name=strndup(buf+slash,namelen);
304 if (synlen>0)
305 syntax=strndup(buf+syntaxpos,synlen);
306 else
307 syntax="";
308 help=strndup(buf+helppos,len-helppos-2);
309 vde_addcmd(*headp,buf,name,syntax,help);
315 static struct vdemenu *vde_gethelp(int vdefd)
317 struct vdemenu *head=NULL;
318 write(vdefd,"help\n",5);
319 vde_getanswer(vde_helpline,&head,vdefd);
320 return head;
323 static void lwip_showline(int *fdp,char *buf,int len,int indata,int rv)
325 if (indata)
326 lwip_write(*fdp,buf,len);
329 static int lwip_showout(int fd, int vdefd)
331 return vde_getanswer(lwip_showline,&fd,vdefd);
334 static int hex2num(int c)
336 if (c>96) c-=32;
337 c -='0';
338 if (c>9)
339 c-=7;
340 return c;
343 static char *uriconv(char *in)
345 char *s=in;
346 char *t=in;
347 while ((*t=*s) != 0) {
348 if (*s=='+')
349 *t=' ';
350 if (*s=='%') {
351 *t=(hex2num(*(s+1))<<4)+hex2num(*(s+2));
352 s+=2;
354 s++;t++;
356 return in;
359 static void postdata_parse(int fd,int vdefd,char *menu,char *postdata)
361 char cmdbuf[BUFSIZE];
362 int cmdlen,arglen,rv;
363 char *postcmd,*cmd,*endcmd,*arg=NULL;
364 /*printf("PD **%s**\n",postdata);*/
365 if ((postcmd=strstr(postdata,"X="))!=NULL) {
366 /* enter in a text field (catched through the hidden button) */
367 cmd=NULL;
368 while(postdata)
370 char *token=strsep(&postdata,"&");
371 int l=strlen(token);
372 char *targ=index(token,'=');
373 if(strncmp("X=",token,2) != 0) {
374 if (targ+1 < token+l) {
375 if(cmd==NULL) {
376 char *point;
377 if ((point=strstr(token,".arg")) != NULL)
378 *point=0;
379 cmd=token;
380 arg=targ+1;
381 } else
382 cmd="";
386 if(cmd!=NULL && *cmd != 0) {
387 strncpy(cmdbuf,menu,BUFSIZE);
388 strncat(cmdbuf,"/",BUFSIZE);
389 strncat(cmdbuf,cmd,BUFSIZE);
390 strncat(cmdbuf," ",BUFSIZE);
391 strncat(cmdbuf,uriconv(arg),BUFSIZE);
392 write(vdefd,cmdbuf,strlen(cmdbuf));
393 lwip_printf(fd,"<P> </P><B>%s %s</B><PRE>",prompt,cmdbuf);
394 rv=lwip_showout(fd,vdefd);
395 lwip_printf(fd,"</PRE><B>Result: %s</B>\r\n",strerror(rv-1000));
398 else if ((postcmd=strstr(postdata,"COMMAND="))!=NULL) {
399 /* accept button */
400 postcmd+=8;
401 for(cmdlen=0;postcmd[cmdlen] != '&' && postcmd[cmdlen] != 0; cmdlen++)
403 strncpy(cmdbuf,menu,BUFSIZE);
404 strncat(cmdbuf,"/",BUFSIZE);
405 cmd=cmdbuf+strlen(cmdbuf);
406 strncat(cmdbuf,postcmd,(BUFSIZE<cmdlen)?BUFSIZE:cmdlen);
407 endcmd=cmdbuf+strlen(cmdbuf);
408 strncat(cmdbuf,".arg",BUFSIZE);
409 if ((arg=strstr(postdata,cmd))!=NULL) {
410 arg+=strlen(cmd)+1;
411 for(arglen=0;arg[arglen] != '&' && arg[arglen] != 0; arglen++)
413 arg[arglen]=0;
414 *endcmd=0;
415 if (*arg != 0) {
416 strncat(cmdbuf," ",BUFSIZE);
417 strncat(cmdbuf,uriconv(arg),BUFSIZE);
419 } else
420 *endcmd=0;
421 write(vdefd,cmdbuf,strlen(cmdbuf));
422 lwip_printf(fd,"<P> </P><B>%s %s</B><PRE>",prompt,cmdbuf);
423 rv=lwip_showout(fd,vdefd);
424 lwip_printf(fd,"</PRE><B>Result: %s</B>\r\n",strerror(rv-1000));
428 static char css[]=
429 "<style type=\"text/CSS\"\r\n"
430 "<!--\r\n"
431 ".core {\r\n"
432 "font-family: Helvetica;\r\n"
433 "color: #0000FF;\r\n"
434 "background-color: #FFFFFF;\r\n"
435 "text-align: justify;\r\n"
436 "margin-left: 5pt;\r\n"
437 "margin-top: 5pt;\r\n"
438 "margin-right: 5pt;\r\n"
439 "margin-bottom: 5pt;\r\n"
440 "}\r\n"
441 ".sidebar {\r\n"
442 "font-family: Helvetica;\r\n"
443 "font-size: 12px;\r\n"
444 "color: #ff0000;\r\n"
445 "}\r\n"
446 "-->\r\n"
447 "</style>\r\n";
449 static char okmsg[]=
450 "HTTP/1.1 200 OK\r\n"
451 "Content-Type: text/html\r\n"
452 "\r\n";
454 static char errmsg[]=
455 "HTTP/1.1 404 Not Found\r\n"
456 "Content-Type: text/html\r\n"
457 "\r\n"
458 "<HTML><HEAD>\r\n"
459 "<TITLE>404 Not Found</TITLE>\r\n"
460 "</HEAD><BODY>\r\n"
461 "<H1>Not Found</H1>\r\n"
462 "The requested URL was not found on this server.\r\n"
463 "<hr>VDE 2.0 WEB MGMT INTERFACE\r\n"
464 "</BODY></HTML>\r\n";
466 static void web_this_form(int fd,struct vdemenu *this)
468 struct vdesub *sub;
469 for (sub=this->sub;sub!=NULL;sub=sub->next) {
470 if (*(sub->syntax) == 0) {
471 lwip_printf(fd,
472 "<TR><TD width=50><INPUT type=submit size=100 name=\"%s\" value=\"%s\"></TD>\r\n"
473 "<TD width=100></TD>\r\n"
474 "<TD width=100></TD>\r\n"
475 "<TD width=300>%s</TD></TR>\r\n",
476 "COMMAND",sub->name,sub->descr);
477 } else {
478 lwip_printf(fd,
479 "<TR><TD width=50><INPUT type=submit size=100 name=\"%s\" value=\"%s\"></TD>\r\n"
480 "<TD width=100>%s</TD>\r\n"
481 "<TD width=100><INPUT type=text name=\"%s.arg\"></TD>\r\n"
482 "<TD width=300>%s</TD></TR>\r\n",
483 "COMMAND",sub->name,sub->syntax,sub->name,sub->descr);
488 static void web_menu_index(int fd)
490 struct vdemenu *this;
491 lwip_printf(fd,"<P><A HREF=\"index.html\">Home Page</A></P>\r\n");
492 for (this=menuhead;this!=NULL;this=this->next)
493 lwip_printf(fd,"<P><A HREF=\"%s.html\">%s</A></P>\r\n",this->name,this->name);
496 static void web_create_page(char *path,int fd,int vdefd,char *postdata)
498 struct vdemenu *this=NULL;
499 char *tail;
500 if ((tail=strstr(path,".html")) != NULL)
501 *tail=0;
502 if (*path==0 || ((this=vde_findmenu(menuhead,path)) != NULL)) {
503 lwip_write(fd,okmsg,sizeof(okmsg)-1);
504 lwip_printf(fd,
505 "<HTML><HEAD>\r\n"
506 "<TITLE>%s %s</TITLE>\r\n",
507 prompt, (*path==0)?"Home Page":path);
508 lwip_write(fd,css,sizeof(css)-1);
509 lwip_printf(fd,
510 "</HEAD><BODY class=core>\r\n"
511 "<H1>%s %s</H1>\r\n"
512 "<TABLE BORDER=0><TD width=80 bgcolor=#aacbff valign=top class=sidebar>",
513 prompt, (*path==0)?"Home Page":this->descr);
514 web_menu_index(fd);
515 if (*path==0) {/* HOME PAGE */
516 int rv;
517 write(vdefd,"showinfo\r\n",10);
518 lwip_printf(fd,
519 "</TD><TD><PRE>\r\n");
520 rv=lwip_showout(fd,vdefd);
521 lwip_printf(fd,"</PRE>\r\n");
522 if (rv != 1000)
523 lwip_printf(fd,"<B>%s</B>\r\n",strerror(rv-1000));
524 } else {
525 lwip_printf(fd,
526 "</TD><TD><FORM action=\"%s.html\" method=post table-layout=fixed>\r\n<TABLE><THEAD><TR>\r\n"
527 "<TD><INPUT type=submit name=X style=\"visibility:hidden\" ></TD>\r\n"
528 "<TD><B>Syntax</B></TD><TD><B>Args</B>\r\n"
529 "</TD><TD><B>Description</B></TD></TR></THEAD>\r\n",path);
530 web_this_form(fd,this);
531 lwip_printf(fd,"</TABLE></FORM>\r\n");
532 if (postdata != NULL) {
533 postdata_parse(fd,vdefd,path,postdata);
536 lwip_printf(fd,
537 "</TD></TABLE>\r\n"
538 "<hr>VDE 2.0 WEB MGMT INTERFACE\r\n"
539 "</BODY></HTML>\r\n");
540 } else
541 lwip_write(fd,errmsg,sizeof(errmsg)-1);
544 static char authmsg[]=
545 "HTTP/1.1 401 Authorization Required\r\n"
546 "WWW-Authenticate: Basic realm=\"";
548 //"Content-Length: 187\r\n"
549 //"Connection: close\r\n"
550 static char authmsg2[]= "\"\r\n"
551 "Content-Type: text/html\r\n"
552 "\r\n"
553 "<HTML><HEAD>\r\n"
554 "<TITLE>401 Authorization Required</TITLE>\r\n"
555 "</HEAD><BODY>\r\n"
556 "<H1>Authorization Required</H1>\r\n"
557 "Login and Password required\r\n"
558 "<hr>\r\nVDE 2.0 WEB MGMT INTERFACE\r\n"
559 "</BODY></HTML>\r\n";
562 int web_core(int fn,int fd,int vdefd)
564 struct webstat *st=status[fn];
565 //printf("CORE %s\n",st->linebuf);
566 if (st->op==WEB_OP_POSTDATA) {
567 //printf("POSTDATA %s\n",st->linebuf);
568 web_create_page(&(st->path[1]),fd,vdefd,st->linebuf);
569 return 1;
570 } else if (strncmp(st->linebuf,"GET",3) == 0) {
571 //printf("GET %s\n",st->linebuf);
572 sscanf(st->linebuf+4,"%s",st->path);
573 st->op=WEB_OP_GET;
574 return 0;
575 } else if (strncmp(st->linebuf,"POST",3) == 0) {
576 //printf("POST %s\n",st->linebuf);
577 sscanf(st->linebuf+5,"%s",st->path);
578 st->op=WEB_OP_POST;
579 return 0;
580 } else if (strncmp(st->linebuf,"Content-Length: ",16) == 0) {
581 st->bodylen=atoi(st->linebuf+16);
582 //printf("BODYLEN %d\n",st->bodylen);
583 return 0;
584 } else if (strncmp(st->linebuf,"Authorization: Basic",20) == 0) {
585 char passwd_buf[BUFSIZE];
586 char *passwd_buf_shift;
587 int len=strlen(st->linebuf);
588 int k=20;
589 while (st->linebuf[k] == ' ') k++;
590 while (st->linebuf[len-1] == '\n' ||
591 st->linebuf[len-1] == '\r' ||
592 st->linebuf[len-1] == ' ') {
593 len--;
594 st->linebuf[len]=0;
596 /* SHA1 */
597 decode64((st->linebuf + k), passwd_buf, strlen(st->linebuf + k));
598 passwd_buf_shift = (char *)(strchr(passwd_buf, ':') + 1);
599 if (sha1passwdok(passwd_buf_shift))
600 st->status=WEB_AUTHORIZED;
601 return 0;
602 } else if (st->linebuf[0]=='\n' || st->linebuf[0]=='\r') {
603 switch (st->status) {
604 case WEB_IDENTIFY:
605 lwip_write(fd,authmsg,sizeof(authmsg)-1);
606 lwip_write(fd,prompt,strlen(prompt));
607 lwip_write(fd,authmsg2,sizeof(authmsg2)-1);
608 return 1;
609 break;
610 case WEB_AUTHORIZED:
611 lowercase(st->path);
612 if (strcmp(st->path,"/index.html") == 0)
613 st->path[1]=0;
614 if (st->op == WEB_OP_GET) {
615 web_create_page(&(st->path[1]),fd,vdefd,NULL);
616 return 1;
617 } else {
618 st->op=WEB_OP_POSTDATA;
619 return 0;
621 default:
622 return 0;
624 } else
625 return 0;
628 void webdata(int fn,int fd,int vdefd)
630 char buf[BUFSIZE];
631 int n,i;
632 struct webstat *st=status[fn];
633 n=lwip_read(fd,buf,BUFSIZE);
634 if (n==0) {
635 web_close(fn,fd);
637 else if (n<0)
638 printlog(LOG_ERR,"web read err: %s",strerror(errno));
639 else {
640 for (i=0;i<n && st->bufindex<BUFSIZE;i++) {
641 st->linebuf[(st->bufindex)++]=buf[i];
642 if (buf[i]=='\n' || (st->op==WEB_OP_POSTDATA && st->bufindex==st->bodylen)) {
643 st->linebuf[(st->bufindex)]=0;
644 if (web_core(fn,fd,vdefd)) {
645 web_close(fn,fd);
646 break;
647 } else
648 st->bufindex=0;
654 void webaccept(int fn,int fd,int vdefd)
656 struct sockaddr_in cli_addr;
657 int newsockfd;
658 unsigned int clilen;
659 struct webstat *st;
660 int newfn;
662 clilen = sizeof(cli_addr);
663 newsockfd = lwip_accept(fd, (struct sockaddr *) &cli_addr, &clilen);
665 if (newsockfd < 0) {
666 printlog(LOG_ERR,"web accept err: %s",strerror(errno));
669 newfn=addpfd(newsockfd,webdata);
670 status[newfn]=st=malloc(sizeof(struct webstat));
671 st->status=WEB_IDENTIFY;
672 st->op=0;
673 st->bufindex=0;
676 void web_init(int vdefd)
678 int sockfd;
679 struct sockaddr_in serv_addr;
680 sockfd=lwip_socket(AF_INET, SOCK_STREAM, 0);
682 if (!sockfd) {
683 printlog(LOG_ERR,"web socket err: %s",strerror(errno));
686 bzero((char *) &serv_addr, sizeof(serv_addr));
687 serv_addr.sin_family = AF_INET;
688 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
689 serv_addr.sin_port = htons(WEB_TCP_PORT);
691 if (lwip_bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
692 printlog(LOG_ERR,"web bind err: %s",strerror(errno));
695 lwip_listen(sockfd, 5);
697 //createbase64passwd();
698 menuhead=vde_gethelp(vdefd);
699 addpfd(sockfd,webaccept);