1/* milli_httpd - pretty small HTTP server 2** A combination of 3** micro_httpd - really small HTTP server 4** and 5** mini_httpd - small HTTP server 6** 7** Copyright ?1999,2000 by Jef Poskanzer <jef@acme.com>. 8** All rights reserved. 9** 10** Redistribution and use in source and binary forms, with or without 11** modification, are permitted provided that the following conditions 12** are met: 13** 1. Redistributions of source code must retain the above copyright 14** notice, this list of conditions and the following disclaimer. 15** 2. Redistributions in binary form must reproduce the above copyright 16** notice, this list of conditions and the following disclaimer in the 17** documentation and/or other materials provided with the distribution. 18** 19** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29** SUCH DAMAGE. 30*/ 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <errno.h> 36#include <fcntl.h> 37#include <time.h> 38#include <unistd.h> 39#include <netinet/in.h> 40#include <sys/types.h> 41#include <sys/socket.h> 42#include <arpa/inet.h> // 2008.01 James. 43#include <sys/time.h> 44#include <assert.h> 45//#include <etioctl.h> 46 47#include <httpd.h> 48#include <bcmnvram.h> // 2007.12 James. 49#include "shutils.h" 50 51#ifdef vxworks 52static void fcntl(int a, int b, int c) {} 53#include <signal.h> 54#include <ioLib.h> 55#include <sockLib.h> 56extern int snprintf(char *str, size_t count, const char *fmt, ...); 57extern int strcasecmp(const char *s1, const char *s2); 58extern int strncasecmp(const char *s1, const char *s2, size_t n); 59extern char *strsep(char **stringp, char *delim); 60#define socklen_t int 61#define main milli 62#else 63#include <error.h> 64#include <sys/signal.h> 65#endif 66 67// Added by Joey for ethtool 68#include <net/if.h> 69#include "ethtool-util.h" 70#ifndef SIOCETHTOOL 71#define SIOCETHTOOL 0x8946 72#endif 73 74#define SIOCDEVPRIVATE 0x89F0 75#define ETCPHYRD 14 76//#define SIOCGETCPHYRD (SIOCDEVPRIVATE + ETCPHYRD) 77#define SIOCGETCPHYRD 0x89FE 78//#include "etioctl.h" 79 80#define SERVER_NAME "httpd" 81#define SERVER_PORT 80 82#define PROTOCOL "HTTP/1.0" 83#define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT" 84 85/* A multi-family sockaddr. */ 86typedef union { 87 struct sockaddr sa; 88 struct sockaddr_in sa_in; 89} usockaddr; 90 91/* Globals. */ 92int conn_fd; 93FILE *conn_fp; 94static char auth_userid[AUTH_MAX]; 95static char auth_passwd[AUTH_MAX]; 96static char auth_realm[AUTH_MAX]; 97#ifdef TRANSLATE_ON_FLY 98char Accept_Language[16]; 99#endif //TRANSLATE_ON_FLY 100 101// 2009.05 James. { 102#ifdef DLM 103#include <disk_initial.h> 104 105disk_info_t *DISKS_INFO = NULL; 106#endif 107// 2009.05 James. } 108 109/* Forwards. */ 110void http_login_timeout(unsigned int ip); 111void http_login(unsigned int ip, char *url); 112void http_logout(unsigned int ip); 113 114static int initialize_listen_socket( usockaddr* usaP ); 115static int auth_check( char* dirname, char* authorization, char* url ); 116static void send_authenticate( char* realm ); 117static void send_error( int status, char* title, char* extra_header, char* text ); 118static void send_headers( int status, char* title, char* extra_header, char* mime_type ); 119static int b64_decode( const char* str, unsigned char* space, int size ); 120static int match( const char* pattern, const char* string ); 121static int match_one( const char* pattern, int patternlen, const char* string ); 122static void handle_request(void); 123 124/* added by Joey */ 125//int redirect = 1; 126int redirect = 0; // 2008.01 James. 127int change_passwd = 0; // 2008.03 James. 128int reget_passwd = 0; // 2008.03 James. 129char url[4096]; 130char wan_if[16]; 131int http_port=SERVER_PORT; 132 133/* Added by Joey for handle one people at the same time */ 134unsigned int login_ip = 0; // the logined ip 135time_t login_timestamp = 0; // the timestamp of the logined ip 136unsigned int login_ip_tmp = 0; // the ip of the current session. 137unsigned int last_login_ip = 0; // the last logined ip 138 139// 2007.11 James { 140time_t request_timestamp = 0; 141time_t turn_off_auth_timestamp = 0; 142int temp_turn_off_auth = 0; // for QISxxx.htm pages 143// 2007.11 James } 144 145static int 146initialize_listen_socket( usockaddr* usaP ) 147 { 148 int listen_fd; 149 int i; 150 151 memset( usaP, 0, sizeof(usockaddr) ); 152 usaP->sa.sa_family = AF_INET; 153 usaP->sa_in.sin_addr.s_addr = htonl( INADDR_ANY ); 154 usaP->sa_in.sin_port = htons( http_port ); 155 156 listen_fd = socket( usaP->sa.sa_family, SOCK_STREAM, 0 ); 157 if ( listen_fd < 0 ) 158 { 159 perror( "socket" ); 160 return -1; 161 } 162 (void) fcntl( listen_fd, F_SETFD, 1 ); 163 i = 1; 164 if ( setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &i, sizeof(i) ) < 0 ) 165 { 166 perror( "setsockopt" ); 167 return -1; 168 } 169 if ( bind( listen_fd, &usaP->sa, sizeof(struct sockaddr_in) ) < 0 ) 170 { 171 perror( "bind" ); 172 return -1; 173 } 174 if ( listen( listen_fd, 1024 ) < 0 ) 175 { 176 perror( "listen" ); 177 return -1; 178 } 179 return listen_fd; 180 } 181 182 183static int 184auth_check( char* dirname, char* authorization, char* url ) 185{ 186 char authinfo[500]; 187 char* authpass; 188 int l; 189 190 /* Is this directory unprotected? */ 191 if ( !strlen(auth_passwd) ){ 192 /* Yes, let the request go through. */ 193 return 1; 194 } 195 196 /* Basic authorization info? */ 197 if (!authorization || strncmp( authorization, "Basic ", 6 ) != 0) 198 { 199 printf("### No authorization in http request with %s! ###\n", url); 200 send_authenticate(dirname); 201 if(login_ip != 0) // 2007.11 James 202 http_logout(login_ip_tmp); 203 204 last_login_ip = 0; // 2007.11 James 205 206 return 0; 207 } 208 209 /* Decode it. */ 210 l = b64_decode( &(authorization[6]), authinfo, sizeof(authinfo) ); 211 authinfo[l] = '\0'; 212 213 /* Split into user and password. */ 214 authpass = strchr( authinfo, ':' ); 215 if ( authpass == (char*) 0 ) { 216 /* No colon? Bogus auth info. */ 217 printf("### No password information in http request! ###\n"); 218 send_authenticate(dirname); 219 http_logout(login_ip_tmp); 220 221 return 0; 222 } 223 *authpass++ = '\0'; 224 225 /* Is this the right user and password? */ 226 if ( !strcmp( auth_userid, authinfo ) && !strcmp( auth_passwd, authpass )) 227 { 228 /* Is this the first login after logout */ 229 if (login_ip == 0 && last_login_ip == login_ip_tmp) 230 { 231 printf("### After logout, The first login ip is the last login ip! ###\n"); 232 send_authenticate(dirname); 233 234 last_login_ip = 0; 235 236 return 0; 237 } 238 239 return 1; 240 } 241 242 printf("### userid or password is wrong! ###\n"); 243 send_authenticate(dirname); 244 http_logout(login_ip_tmp); 245 246 return 0; 247} 248 249static void 250send_authenticate(char* realm) 251{ 252 char header[10000]; 253 254 if(!strcmp(realm, "WL500gpv2")) 255 (void)snprintf(header, sizeof(header), "WWW-Authenticate: Basic realm=\"%s\"", "WL-500gP V2"); 256 else if(!strcmp(realm, "WL520gu")) 257 (void)snprintf(header, sizeof(header), "WWW-Authenticate: Basic realm=\"%s\"", "WL-520GU"); 258 else 259 (void)snprintf(header, sizeof(header), "WWW-Authenticate: Basic realm=\"%s\"", realm); 260 261 send_error(401, "Unauthorized", header, "Authorization required."); 262} 263 264static void 265send_error(int status, char* title, char* extra_header, char* text) 266{ 267 send_headers(status, title, extra_header, "text/html"); 268 (void)fprintf(conn_fp, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H4>%d %s</H4>\n", status, title, status, title); 269 (void)fprintf(conn_fp, "%s\n", text); 270 (void)fprintf(conn_fp, "</BODY></HTML>\n"); 271 (void)fflush(conn_fp); 272} 273 274static void 275send_headers(int status, char* title, char* extra_header, char* mime_type) 276{ 277 time_t now; 278 char timebuf[100]; 279 280 (void)fprintf(conn_fp, "%s %d %s\r\n", PROTOCOL, status, title); 281 (void)fprintf(conn_fp, "Server: %s\r\n", SERVER_NAME); 282 now = time((time_t*)0); 283 (void)strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime( &now )); 284 (void)fprintf(conn_fp, "Date: %s\r\n", timebuf); 285 286 if(extra_header != (char*)0) 287 (void)fprintf(conn_fp, "%s\r\n", extra_header); 288 289 if(mime_type != (char*)0) 290 (void)fprintf(conn_fp, "Content-Type: %s\r\n", mime_type); 291 292 (void)fprintf(conn_fp, "Connection: close\r\n"); 293 (void)fprintf(conn_fp, "\r\n"); 294} 295 296/* Base-64 decoding. This represents binary data as printable ASCII 297** characters. Three 8-bit binary bytes are turned into four 6-bit 298** values, like so: 299** 300** [11111111] [22222222] [33333333] 301** 302** [111111] [112222] [222233] [333333] 303** 304** Then the 6-bit values are represented using the characters "A-Za-z0-9+/". 305*/ 306 307static int b64_decode_table[256] = { 308 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */ 309 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */ 310 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */ 311 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */ 312 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */ 313 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */ 314 -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */ 315 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */ 316 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */ 317 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */ 318 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */ 319 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */ 320 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */ 321 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */ 322 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */ 323 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */ 324 }; 325 326/* Do base-64 decoding on a string. Ignore any non-base64 bytes. 327** Return the actual number of bytes generated. The decoded size will 328** be at most 3/4 the size of the encoded, and may be smaller if there 329** are padding characters (blanks, newlines). 330*/ 331static int 332b64_decode( const char* str, unsigned char* space, int size ) 333 { 334 const char* cp; 335 int space_idx, phase; 336 int d, prev_d=0; 337 unsigned char c; 338 339 space_idx = 0; 340 phase = 0; 341 for ( cp = str; *cp != '\0'; ++cp ) 342 { 343 d = b64_decode_table[(int)*cp]; 344 if ( d != -1 ) 345 { 346 switch ( phase ) 347 { 348 case 0: 349 ++phase; 350 break; 351 case 1: 352 c = ( ( prev_d << 2 ) | ( ( d & 0x30 ) >> 4 ) ); 353 if ( space_idx < size ) 354 space[space_idx++] = c; 355 ++phase; 356 break; 357 case 2: 358 c = ( ( ( prev_d & 0xf ) << 4 ) | ( ( d & 0x3c ) >> 2 ) ); 359 if ( space_idx < size ) 360 space[space_idx++] = c; 361 ++phase; 362 break; 363 case 3: 364 c = ( ( ( prev_d & 0x03 ) << 6 ) | d ); 365 if ( space_idx < size ) 366 space[space_idx++] = c; 367 phase = 0; 368 break; 369 } 370 prev_d = d; 371 } 372 } 373 return space_idx; 374 } 375 376 377/* Simple shell-style filename matcher. Only does ? * and **, and multiple 378** patterns separated by |. Returns 1 or 0. 379*/ 380static int match(const char* pattern, const char* string){ 381 const char* or; 382 383 for(;;){ 384 or = strchr(pattern, '|'); 385 if(or == (char*)0) 386 return match_one(pattern, strlen(pattern), string); 387 388 if(match_one(pattern, or-pattern, string)) 389 return 1; 390 391 pattern = or+1; 392 } 393} 394 395static int match_one(const char* pattern, int patternlen, const char* string){ 396 const char* p; 397 398 for(p = pattern; p-pattern < patternlen; ++p, ++string){ 399 if(*p == '?' && *string != '\0') 400 continue; 401 402 if(*p == '*'){ 403 int i, pl; 404 405 ++p; 406 if(*p == '*'){ 407 /* Double-wildcard matches anything. */ 408 ++p; 409 i = strlen(string); 410 } 411 else 412 /* Single-wildcard matches anything but slash. */ 413 i = strcspn(string, "/"); 414 415 pl = patternlen-(p-pattern); 416 for(; i >= 0; --i) 417 if(match_one(p, pl, &(string[i]))) 418 return 1; 419 420 return 0; 421 } 422 423 if(*p != *string) 424 return 0; 425 } 426 427 if(*string == '\0') 428 return 1; 429 430 return 0; 431} 432 433void 434do_file(char *path, FILE *stream) 435{ 436 FILE *fp; 437 int c; 438 439 if (!(fp = fopen(path, "r"))) 440 return; 441 while ((c = getc(fp)) != EOF) 442 fputc(c, stream); 443 fclose(fp); 444} 445 446 447static void 448handle_request(void) 449{ 450 char line[10000], *cur; 451 char *method, *path, *protocol, *authorization, *boundary, *alang; 452 char *cp; 453 char *file; 454 int len; 455 struct mime_handler *handler; 456 int cl = 0, flags; 457 //int notfirstSetting = (int)strtol(nvram_safe_get("x_Setting"), NULL, 10); 458 int firstSetting = is_firsttime(); // 2009.06 James. 459 int changed_http_passwd = (int)strtol(nvram_safe_get("changed_http_passwd"), NULL, 10); 460 461 /* Initialize the request variables. */ 462 authorization = boundary = NULL; 463 bzero( line, sizeof line ); 464 465 /* Parse the first line of the request. */ 466 if ( fgets( line, sizeof(line), conn_fp ) == (char*) 0 ) { 467 send_error( 400, "Bad Request", (char*) 0, "No request found." ); 468 return; 469 } 470 471 method = path = line; 472 strsep(&path, " "); 473 while (*path == ' ') path++; 474 protocol = path; 475 476 strsep(&protocol, " "); 477 while (*protocol == ' ') protocol++; 478 cp = protocol; 479 480 strsep(&cp, " "); 481 if ( !method || !path || !protocol ) { 482 send_error( 400, "Bad Request", (char*) 0, "Can't parse request." ); 483 return; 484 } 485 cur = protocol + strlen(protocol) + 1; 486 487#ifdef TRANSLATE_ON_FLY 488 memset(Accept_Language, 0, sizeof(Accept_Language)); 489#endif 490 491 /* Parse the rest of the request headers. */ 492 while ( fgets( cur, line + sizeof(line) - cur, conn_fp ) != (char*) 0 ) 493 { 494 if ( strcmp( cur, "\n" ) == 0 || strcmp( cur, "\r\n" ) == 0 ){ 495 break; 496 } 497#ifdef TRANSLATE_ON_FLY 498 else if ( strncasecmp( cur, "Accept-Language:",16) ==0){ 499 char *p; 500 struct language_table *pLang; 501 char lang_buf[256]; 502 memset(lang_buf, 0, sizeof(lang_buf)); 503 alang = &cur[16]; 504 strcpy(lang_buf, alang); 505 p = lang_buf; 506 while(p != NULL) 507 { 508 p = strtok (p, "\r\n ,;"); 509 if (p == NULL) break; 510// 2008.11 James. { 511 int i, len = strlen(p); 512 513 for(i = 0; i < len; ++i) 514 if(isupper(p[i])){ 515 p[i] = tolower(p[i]); 516 } 517// 2008.11 James. } 518 for (pLang = language_tables; pLang->Lang != NULL; ++pLang) 519 { 520 if(strcasecmp(p, pLang->Lang)==0) 521 { 522 snprintf(Accept_Language, sizeof(Accept_Language), "%s", pLang->Target_Lang); 523 524 //if(notfirstSetting != 1) 525 if(firstSetting == 1) // 2009.06 James. 526 nvram_set("preferred_lang", Accept_Language); 527 528 break; 529 } 530 } 531 532 if(Accept_Language[0] != 0){ 533 break; 534 } 535 536 p+=strlen(p)+1; 537 } 538 539 if (Accept_Language[0] == 0) { 540 // If all language setting of user's browser are not supported, use English. 541 printf ("Auto detect language failed. Use English.\n"); 542 strcpy (Accept_Language, "EN"); 543 544// 2008.07 James. { 545 //if(notfirstSetting != 1) 546 if(firstSetting == 1) // 2009.06 James. 547 nvram_set("preferred_lang", "EN"); 548// 2008.07 James. } 549 } 550 } 551#endif 552 else if ( strncasecmp( cur, "Authorization:", 14 ) == 0 ) 553 { 554 cp = &cur[14]; 555 cp += strspn( cp, " \t" ); 556 authorization = cp; 557 cur = cp + strlen(cp) + 1; 558 } 559 else if (strncasecmp( cur, "Content-Length:", 15 ) == 0) { 560 cp = &cur[15]; 561 cp += strspn( cp, " \t" ); 562 cl = strtoul( cp, NULL, 0 ); 563 } 564 else if ((cp = strstr( cur, "boundary=" ))) { 565 boundary = &cp[9]; 566 for( cp = cp + 9; *cp && *cp != '\r' && *cp != '\n'; cp++ ); 567 *cp = '\0'; 568 cur = ++cp; 569 } 570 } 571 572 if ( strcasecmp( method, "get" ) != 0 && strcasecmp(method, "post") != 0 ) { 573 send_error( 501, "Not Implemented", (char*) 0, "That method is not implemented." ); 574 return; 575 } 576 577 if ( path[0] != '/' ) { 578 send_error( 400, "Bad Request", (char*) 0, "Bad filename." ); 579 return; 580 } 581 582 file = &(path[1]); 583 len = strlen( file ); 584 if ( file[0] == '/' || strcmp( file, ".." ) == 0 || strncmp( file, "../", 3 ) == 0 || strstr( file, "/../" ) != (char*) 0 || strcmp( &(file[len-3]), "/.." ) == 0 ) { 585 send_error( 400, "Bad Request", (char*) 0, "Illegal filename." ); 586 return; 587 } 588 589 if(file[0] == '\0' || file[len-1] == '/') 590 file = "index.asp"; 591 592// 2007.11 James. { 593 char *query; 594 int file_len; 595 596 memset(url, 0, 4096); 597 if((query = index(file, '?')) != NULL){ 598 file_len = strlen(file)-strlen(query); 599 600 strncpy(url, file, file_len); 601 } 602 else 603 strcpy(url, file); 604/*if(strstr(url, ".htm") || strstr(url, ".asp")) 605 cprintf("url: %s.\n", url);//*/ 606// 2007.11 James. } 607 608 http_login_timeout(login_ip_tmp); // 2008.07 James. 609 610 if(http_port == SERVER_PORT && http_login_check() == 0){ 611// 2007.11 James. { 612 /*struct in_addr login_ip_addr; 613 char *login_ip_str; 614 615 login_ip_addr.s_addr = login_ip; 616 login_ip_str = inet_ntoa(login_ip_addr); 617 618 sprintf(line, "Please log out user, %s, first or wait for session timeout(60 seconds).", login_ip_str); 619 620 printf("resposne: %s \n", line); 621 send_error( 200, "Request is rejected", (char*) 0, line); 622 return;//*/ 623 624 if((strstr(url, ".htm") != NULL 625 && !(!strcmp(url, "error_page.htm") 626 //|| (strstr(url, "QIS_") != NULL && !nvram_match("x_Setting", "1") && login_ip == 0) 627 || (strstr(url, "QIS_") != NULL && changed_http_passwd != 1 && login_ip == 0) 628 || !strcmp(url, "gotoHomePage.htm") 629 )) 630 || (strstr(url, ".asp") != NULL && login_ip != 0)){ 631 file = "Nologin.asp"; 632 633 memset(url, 0, 4096); 634 strcpy(url, file); 635 } 636// 2007.11 James. } 637 } 638 639 //2006_12_11_Roly 640 //check wan port connect status when change webpages 641 //is_connected(); // 2008.03 James. Be replaced by wanduck. 642 643 for(handler = &mime_handlers[0]; handler->pattern; handler++) 644 { 645// 2007.11 James. for the correct result of match(). { 646 //if (match(handler->pattern, file)) 647 if(match(handler->pattern, url)) 648// 2007.11 James. for the correct result of match(). } 649 { 650// 2007.11 James. for QISxxx.htm pages { 651 request_timestamp = time((time_t *)0); 652 653 int login_state = http_login_check(); 654 if((login_state == 1 || login_state == 2) 655 //&& !nvram_match("x_Setting", "1") 656 && changed_http_passwd != 1 657 && (strstr(url, "QIS_") != NULL 658 || !strcmp(url, "result_of_get_changed_status_QIS.asp") 659 || !strcmp(url, "detectWAN.asp") 660 // to avoid the interference of the other logined browser. { 661 || !strcmp(url, "result_of_get_changed_status.asp") 662 || !strcmp(url, "WPS_info.asp") 663 || !strcmp(url, "WAN_info.asp") 664 // } 665 || !strcmp(url, "start_apply.htm") 666 || !strcmp(url, "start_apply2.htm") 667 ) 668 ){ 669 turn_off_auth_timestamp = request_timestamp; 670 temp_turn_off_auth = 1; 671 redirect = 0; 672 } 673 else if(!strcmp(url, "error_page.htm") 674 || !strcmp(url, "Nologin.asp") 675 || !strcmp(url, "gotoHomePage.htm") 676 ){ 677 ; // do nothing. 678 } 679 else if(login_state == 2 680 && !strcmp(url, "Logout.asp")){ 681 turn_off_auth_timestamp = 0; 682 temp_turn_off_auth = 0; 683 redirect = 1; 684 } 685 else if(strstr(url, ".asp") != NULL 686 || strstr(url, ".cgi") != NULL 687 || strstr(url, ".htm") != NULL 688 || strstr(url, ".CFG") != NULL 689 ){ 690 switch(login_state){ 691 case -1: 692 return; 693 case 0: 694 printf("System error! the url would be changed to Nologin.asp in this case!\n"); 695 break; 696 case 1: 697 turn_off_auth_timestamp = 0; 698 temp_turn_off_auth = 0; 699 redirect = 0; 700 break; 701 case 2: 702 /*if(strcmp(url, "WPS_info.asp") || 703 strcmp(url, "WAN_info.asp")){//*/ 704 turn_off_auth_timestamp = 0; 705 temp_turn_off_auth = 0; 706 //} 707 redirect = 0; 708 break; 709 default: 710 printf("System error! the login_state is wrong!\n"); 711 } 712 } 713 else if(login_state == 2 714 && temp_turn_off_auth 715 && (unsigned long)(request_timestamp-turn_off_auth_timestamp) > 10 716 ){ 717 http_logout(login_ip_tmp); 718 turn_off_auth_timestamp = 0; 719 temp_turn_off_auth = 0; 720 redirect = 0; 721 } 722 723 if(handler->auth){ 724 if(!temp_turn_off_auth){ 725 handler->auth(auth_userid, auth_passwd, auth_realm); 726 if(!auth_check(auth_realm, authorization, url)) 727 return; 728 } 729 730 if(!redirect) 731 http_login(login_ip_tmp, url); 732 } 733 734 if(strcasecmp(method, "post") == 0 && !handler->input){ 735 send_error(501, "Not Implemented", NULL, "That method is not implemented."); 736 return; 737 } 738// 2007.11 James. for QISxxx.htm pages } 739 740 if(handler->input){ 741 handler->input(file, conn_fp, cl, boundary); 742#if defined(linux) 743 /*if((flags = fcntl(fileno(conn_fp), F_GETFL)) != -1 && 744 fcntl(fileno(conn_fp), F_SETFL, flags | O_NONBLOCK) != -1){//*/ 745 if((flags = fcntl(conn_fd, F_GETFL)) != -1 && 746 fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK) != -1){//*/ 747 /* Read up to two more characters */ 748 if(fgetc(conn_fp) != EOF) 749 (void)fgetc(conn_fp); 750 751 //fcntl(fileno(conn_fp), F_SETFL, flags); 752 fcntl(conn_fd, F_SETFL, flags); 753 } 754#elif defined(vxworks) 755 flags = 1; 756 //if(ioctl(fileno(conn_fp), FIONBIO, (int) &flags) != -1){ 757 if(ioctl(conn_fd, FIONBIO, (int) &flags) != -1){ 758 /* Read up to two more characters */ 759 if(fgetc(conn_fp) != EOF) 760 (void)fgetc(conn_fp); 761 flags = 0; 762 //ioctl(fileno(conn_fp), FIONBIO, (int) &flags); 763 ioctl(conn_fd, FIONBIO, (int) &flags); 764 } 765#endif 766 } 767 768 send_headers( 200, "Ok", handler->extra_header, handler->mime_type ); 769 if(handler->output){ 770 handler->output(file, conn_fp); 771 } 772 773 break; 774 } 775 } 776 777 if(!handler->pattern) 778 send_error( 404, "Not Found", (char*) 0, "File not found." ); 779 780 if(!strcmp(file, "Logout.asp")){ 781 http_logout(login_ip_tmp); 782 } 783 784 if(!strcmp(file, "Reboot.asp")){ 785 system("reboot"); 786 } 787} 788 789void http_login_cache(usockaddr *u){ 790 struct in_addr temp_ip_addr; 791 char *temp_ip_str; 792 793 login_ip_tmp = (unsigned int)(u->sa_in.sin_addr.s_addr); 794 temp_ip_addr.s_addr = login_ip_tmp; 795 temp_ip_str = inet_ntoa(temp_ip_addr); 796} 797 798void http_login(unsigned int ip, char *url){ 799 /*struct in_addr login_ip_addr; 800 char *login_ip_str;//*/ 801 802 if(http_port != SERVER_PORT || ip == 0x100007f) 803 return; 804 805 login_ip = ip; 806 last_login_ip = 0; 807 808 /*login_ip_addr.s_addr = login_ip; 809 login_ip_str = inet_ntoa(login_ip_addr);//*/ 810 811 if(strcmp(url, "result_of_get_changed_status.asp") 812 && strcmp(url, "result_of_get_changed_status_QIS.asp") 813 && strcmp(url, "WPS_info.asp") 814 && strcmp(url, "WAN_info.asp")) 815 login_timestamp = time((time_t *)0); 816 817 /*char login_ipstr[32], login_timestampstr[32]; 818 819 memset(login_ipstr, 0, 32); 820 sprintf(login_ipstr, "%u", login_ip); 821 nvram_set("login_ip", login_ipstr); 822 823 if(strcmp(url, "result_of_get_changed_status.asp") 824 && strcmp(url, "result_of_get_changed_status_QIS.asp") 825 && strcmp(url, "WPS_info.asp") 826 && strcmp(url, "WAN_info.asp")){ 827 memset(login_timestampstr, 0, 32); 828 sprintf(login_timestampstr, "%lu", login_timestamp); 829 nvram_set("login_timestamp", login_timestampstr); 830 }//*/ 831} 832 833// -1: can not login, 0: not loginer, 1: can login, 2: loginer. 834int http_login_check(void){ 835 if(http_port != SERVER_PORT || login_ip_tmp == 0x100007f) 836 //return 1; 837 return -1; // 2008.01 James. 838 839 //http_login_timeout(login_ip_tmp); // 2008.07 James. 840 841 if(login_ip == 0) 842 return 1; 843 else if(login_ip == login_ip_tmp) 844 return 2; 845 846 return 0; 847} 848 849void http_login_timeout(unsigned int ip) 850{ 851 time_t now; 852 853 time(&now); 854 855// 2007.10 James. for really logout. { 856 //if (login_ip!=ip && (unsigned long)(now-login_timestamp) > 60) //one minitues 857 if((login_ip != 0 && login_ip != ip) && (unsigned long)(now-login_timestamp) > 60) //one minitues 858// 2007.10 James } 859 { 860 http_logout(login_ip); 861 } 862} 863 864void http_logout(unsigned int ip){ 865 if(ip == login_ip){ 866 last_login_ip = login_ip; 867 login_ip = 0; 868 login_timestamp = 0; 869 870 /*nvram_set("login_ip", ""); 871 nvram_set("login_timestamp", "");//*/ 872 873// 2008.03 James. { 874 if(change_passwd == 1){ 875 change_passwd = 0; 876 reget_passwd = 1; 877 } 878// 2008.03 James. } 879 } 880} 881 882int is_auth(void) 883{ 884 if(http_port == SERVER_PORT || !strcmp(nvram_get_x("PrinterStatus", "usb_webhttpcheck_x"), "1")) 885 return 1; 886 else 887 return 0; 888} 889 890int is_phyconnected(void){ 891 int fd, err; 892 struct ifreq ifr; 893 struct ethtool_cmd ecmd; 894 int flag; 895 896 memset(&ifr, 0, sizeof(ifr)); 897 898 strcpy(ifr.ifr_name, wan_if); 899 900 fd = socket(AF_INET, SOCK_DGRAM, 0); 901 if(fd < 0){ 902 //printf("fd error\n"); 903 return 0; 904 } 905 906 ecmd.cmd = ETHTOOL_GSET; 907 ifr.ifr_data = (caddr_t)&ecmd; 908 err = ioctl(fd, SIOCETHTOOL, (void*)&ifr); 909 if(err == 0){ 910 char tmpstr[60]; 911 flag = 0; 912 913#ifdef CDMA 914 if(!nvram_match("hsdpa_product", "")) // HSDPA 915 flag = 1; 916#endif 917 //2006_06_16_Roly 918 //detect wan port(eth1) connection 919 int vecarg[2]; 920 int verbuf; 921 922 vecarg[0] = strtoul("0x01", NULL, 0) << 16; 923 vecarg[0] |= strtoul("0x00", NULL, 0) & 0xffff; 924 925 sprintf(tmpstr, "0x%04x\n", vecarg[1]); 926 927 ifr.ifr_data = (caddr_t) vecarg; 928 if(ioctl(fd, SIOCGETCPHYRD, (caddr_t)&ifr) < 0) 929 printf("etcphyrd error\n"); 930 close(fd); 931 932 verbuf = vecarg[1]; 933 934#ifdef WL500GPV2 935 if((verbuf&0x0010) != 0) 936#elif WL520GU 937 if((verbuf&0x0001) != 0) 938#else 939 if((verbuf&0x0000) != 0) 940#endif 941 flag = 1; 942 943 if(!flag){ 944 nvram_set("wan_status_t", "Disconnected"); 945 nvram_set("wan_reason_t", "Cable is not attached"); 946 } 947 else if(!strcmp(nvram_get_x("", "wan_status_t"), "Disconnected") && strcmp(nvram_get_x("", "wan_ipaddr_t"), "")){ 948 nvram_set("wan_status_t", "Connected"); 949 } 950 951 return flag; 952 } 953 else{ 954 close(fd); 955 //printf("err error\n"); 956 return 0; 957 } 958} 959 960int is_fileexist(char *filename) 961{ 962 FILE *fp; 963 964 fp=fopen(filename, "r"); 965 966 if (fp==NULL) return 0; 967 fclose(fp); 968 return 1; 969} 970 971#if 0 972int is_connected(void){ 973 FILE *fp; 974 char line[128], *reason; 975 976 /* check if physical connection exist */ 977 if(!is_phyconnected()) 978 return 0; 979 980 /* check if connection static is CONNECTED */ 981 if(!strcmp(nvram_get_x("WANIPAddress", "wan_status_t"), "Disconnected")){ 982 fp = fopen("/tmp/wanstatus.log", "r"); 983 if(fp != NULL){ 984 fgets(line, sizeof(line), fp); 985 reason = strchr(line, ','); 986 if(reason != NULL) 987 nvram_set("wan_reason_t", reason+1); 988 fclose(fp); 989 } 990 991 return 0; 992 } 993 994 return 1; 995} 996#endif 997 998int firsttime = -1; // 2009.06 James. 999 1000int is_firsttime(void) 1001{ 1002 /*if(!strcmp(nvram_get_x("General", "x_Setting"), "1")) 1003 return 0; 1004 else 1005 return 1;//*/ 1006 //static int firsttime = -1; // 2009.06 James. 1007 1008 if(firsttime == -1){ 1009 if(!strcmp(nvram_get_x("General", "x_Setting"), "1")) 1010 firsttime = 0; 1011 else 1012 firsttime = 1; 1013 } 1014 1015 return firsttime; 1016} 1017 1018#ifdef TRANSLATE_ON_FLY 1019int 1020load_dictionary (char *lang, pkw_t pkw) 1021{ 1022 char dfn[16]; 1023 char *p, *q; 1024 FILE *dfp = NULL; 1025 int dict_size = 0; 1026 struct timeval tv1, tv2; 1027 const char *eng_dict = "EN.dict"; 1028#ifndef RELOAD_DICT 1029 static char loaded_dict[12] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; 1030#endif // RELOAD_DICT 1031 1032 gettimeofday (&tv1, NULL); 1033 if (lang == NULL || (lang != NULL && strlen (lang) == 0)) { 1034 // if "lang" is invalid, use English as default 1035 snprintf (dfn, sizeof (dfn), eng_dict); 1036 } else { 1037 snprintf (dfn, sizeof (dfn), "%s.dict", lang); 1038 } 1039 1040#ifndef RELOAD_DICT 1041 //printf ("loaded_dict (%s) v.s. dfn (%s)\n", loaded_dict, dfn); 1042 if (strcmp (dfn, loaded_dict) == 0) { 1043 return 1; 1044 } 1045 release_dictionary (pkw); 1046#endif // RELOAD_DICT 1047 1048 do { 1049 printf("Open (%s) dictionary file.\n", dfn); 1050 dfp = fopen (dfn, "r"); 1051 if (dfp != NULL) { 1052#ifndef RELOAD_DICT 1053 snprintf (loaded_dict, sizeof (loaded_dict), "%s", dfn); 1054#endif // RELOAD_DICT 1055 break; 1056 } 1057 1058 printf ("Open (%s) failure. errno %d (%s)\n", dfn, errno, strerror (errno)); 1059 if (dfp == NULL && strcmp (dfn, eng_dict) == 0) { 1060 return 0; 1061 } else { 1062 // If we can't open specified language file, use English as default 1063 snprintf (dfn, sizeof (dfn), eng_dict); 1064 nvram_set("preferred_lang", "EN"); 1065 } 1066 } while (1); 1067 1068 memset (pkw, 0, sizeof (kw_t)); 1069 fseek (dfp, 0L, SEEK_END); 1070 dict_size = ftell (dfp) + 128; 1071 printf ("dict_size %d\n", dict_size); 1072 REALLOC_VECTOR (pkw->idx, pkw->len, pkw->tlen, sizeof (unsigned char*)); 1073 pkw->buf = q = malloc (dict_size); 1074 1075 fseek (dfp, 0L, SEEK_SET); 1076 while (!feof (dfp)) { 1077 // if pkw->idx is not enough, add 32 item to pkw->idx 1078 REALLOC_VECTOR (pkw->idx, pkw->len, pkw->tlen, sizeof (unsigned char*)); 1079 1080 fscanf (dfp, "%[^\n]%*c", q); 1081 if ((p = strchr (q, '=')) != NULL) { 1082 pkw->idx[pkw->len] = q; 1083 pkw->len++; 1084 q = p + strlen (p); 1085 *q = '\0'; 1086 q++; 1087 } 1088 } 1089 1090 fclose (dfp); 1091 gettimeofday (&tv2, NULL); 1092 printf("Load %d keywords spent %ldms\n", pkw->len, ((tv2.tv_sec * 1000000 + tv2.tv_usec) - (tv1.tv_sec * 1000000 + tv1.tv_usec)) / 1000); 1093 1094 return 1; 1095} 1096 1097 1098void 1099release_dictionary (pkw_t pkw) 1100{ 1101 if (pkw == NULL) { 1102 return; 1103 } 1104 1105 pkw->len = pkw->tlen = 0; 1106 1107 if (pkw->idx != NULL) { 1108 free (pkw->idx); 1109 pkw->idx = NULL; 1110 } 1111 1112 if (pkw->buf != NULL) { 1113 free (pkw->buf); 1114 pkw->buf = NULL; 1115 } 1116} 1117 1118char* 1119search_desc (pkw_t pkw, char *name) 1120{ 1121 int i; 1122 char *p, *ret = NULL; 1123 1124 if (pkw == NULL || (pkw != NULL && pkw->len <= 0)) { 1125 return NULL; 1126 } 1127 for (i = 0; i < pkw->len; ++i) { 1128 p = pkw->idx[i]; 1129 if (strncmp (name, p, strlen (name)) == 0) { 1130 ret = p + strlen (name); 1131 break; 1132 } 1133 } 1134 1135 return ret; 1136} 1137#endif //TRANSLATE_ON_FLY 1138 1139 1140 1141int main(int argc, char **argv) 1142{ 1143 usockaddr usa; 1144 int listen_fd; 1145 //int conn_fd; 1146 socklen_t sz = sizeof(usa); 1147 char pidfile[32]; 1148 1149 // Added by Joey for handling WAN Interface 1150 // usage: httpd [wan interface] [port] 1151 if(argc > 2) 1152 http_port = atoi(argv[2]); 1153 1154 if(argc > 1) 1155 strcpy(wan_if, argv[1]); 1156 else 1157 strcpy(wan_if, ""); 1158 1159 //websSetVer(); 1160 1161 // 2008.03 James. 1162 /*nvram_unset("login_timestamp"); 1163 nvram_unset("login_ip");//*/ 1164 1165 /* Ignore broken pipes */ 1166 signal(SIGPIPE, SIG_IGN); 1167 1168 /* Initialize listen socket */ 1169 if ((listen_fd = initialize_listen_socket(&usa)) < 0) { 1170 fprintf(stderr, "can't bind to any address\n" ); 1171 exit(errno); 1172 } 1173 1174#if !defined(DEBUG) && !defined(vxworks) 1175 { 1176 FILE *pid_fp; 1177 /* Daemonize and log PID */ 1178 //if (http_port==SERVER_PORT) 1179 //{ 1180 if (daemon(1, 1) == -1) 1181 { 1182 perror("daemon"); 1183 exit(errno); 1184 } 1185 //} 1186 if (http_port==SERVER_PORT) 1187 strcpy(pidfile, "/var/run/httpd.pid"); 1188 else sprintf(pidfile, "/var/run/httpd-%d.pid", http_port); 1189 1190 if (!(pid_fp = fopen(pidfile, "w"))) { 1191 perror(pidfile); 1192 return errno; 1193 } 1194 fprintf(pid_fp, "%d", getpid()); 1195 fclose(pid_fp); 1196 } 1197#endif 1198 1199 /* Loop forever handling requests */ 1200 for (;;) { 1201 if ((conn_fd = accept(listen_fd, &usa.sa, &sz)) < 0) { 1202 perror("accept"); 1203 return errno; 1204 } 1205 if (!(conn_fp = fdopen(conn_fd, "r+"))) { 1206 perror("fdopen"); 1207 return errno; 1208 } 1209 1210 http_login_cache(&usa); 1211 1212 handle_request(); 1213 fflush(conn_fp); 1214 fclose(conn_fp); 1215 close(conn_fd); 1216 1217#ifdef DLM 1218 if(DISKS_INFO != NULL) 1219 free_disk_data(&DISKS_INFO); // 2009.05 James. 1220#endif 1221 } 1222 1223 shutdown(listen_fd, 2); 1224 close(listen_fd); 1225 1226 return 0; 1227} 1228