checks.c

Go to the documentation of this file.
00001 /*
00002  ** Copyright 2005 - INL
00003  ** Written by Eric Leblond <regit@inl.fr>
00004  **            Vincent Deffontaines <vincent@inl.fr>
00005  ** INL http://www.inl.fr/
00006  **
00007  ** $Id: checks.c 4874 2008-07-22 13:35:49Z regit $
00008  **
00009  **
00010  ** This program is free software; you can redistribute it and/or modify
00011  ** it under the terms of the GNU General Public License as published by
00012  ** the Free Software Foundation, version 3 of the License.
00013  **
00014  ** This program is distributed in the hope that it will be useful,
00015  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  ** GNU General Public License for more details.
00018  **
00019  ** You should have received a copy of the GNU General Public License
00020  ** along with this program; if not, write to the Free Software
00021  ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022  */
00023 
00024 #include "nufw_source.h"
00025 #include "libnuclient.h"
00026 #include <sasl/saslutil.h>
00027 #include <nussl.h>
00028 #include <proto.h>
00029 #include "proc.h"
00030 #include "checks.h"
00031 #include "tcptable.h"
00032 #include "sending.h"
00033 
00046 nu_error_t recv_message(nuauth_session_t *session, nuclient_error_t *err)
00047 {
00048         int ret;
00049         char dgram[512];
00050         const size_t message_length =
00051             sizeof(struct nu_header) + sizeof(struct nu_authfield_hello) +
00052             sizeof(struct nu_authreq);
00053         char message[message_length];
00054         struct nu_header *header;
00055         struct nu_authreq *authreq;
00056         struct nu_authfield_hello *hellofield;
00057 
00058         /* fill struct */
00059         header = (struct nu_header *) message;
00060         header->proto = PROTO_VERSION;
00061         header->msg_type = USER_REQUEST;
00062         header->option = 0;
00063         header->length = htons(message_length);
00064 
00065         authreq = (struct nu_authreq *) (header + 1);
00066         authreq->packet_seq = session->packet_seq++;
00067         authreq->packet_length =
00068                 htons(sizeof(struct nu_authreq) +
00069                                 sizeof(struct nu_authfield_hello));
00070 
00071         hellofield = (struct nu_authfield_hello *) (authreq + 1);
00072         hellofield->type = HELLO_FIELD;
00073         hellofield->option = 0;
00074         hellofield->length = htons(sizeof(struct nu_authfield_hello));
00075 
00076         ret = nussl_read(session->nussl, dgram, sizeof dgram);
00077 
00078         if (ret == NUSSL_SOCK_TIMEOUT) {
00079                 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00080                 return NU_EXIT_CONTINUE;
00081         }
00082 
00083         if (ret <= 0) {
00084                 ask_session_end(session);
00085                 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00086                 return NU_EXIT_ERROR;
00087         }
00088 
00089         switch (dgram[0]) {
00090                 case SRV_REQUIRED_PACKET:
00091                         if (session->debug_mode) {
00092                                 printf("[+] Client is asked to send new connections.\n");
00093                         }
00094                         nu_client_real_check(session, err);
00095                         break;
00096 
00097                 case SRV_REQUIRED_HELLO:
00098                         hellofield->helloid =
00099                                 ((struct nu_srv_helloreq *) dgram)->helloid;
00100                         if (session->debug_mode) {
00101                                 printf("[+] Send HELLO\n");
00102                         }
00103 
00104                         /*  send it */
00105                         ret = nussl_write(session->nussl, message, message_length);
00106                         if (ret < 0) {
00107 #if DEBUG_ENABLE
00108                                 printf("write failed at %s:%d\n",
00109                                                 __FILE__, __LINE__);
00110 #endif
00111                                 ask_session_end(session);
00112                                 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00113                                 return NU_EXIT_ERROR;
00114                         }
00115                         break;
00116 
00117                 default:
00118                         printf("unknown message\n");
00119                         return NU_EXIT_CONTINUE;
00120         }
00121         return NU_EXIT_OK;
00122 }
00123 
00124 nu_error_t increase_refresh_delay(nuauth_session_t *session)
00125 {
00126         if (session->sleep_delay.tv_sec * 1000000 + 
00127                 session->sleep_delay.tv_usec <
00128                 session->max_sleep_delay.tv_sec * 1000000 +
00129                 session->max_sleep_delay.tv_usec) {
00130                 session->sleep_delay.tv_sec = session->sleep_delay.tv_sec * 2 +
00131                             (session->sleep_delay.tv_usec * 2) / 1000000;
00132                 session->sleep_delay.tv_usec =
00133                         session->sleep_delay.tv_usec * 2 % 1000000;
00134                 /* Should retest: We may exceed max delay if we don't have 
00135                  * max_delay=min_delay*2^k */
00136         }
00137         return NU_EXIT_OK;
00138 }
00139 
00140 nu_error_t reset_refresh_delay(nuauth_session_t *session)
00141 {
00142         session->sleep_delay.tv_sec = session->min_sleep_delay.tv_sec;
00143         session->sleep_delay.tv_usec = session->min_sleep_delay.tv_usec;
00144         return NU_EXIT_OK;
00145 }
00146 
00162 int nu_client_check(nuauth_session_t * session, nuclient_error_t * err)
00163 {
00164         /* test is a thread has detected problem with the session */
00165         if (session->connected == 0) {
00166                 SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00167                 return -1;
00168         }
00169 
00170         if (session->server_mode == SRV_TYPE_POLL) {
00171                 int checkreturn;
00172 
00173                 usleep(session->sleep_delay.tv_sec * 1000000 +
00174                        session->sleep_delay.tv_usec);
00175                 checkreturn = nu_client_real_check(session, err);
00176                 if (checkreturn < 0) {
00177                         /* error code filled by nu_client_real_check() */
00178                         return -1;
00179                 } else {
00180                         SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00181                         return 1;
00182                 }
00183         } else {
00184                 struct timeval tv;      
00185                 fd_set select_set;
00186                 int ret;
00187                 tv.tv_sec = session->sleep_delay.tv_sec;
00188                 tv.tv_usec = session->sleep_delay.tv_usec;
00189 
00190                 if (session->nussl == NULL) {
00191                         SET_ERROR(err, INTERNAL_ERROR, UNKNOWN_ERR);
00192                         return -1;
00193                 }
00194                 /* Going to wait an event */
00195                 FD_ZERO(&select_set);
00196                 FD_SET(nussl_session_get_fd(session->nussl), &select_set);
00197                 ret = select(nussl_session_get_fd(session->nussl)+1, &select_set, NULL, NULL, &tv);
00198 
00199                 /* catch select() error */
00200                 if (ret == -1) {
00201                         ask_session_end(session);
00202                         SET_ERROR(err, INTERNAL_ERROR, SESSION_NOT_CONNECTED_ERR);
00203                         return -1;
00204                 }
00205 
00206                 if (ret == 0) {
00207                         int checkreturn;
00208                         /* start a check */
00209                         checkreturn = nu_client_real_check(session, err);
00210                         if (checkreturn < 0) {
00211                                 /* error code filled by nu_client_real_check() */
00212                                 return -1;
00213                         } else {
00214                                 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00215                                 if (checkreturn == 0) {
00216                                         increase_refresh_delay(session);
00217                                 }
00218                                 return 1;
00219                         }
00220                         /* sending hello if needed */
00221                         if ((time(NULL) - session->timestamp_last_sent) >
00222                                         SENT_TEST_INTERVAL) {
00223                                 if (!send_hello_pckt(session)) {
00224                                         SET_ERROR(err, INTERNAL_ERROR,
00225                                                         TIMEOUT_ERR);
00226                                         return -1;
00227                                 }
00228                                 session->timestamp_last_sent = time(NULL);
00229                         }
00230                 } else {
00231                         if (recv_message(session, err) == NU_EXIT_ERROR) {
00232                                 return -1;
00233                         }
00234                 }
00235         }
00236         SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00237         return 1;
00238 }
00239 
00250 int nu_client_real_check(nuauth_session_t * session, nuclient_error_t * err)
00251 {
00252         conntable_t *new;
00253         int nb_packets = 0;
00254 
00255         if (session->debug_mode) {
00256                 printf("[+] Client checking for new connections.\n");
00257         }
00258 
00259         if (tcptable_init(&new) == 0) {
00260                 SET_ERROR(err, INTERNAL_ERROR, MEMORY_ERR);
00261                 return -1;
00262         }
00263         if (tcptable_read(session, new) == 0) {
00264                 tcptable_free(new);
00265                 SET_ERROR(err, INTERNAL_ERROR, TCPTABLE_ERR);
00266                 return -1;
00267         }
00268 #ifdef LINUX
00269         /* update cache for link between proc and socket inode */
00270         prg_cache_load();
00271 #endif
00272         nb_packets = compare(session, session->ct, new, err);
00273         /* free link between proc and socket inode */
00274 #ifdef LINUX
00275         prg_cache_clear();
00276 #endif
00277 
00278         tcptable_free(session->ct);
00279 
00280         /* on error, we ask client to exit */
00281         if (nb_packets < 0) {
00282                 ask_session_end(session);
00283                 return nb_packets;
00284         }
00285         session->ct = new;
00286 
00287         if (nb_packets > 0) {
00288                 reset_refresh_delay(session);
00289         }
00290         return nb_packets;
00291 }
00292 
00293 

Generated on Sat Nov 22 04:00:37 2008 for NuFW by  doxygen 1.4.7