/[monit]/monit/net.c
ViewVC logotype

Diff of /monit/net.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.21 by hauk, Fri Jul 25 15:01:15 2003 UTC revision 1.22 by hauk, Wed Jul 30 01:27:15 2003 UTC
# Line 97  Line 97 
97   */   */
98    
99    
100    /* -------------------------------------------------------------- Prototypes */
101    
102    
103    static int do_connect(int s, const struct sockaddr *addr, socklen_t addrlen);
104    
105    
106  /* ------------------------------------------------------------------ Public */  /* ------------------------------------------------------------------ Public */
107    
108    
# Line 116  int check_connect(char *hostname, int po Line 122  int check_connect(char *hostname, int po
122    
123    ASSERT(hostname);    ASSERT(hostname);
124        
125    if ((socket= create_socket(hostname, port, protocol)) < 0) {    if((socket= create_socket(hostname, port, protocol)) < 0) {
       
126      rv= FALSE;      rv= FALSE;
127          } else if(! check_socket(socket)) {
   } else if (! check_socket(socket)) {  
   
128      rv= FALSE;      rv= FALSE;
   
129    }    }
130        
131    close_socket(socket);    close_socket(socket);
# Line 144  int check_host(char *hostname) { Line 146  int check_host(char *hostname) {
146    
147    ASSERT(hostname);    ASSERT(hostname);
148    
149    if ((hp = gethostbyname(hostname)) == NULL) {    if((hp = gethostbyname(hostname)) == NULL) {
       
150      return FALSE;      return FALSE;
       
151    }    }
152        
153    return TRUE;    return TRUE;
# Line 171  int check_socket(int socket) { Line 171  int check_socket(int socket) {
171    FD_SET(socket, &wset);    FD_SET(socket, &wset);
172    tv.tv_sec= SELECT_TIMEOUT;    tv.tv_sec= SELECT_TIMEOUT;
173    tv.tv_usec= 0;    tv.tv_usec= 0;
174      
175    return (select(socket+1, &rset, &wset, NULL, &tv) > 0);    return (select(socket+1, &rset, &wset, NULL, &tv) > 0);
176      
177  }  }
178    
179    
# Line 196  int check_udp_socket(int socket) { Line 197  int check_udp_socket(int socket) {
197     * R/W is asynchronous and we should probably loop and wait longer     * R/W is asynchronous and we should probably loop and wait longer
198     * for a possible ICMP error.     * for a possible ICMP error.
199     */     */
   set_noblock(socket);  
200    write(socket, buf, 1);    write(socket, buf, 1);
201    sleep(2);    sleep(2);
202    r= read(socket, buf, 1);    r= read(socket, buf, 1);
   set_block(socket);  
203    if(0>r) {    if(0>r) {
204      switch(errno) {      switch(errno) {
205      case ECONNREFUSED: return FALSE;      case ECONNREFUSED: return FALSE;
# Line 214  int check_udp_socket(int socket) { Line 213  int check_udp_socket(int socket) {
213    
214    
215  /**  /**
216   * Open a socket against hostname:port with the given protocol.   * Create a non-blocking socket against hostname:port with the given
217   * The protocol is normaly either SOCK_STREAM or SOCK_DGRAM.   * protocol.  The protocol is normaly either SOCK_STREAM or
218     * SOCK_DGRAM.
219   * @param hostname The host to open a socket at   * @param hostname The host to open a socket at
220   * @param port The port number to connect to   * @param port The port number to connect to
221   * @param protocol Socket protocol to use (SOCK_STREAM|SOCK_DGRAM)   * @param protocol Socket protocol to use (SOCK_STREAM|SOCK_DGRAM)
# Line 230  int create_socket(char *hostname, int po Line 230  int create_socket(char *hostname, int po
230    ASSERT(hostname);    ASSERT(hostname);
231    
232    if((hp= gethostbyname(hostname)) == NULL) {    if((hp= gethostbyname(hostname)) == NULL) {
       
233      return -1;      return -1;
       
234    }    }
235        
236    if((s= socket(AF_INET, protocol, 0)) < 0) {    if((s= socket(AF_INET, protocol, 0)) < 0) {
       
237      return -1;      return -1;
       
238    }    }
239        
240    sin.sin_family= AF_INET;    sin.sin_family= AF_INET;
241    sin.sin_port= htons(port);    sin.sin_port= htons(port);
242    memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);    memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
243      
244      if(do_connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
245        goto error;
246      }
247    
248    if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {    if(set_noblock(s) < 0) {
249        goto error;
     close_socket(s);  
     return -1;  
       
250    }    }
251    
252    return s;    return s;
253      
254      error:
255      close_socket(s);
256      return -1;
257    
258  }  }
259    
260    
# Line 269  int create_generic_socket(Port_T p) { Line 270  int create_generic_socket(Port_T p) {
270    
271    ASSERT(p);    ASSERT(p);
272    
273    if(p->family == AF_INET) {    switch(p->family) {
274      case AF_UNIX:
275      socket_fd= create_socket(p->hostname, p->port, p->type);        socket_fd= create_unix_socket(p->pathname);
276          break;
277    } else if(p->family == AF_UNIX) {    case AF_INET:
278          socket_fd= create_socket(p->hostname, p->port, p->type);
279      socket_fd= create_unix_socket(p->pathname, p->type);        break;
280      default:
281          socket_fd= -1;
282    }    }
283      
284    return socket_fd;    return socket_fd;
285        
286  }  }
287    
288    
289  /**  /**
290   * Open a socket against pathname with the given protocol.   * Create a non-blocking socket against pathname with the given
291   * The protocol is normaly either SOCK_STREAM or SOCK_DGRAM.   * protocol.  
292   * @param pathname The unix socket to connect to   * @param pathname The unix socket to connect to
293   * @param protocol Socket protocol to use (SOCK_STREAM|SOCK_DGRAM)   * @param protocol Socket protocol to use (SOCK_STREAM|SOCK_DGRAM)
294   * @return The socket or -1 if an error occured.   * @return The socket or -1 if an error occured.
295   */   */
296  int create_unix_socket(char *pathname, int protocol) {  int create_unix_socket(char *pathname) {
297    
298    int s;    int s;
299    struct sockaddr_un unixsocket;    struct sockaddr_un unixsocket;
300        
301    ASSERT(pathname);    ASSERT(pathname);
302    
303    if ((s= socket(PF_UNIX, protocol, 0)) < 0) {    if((s= socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
       
304      return -1;      return -1;
       
305    }    }
306        
307    unixsocket.sun_family= AF_UNIX;    unixsocket.sun_family= AF_UNIX;
308    snprintf(unixsocket.sun_path, sizeof(unixsocket.sun_path), "%s", pathname);    snprintf(unixsocket.sun_path, sizeof(unixsocket.sun_path), "%s", pathname);
309      
310    if (connect(s, (struct sockaddr *)&unixsocket, sizeof(unixsocket)) < 0) {    if (do_connect(s, (struct sockaddr *)&unixsocket, sizeof(unixsocket)) < 0) {
311        goto error;
     close_socket(s);  
     return -1;  
       
312    }    }
313      
314      if(set_noblock(s) < 0) {
315        goto error;
316      }
317      
318    return s;    return s;
319        
320      error:
321      close_socket(s);
322      return -1;
323    
324  }  }
325    
326    
327  /**  /**
328   * Creates a server socket (SOCK_STREAM type) and binds it to the   * Creates a blocking server socket (SOCK_STREAM type) and binds it to
329   * specified local port number, with the specified backlog. Set a   * the specified local port number, with the specified backlog. Set a
330   * socket option to make the port reusable again. This is useful if   * socket option to make the port reusable again. This is useful if
331   * the server has been shut down, and then restarted right away while   * the server has been shut down, and then restarted right away while
332   * sockets are still active on its port. If a bind address is given   * sockets are still active on its port. If a bind address is given
# Line 358  int create_server_socket(int port, int b Line 363  int create_server_socket(int port, int b
363      myaddr.sin_addr.s_addr= htonl(INADDR_ANY);      myaddr.sin_addr.s_addr= htonl(INADDR_ANY);
364    }    }
365        
366    if (setsockopt(s, SOL_SOCKET,    if(setsockopt(s, SOL_SOCKET,
367                    SO_REUSEADDR, (char *)&flag, sizeof(int)) < 0)                  SO_REUSEADDR, (char *)&flag, sizeof(int)) < 0)
368        goto error;        goto error;
369      
370    if (bind(s, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_in)) < 0)    if(bind(s, (struct sockaddr *)&myaddr, sizeof(struct sockaddr_in)) < 0)
371        goto error;        goto error;
372        
373    if (listen(s, backlog) < 0)    if(listen(s, backlog) < 0)
374        goto error;        goto error;
375        
376    if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1)    if(fcntl(s, F_SETFD, FD_CLOEXEC) == -1)
377        goto error;        goto error;
378        
379    return s;    return s;
# Line 390  int close_socket(int socket) { Line 395  int close_socket(int socket) {
395    
396    int rv= TRUE;    int rv= TRUE;
397    
398    if ((shutdown(socket, 2) < 0)) {    if((shutdown(socket, 2) < 0)) {
       
399      rv= FALSE;      rv= FALSE;
       
400    }    }
401        
402    if (close(socket) < 0) {    if(close(socket) < 0) {
       
403      rv= FALSE;      rv= FALSE;
       
404    }    }
405      
406    return rv;    return rv;
407    
408  }  }
409    
410    
411  /**  /**
  * Set a so_timeout (read/write) for the given socket with the  
  * specified timeout in seconds.  
  * @param socket A socket  
  * @param timeout Read/Write timeout in seconds  
  * @return TRUE if success otherwise FALSE  
  */  
 int set_sotimeout(int socket, int timeout) {  
   
   struct timeval tv= {timeout, 0};  
   
   return ((setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))==0) &&  
           (setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv))==0));  
   
 }  
   
   
 /**  
412   * Enable nonblocking i|o on the given socket.   * Enable nonblocking i|o on the given socket.
413   * @param socket A socket   * @param socket A socket
414   * @return TRUE if success, otherwise FALSE   * @return TRUE if success, otherwise FALSE
415   */   */
416  int set_noblock(int socket) {  int set_noblock(int socket) {
417        
418    int flag= 1;    int flags;
419    
420    return (! ioctl(socket, FIONBIO, &flag));    flags= fcntl(socket, F_GETFL, 0);
421      flags |= O_NONBLOCK;
422    
423      return (fcntl(socket, F_SETFL, flags) == 0);
424    
425  }  }
426    
# Line 445  int set_noblock(int socket) { Line 432  int set_noblock(int socket) {
432   */   */
433  int set_block(int socket) {  int set_block(int socket) {
434    
435    int flag= 0;    int flags;
436    
437      flags= fcntl(socket, F_GETFL, 0);
438      flags &= ~O_NONBLOCK;
439    
440    return (! ioctl(socket, FIONBIO, &flag));    return (fcntl(socket, F_SETFL, flags) == 0);
441    
442  }  }
443    
444    
445  /**  /**
446   * Send the message 'msg' down the socket in non-blocking mode and   * Check if data is available, if not, wait timeout seconds for data
447   * with failover. Inspired by code from the Apache web server.   * to be present.
448   * @param sock A socket   * @param socket A socket
449   * @param msg The message to send   * @param timeout How long to wait before timeout (value in seconds)
450   * @param len The length of the message in bytes   * @return Return TRUE if the event occured, otherwise FALSE.
  * @param flags Optional send flags  
  * @return The bytes sent or -1 if an error occured  
451   */   */
452  int sock_send(int sock, const char *msg, int len, int flags) {  int can_read(int socket, int timeout) {
453    
454    int rv;    fd_set rset;
455    fd_set fdset;    struct timeval tv;
456    struct timeval t;    
457    int retry;    FD_ZERO(&rset);
458      FD_SET(socket, &rset);
459      tv.tv_sec= timeout;
460      tv.tv_usec= 0;
461      
462      return (select(socket+1, &rset, NULL, NULL, &tv) > 0);
463      
464    }
465    
   ASSERT(msg);  
466    
467    if (! set_noblock(sock)) {  /**
468         * Check if data can be sent to the socket, if not, wait timeout
469      return -1;   * seconds for the socket to be ready.
470         * @param socket A socket
471    }   * @param timeout How long to wait before timeout (value in seconds)
472     * @return Return TRUE if the event occured, otherwise FALSE.
473     */
474    int can_write(int socket, int timeout) {
475    
476    rv= send(sock, msg, len, flags);    fd_set wset;
477    if (rv <= 0) {    struct timeval tv;
       
     if (errno == EWOULDBLOCK)  
         do {  
             
           retry= FALSE;  
           FD_ZERO(&fdset);  
           FD_SET(sock, &fdset);  
           t.tv_sec= SELECT_TIMEOUT;  
           t.tv_usec= 0;  
           rv = select(sock+1, NULL, &fdset, NULL, &t);  
           if (rv <= 0) {  
               
             rv= -1;  
               
           }  
           else {  
               
             rv = send(sock, msg, len, flags);  
             if (rv <= 0) {  
                 
               if(errno == EWOULDBLOCK) {  
                   
                 retry= TRUE;  
                 sleep(1);  
                   
               }  
                 
             }  
               
           }  
             
         } while(retry);  
       
   }  
     
   set_block(sock);  
478    
479    return rv;    FD_ZERO(&wset);
480      FD_SET(socket, &wset);
481      tv.tv_sec= timeout;
482      tv.tv_usec= 0;
483    
484      return (select(socket+1, NULL, &wset, NULL, &tv) > 0);
485        
486  }  }
487    
488    
489  /**  /**
490   * Read a message from the socket in non-blocking mode and   * Write <code>size</code> bytes from the <code>buffer</code> to the
491   * with failover. Inspired by code from the Apache web server.   * <code>socket</code>
492   * @param sock A socket   * @param socket the socket to write to
493   * @param buf The buffer to read a message into   * @param buffer The buffer to write
494   * @param len The length of the buffer   * @param size Number of bytes to send
495   * @param flags Optional recv flags   * @return The number of bytes sent or -1 if an error
496   * @return Returns the bytes read or -1 if an error occured   * occured. Returning 0 means EOF
497   */   */
498  int sock_recv(int sock, char *buf, int len, int flags) {  int sock_write(int socket, void *buffer, int size) {
   
   int rv;  
   fd_set fdset;  
   struct timeval t;  
   
   ASSERT(buf);  
499    
500    if (! set_noblock(sock)) {    ssize_t n= 0;
501          
502      if(size<=0)
503          return 0;
504      
505      errno= 0;
506      do {
507        n= write(socket, buffer, size);
508      } while(n == -1 && errno == EINTR);
509      
510      if(n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
511        if(can_write(socket, 5) <= 0) {
512          return -1;
513        }
514        do {
515          n= write(socket, buffer, size);
516        } while(n == -1 && errno == EINTR);
517      }
518      
519      if(n < 0) {
520      return -1;      return -1;
       
521    }    }
522    
523      return n;
524    
525    }
526    
527    
528    /**
529     * Read up to size bytes from the <code>socket</code> into the
530     * <code>buffer</code>. If data is not available wait for
531     * <code>timeout</code> seconds.
532     * @param socket the Socket to read data from
533     * @param buffer The buffer to write the data to
534     * @param size Number of bytes to read from the socket
535     * @param timeout Seconds to wait for data to be available
536     * @return The number of bytes read or -1 if an error
537     * occured. Returning 0 means EOF
538    */
539    int sock_read(int socket, void *buffer, int size, int timeout) {
540        
541    rv= recv(sock, buf, len, flags);    ssize_t n;
542    if (rv <= 0) {    
543          errno= 0;
544      if (errno == EWOULDBLOCK) {    do {
545              n= read(socket, buffer, size);
546        FD_ZERO(&fdset);    } while(n == -1 && errno == EINTR);
547        FD_SET(sock, &fdset);    
548        t.tv_sec= SELECT_TIMEOUT;    if(n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
549        t.tv_usec = 0;      if(can_read(socket, timeout) <= 0) {
550        rv = select(sock+1, &fdset, NULL, NULL, &t);        return -1;
       if (rv <= 0) {  
           
         rv= -1;  
           
       }  
       else {  
           
         rv= recv(sock, buf, len, flags);  
           
       }  
         
551      }      }
552            do {
553          n= read(socket, buffer, size);
554        } while(n == -1 && errno == EINTR);
555    }    }
556    
557    set_block(sock);    return n;
   
   return rv;  
558    
559  }  }
560    
# Line 595  char *get_localhostname() { Line 579  char *get_localhostname() {
579  }  }
580    
581    
582  /**  /* ----------------------------------------------------------------- Private */
583   * Get the remote host name from the originating host.  
584   * @param socket A socket  
585   * @return the (official) name (A-Record) of the peer  /*
586   * or NULL if lookup failed.   * Do a non blocking connect, timeout of not connected within 5 seconds
587   */   */
588  char *get_remote_host(int socket) {  static int do_connect(int s, const struct sockaddr *addr, socklen_t addrlen) {
589    
590    struct hostent *h;    int n, error;
591    struct sockaddr_in r;    fd_set wset, rset;
592    int l= sizeof(struct sockaddr_in);    struct timeval tv;
593    
594    if (getpeername(socket, (struct sockaddr*)&r, &l) < 0) {    errno= 0;
595          error= 0;
596      return NULL;    
597          if(0 > (n= connect(s, addr, addrlen)))
598    } else {        if(errno != EINPROGRESS)
599                  return -1;
600      h=gethostbyaddr((char *)&r.sin_addr, sizeof(struct in_addr), AF_INET);    
601      if (h) {    FD_ZERO(&rset);
602            FD_SET(s, &rset);
603        return strdup(h->h_name);    wset= rset;
604            tv.tv_sec= 5;
605      }    tv.tv_usec= 0;
606          
607      if(select(s+1, NULL, &rset, &wset, &tv)==0) {
608        close(s);
609        errno= ETIMEDOUT;
610        return -1;
611    }    }
612    
613    return NULL;    if(FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) {
614        int len= sizeof(error);
615        if(getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
616            return -1;
617      } else
618          return -1;
619    
620      if(error) {
621        close(s);
622        errno= error;
623        return -1;
624      }
625    
626      return 0;
627      
628  }  }
629    

Legend:
Removed from v.1.21  
changed lines
  Added in v.1.22

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26