dpm-ctrl_http.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dpm-ctrl_http.c 346460 2009-11-14 05:06:47Z ssiano $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  *
00010  * Copyright (c) 2007-2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00024 #include <dirent.h>
00025 #include <pthread.h>
00026 #include <mihl.h>
00027 #include "dpm-ctrl_main.h"
00028 #include "dpm-ctrl_config.h"
00029 #include "dpm-ctrl_http.h"
00030 
00031 /*** Constants ***/
00032 
00036 #define DPM_HTTP_PORT 80
00037 
00041 #define DPM_HTTP_MAX_CONNECTIONS 400
00042 
00046 #define HTTP_SERVER_LOG_LEVEL \
00047     (MIHL_LOG_ERROR | MIHL_LOG_WARNING | MIHL_LOG_INFO | MIHL_LOG_INFO_VERBOSE)
00048 
00052 #define HTML_CONTENT "Content-type: text/html\r\n"
00053 
00054 
00055 /*** Data structures: ***/
00056 
00060 static volatile uint8_t shutdown_server = 1;
00061 static pthread_t        http_thread;    
00062 static pthread_mutex_t  suspend_lock;   
00063 extern int http_cpu_num;                
00064 
00068 typedef enum {
00069     LOGGED_OUT = 1,  
00070     LOGGED_IN,       
00071     BAD_PASSWORD,    
00072     LOGIN_SUCCESSFUL 
00073 } status_e;
00074 
00075 /*** STATIC/INTERNAL Functions ***/
00076 
00077 
00089 static void
00090 write_page(mihl_cnx_t * cnx, status_e status)
00091 {
00092     mihl_add(cnx,
00093         "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
00094         "<html>"
00095         "<head>"
00096         "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">"
00097         "<title>SYNC Dynamic Policy Manager - Portal</title>"
00098         "<style>"
00099         "body {"
00100         "    background-color: #666666;"
00101         "    font-family: Arial, sans-serif;"
00102         "    font-size: 10pt;"
00103         "}"
00104         "#content {"
00105         "    background-color: #FFFFFF;"
00106         "    border: 1px outset #000000;"
00107         "    height: 300px;"
00108         "    min-width: 700px;"
00109         "    width: 700px;"
00110         "    padding: 10px;"
00111         "}"
00112         "</style>"
00113         "</head>"
00114         "<body>"
00115         "<div align=\"center\">"
00116         "  <div id=\"content\" align=\"left\">"
00117         "    <p align=\"center\"><strong><u>Welcome to the SDK Your Net Corporation (SYNC)" 
00118         "    Dynamic Policy Manager Example Portal</u></strong></p>"
00119         "    <p>&nbsp;</p>");
00120     
00121     if(status == LOGGED_IN || status == LOGIN_SUCCESSFUL) {
00122         
00123         mihl_add(cnx,
00124             "    <p>Using this site you may repudiate your own traffic policy by logging in.</p>");
00125 
00126         if(status == LOGIN_SUCCESSFUL) {
00127             mihl_add(cnx,
00128                     "    <p style=\"color:green\">Login Succesful.</p>");
00129         }
00130         
00131         mihl_add(cnx,
00132             "    <p><u><b>Subscriber Sign-out</b></u>"
00133             "        <form name=\"signout\" action=\"/logout.html\" method=\"post\">"
00134             "        <input value=\" Sign Out \" tabindex=\"1\" type=\"submit\"><br>");
00135     } else {
00136         mihl_add(cnx,
00137             "    <p>Using this site you may authorize your own traffic policy by logging in.</p>");
00138         
00139         if(status == BAD_PASSWORD) {
00140             mihl_add(cnx,
00141                     "    <p style=\"color:red\">Incorrect username or password.</p>");
00142         }
00143         
00144         mihl_add(cnx,
00145             "    <p><u><b>Subscriber Sign-in</b></u>"
00146             "        <form name=\"signin\" action=\"/login.html\" method=\"post\">"
00147             "        Username:<br><input name=\"username\" id=\"username\" tabindex=\"1\" size=\"21\" type=\"text\"><br><br>"
00148             "        Password:<br><input name=\"password\" id=\"password\" tabindex=\"2\" size=\"21\" type=\"password\">"
00149             "        <br><br>"
00150             "        <input value=\" Sign In \" tabindex=\"3\" type=\"submit\"><br>");
00151     }
00152 
00153     mihl_add(cnx,
00154         "        </form>"
00155         "    </p>"
00156         "  </div>"
00157         "</div>"
00158         "</body>"
00159         "</html>");
00160 }
00161 
00162 
00183 static int
00184 logout(mihl_cnx_t * cnx,
00185        char const * tag,
00186        char const * host,
00187        int num_vars __unused,
00188        char ** var_names __unused,
00189        char ** var_values __unused,
00190        void * param __unused)
00191 {
00192     
00193     struct in_addr client_address;
00194     int rc;
00195     
00196     rc = inet_aton(host, &client_address); // client_address is nw-byte order
00197     if(rc != 1) {
00198         LOG(LOG_ERR, "%s: Couldn't parse host IP: %s", __func__, host);
00199         return 0;
00200     }
00201     
00202     LOG(LOG_INFO, "%s: %s (%s)", __func__, tag, host);
00203     
00204     if(user_logged_in(client_address.s_addr)) {
00205         
00206         remove_policy(client_address.s_addr);
00207         
00208     } else {
00209         LOG(LOG_WARNING, "%s: Got a logout request for a user that "
00210                 "isn't logged in: %s", __func__, host);
00211     }
00212     
00213     write_page(cnx, LOGGED_OUT);
00214     
00215     return mihl_send(cnx, NULL, HTML_CONTENT);
00216 }
00217 
00218 
00239 static int
00240 login(mihl_cnx_t * cnx,
00241       char const * tag,
00242       char const * host,
00243       int num_vars,
00244       char ** var_names,
00245       char ** var_values,
00246       void * param __unused)
00247 {
00248     /********************
00249     const char * sep = "/?&";
00250     char url[1024], * token,
00251     ********************/
00252     char * username, * password;
00253     struct in_addr client_address;
00254     int rc, i;
00255     
00256     rc = inet_aton(host, &client_address); // client_address is nw-byte order
00257     if(rc != 1) {
00258         LOG(LOG_ERR, "%s: Couldn't parse host IP: %s", __func__, host);
00259         return 0;
00260     }
00261     
00262     LOG(LOG_INFO, "%s: %s (%s) (numvars: %d)", __func__, tag, host, num_vars);
00263     
00264     // parse tag/URL for username/password to validate
00265     username = password = NULL;
00266     
00267     for(i = 0; i < num_vars; ++i) {
00268         if(strcmp(var_names[i], "username") == 0) {
00269             username = var_values[i];
00270         } else if(strcmp(var_names[i], "password") == 0) {
00271             password = var_values[i];
00272         }
00273     }
00274     
00275     // validate
00276     if(username == NULL || password == NULL ||
00277             !validate_credentials(username, password)) {
00278         write_page(cnx, BAD_PASSWORD);
00279     } else {
00280         // add policy for this user
00281         apply_policy(username, client_address.s_addr);
00282         write_page(cnx, LOGIN_SUCCESSFUL);
00283     }
00284     
00285     return mihl_send(cnx, NULL, HTML_CONTENT);
00286 }
00287 
00288 
00309 static int
00310 check_access(mihl_cnx_t * cnx,
00311              char const * tag,
00312              char const * host,
00313              void * param __unused)
00314 {
00315     struct in_addr client_address;
00316     int rc;
00317     
00318     LOG(LOG_INFO, "%s: %s (%s)", __func__, tag, host);
00319     
00320     rc = inet_aton(host, &client_address); // client_address is nw-byte order
00321     if(rc != 1) {
00322         LOG(LOG_ERR, "%s: Couldn't parse host IP: %s", __func__, host);
00323         return 0;
00324     }
00325     
00326     write_page(cnx,
00327             (user_logged_in(client_address.s_addr)) ? LOGGED_IN : LOGGED_OUT);
00328     
00329     return mihl_send(cnx, NULL, HTML_CONTENT);
00330 }
00331 
00332 
00341 static void *
00342 run_http_server(void * params __unused)
00343 {
00344     mihl_ctx_t * ctx;
00345     sigset_t sig_mask;
00346 
00347     LOG(LOG_INFO, "%s: HTTP server thread alive", __func__);
00348     
00349     // Block SIGTERM to this thread/main thread will handle otherwise we inherit  
00350     // this behaviour in our threads sigmask and the signal might come here
00351     sigemptyset(&sig_mask);
00352     sigaddset(&sig_mask, SIGTERM);
00353     pthread_sigmask(SIG_BLOCK, &sig_mask, NULL);
00354     
00355     // initial a server and get the server context
00356     ctx = mihl_init("0.0.0.0", DPM_HTTP_PORT,
00357             DPM_HTTP_MAX_CONNECTIONS, HTTP_SERVER_LOG_LEVEL);
00358     
00359     if (!ctx) {
00360         LOG(LOG_ERR, "%s: Failed to start HTTP server using library",
00361             __func__);
00362         pthread_exit((void *) 0);
00363         return NULL;
00364     }
00365 
00366     LOG(LOG_INFO, "%s: Started HTTP server", __func__);
00367     
00368     // register default handler
00369     mihl_handle_get(ctx, NULL, check_access, NULL);
00370     
00371     // register other handlers to control access
00372     mihl_handle_post(ctx, "/login.html", login, NULL);
00373     mihl_handle_post(ctx, "/logout.html", logout, NULL);
00374 
00375     // MAIN LOOP
00376     while(!shutdown_server) {
00377         // don't serve while suspended
00378         INSIST_ERR(pthread_mutex_lock(&suspend_lock) == 0);
00379         
00380         mihl_server(ctx); // serve pages and accept/terminate connections
00381         
00382         INSIST_ERR(pthread_mutex_unlock(&suspend_lock) == 0);
00383     }
00384     
00385     mihl_end(ctx);
00386     
00387     LOG(LOG_INFO, "%s: HTTP server thread exiting", __func__);
00388 
00389     pthread_exit((void *) 0); // explicitly return to join
00390     return NULL;
00391 }
00392 
00393 
00394 /*** GLOBAL/EXTERNAL Functions ***/
00395 
00396 
00400 void
00401 init_http_server(void)
00402 {
00403     pthread_attr_t attr;
00404     int rc;
00405     
00406     pthread_mutex_init(&suspend_lock, NULL);
00407     
00408     if(!shutdown_server) { // if server is running
00409         shutdown_http_server();
00410     }
00411 
00412     /* Initialize and set thread detached attribute */
00413     pthread_attr_init(&attr);
00414     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00415     pthread_attr_setcpuaffinity_np(&attr, http_cpu_num);
00416 
00417     shutdown_server = 0; // server starting
00418     
00419     LOG(LOG_INFO, "%s: Staring DPM's HTTP server", __func__);
00420     
00421     rc = pthread_create(&http_thread, NULL, run_http_server, NULL);
00422     if(rc) {
00423         LOG(LOG_ERR, "%s: Failed to start http server thread (%d)",
00424             __func__, rc);
00425         shutdown_server = 1; // still shutdown
00426     }
00427     
00428     pthread_attr_destroy(&attr);
00429 }
00430 
00431 
00435 void
00436 suspend_http_server(void)
00437 {
00438     int rc;
00439     
00440     rc = pthread_mutex_lock(&suspend_lock);
00441     
00442     if(rc != 0) {
00443         LOG(LOG_ERR, "%s: Failed to suspend http server %d", __func__, rc);
00444     }
00445 }
00446 
00447 
00452 void
00453 resume_http_server(void)
00454 {
00455     int rc;
00456     
00457     rc = pthread_mutex_unlock(&suspend_lock);
00458     
00459     if(rc != 0) {
00460         LOG(LOG_ERR, "%s: Failed to resume http server %d", __func__, rc);
00461     }
00462 }
00463 
00464 
00469 void
00470 shutdown_http_server(void)
00471 {
00472     int rc, status;
00473     
00474     if(shutdown_server) { // if server isn't running
00475         return;
00476     }
00477     
00478     shutdown_server = 1;
00479     
00480     LOG(LOG_INFO, "%s: Shutting down DPM's HTTP server", __func__);
00481     
00482     // wait for server thread
00483     rc = pthread_join(http_thread, (void **)&status);
00484     if(rc) {
00485         LOG(LOG_WARNING, "%s: Failed to synchronize on http server "
00486                 "thread exit (%d)", __func__, rc);
00487         return;
00488     }
00489     
00490     pthread_mutex_destroy(&suspend_lock);
00491 }

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:54 2010 for SDK Your Net Corporation Dynamic Policy Manager Example: dpm-ctrl 1.0 by Doxygen 1.5.1