diff --git a/src/common/Makefile.am b/src/common/Makefile.am index f48fb803e77bbb4ccce95376af22912ffdb8264e..b23987f73f31b48cb0d7a0f6e841dcd1b370d952 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -42,6 +42,7 @@ libcommon_la_SOURCES = \ slurm_protocol_util.c \ slurm_protocol_socket_implementation.c \ slurm_protocol_defs.c \ + util-net.c \ $(elan_sources) \ $(auth_sources) @@ -72,7 +73,9 @@ noinst_HEADERS = \ slurm_protocol_socket_common.h \ slurm_protocol_mongo_common.h \ slurm_protocol_interface.h \ - slurm_errno.h \ + slurm_errno.h \ + util-net.h \ + wrapper.h \ qsw.h libdaemonize_la_SOURCES = \ diff --git a/src/common/slurm_protocol_socket_implementation.c b/src/common/slurm_protocol_socket_implementation.c index 8faa3278967938fde3af75cd737eaf482e59fe02..96d5936b0b9717efb7517f2e21bf6c3f5f0e0d6b 100644 --- a/src/common/slurm_protocol_socket_implementation.c +++ b/src/common/slurm_protocol_socket_implementation.c @@ -46,11 +46,12 @@ # endif #endif -#include <src/common/slurm_protocol_interface.h> -#include <src/common/slurm_protocol_common.h> -#include <src/common/slurm_protocol_defs.h> -#include <src/common/log.h> -#include <src/common/pack.h> +#include "src/common/slurm_protocol_interface.h" +#include "src/common/slurm_protocol_common.h" +#include "src/common/slurm_protocol_defs.h" +#include "src/common/log.h" +#include "src/common/pack.h" +#include "src/common/util-net.h" #define TEMP_BUFFER_SIZE 1024 @@ -69,8 +70,9 @@ slurm_fd _slurm_open_msg_conn ( slurm_addr * slurm_address ) return _slurm_open_stream ( slurm_address ) ; } -/* this should be a no-op that just returns open_fd in a message implementation */ -slurm_fd _slurm_accept_msg_conn ( slurm_fd open_fd , slurm_addr * slurm_address ) +/* this should be a no-op that just returns open_fd in a message + * implementation */ +slurm_fd _slurm_accept_msg_conn (slurm_fd open_fd ,slurm_addr * slurm_address) { return _slurm_accept_stream ( open_fd , slurm_address ) ; } @@ -80,13 +82,18 @@ int _slurm_close_accepted_conn ( slurm_fd open_fd ) return _slurm_close ( open_fd ) ; } -ssize_t _slurm_msg_recvfrom ( slurm_fd open_fd, char *buffer , size_t size , uint32_t flags, slurm_addr * slurm_address ) +ssize_t _slurm_msg_recvfrom ( slurm_fd open_fd, char *buffer , size_t size , + uint32_t flags, slurm_addr * slurm_address ) { return _slurm_msg_recvfrom_timeout ( open_fd , buffer , size , flags , - slurm_address , SLURM_MESSGE_TIMEOUT_MSEC_STATIC ) ; + slurm_address , + SLURM_MESSGE_TIMEOUT_MSEC_STATIC ) ; } -ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t size , uint32_t flags, slurm_addr * slurm_address , int timeout) +ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , + size_t size , uint32_t flags, + slurm_addr * slurm_address , + int timeout) { size_t recv_len ; @@ -102,9 +109,11 @@ ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t si total_len = 0 ; while ( total_len < sizeof ( uint32_t ) ) { - if ( ( recv_len = _slurm_recv_timeout ( open_fd , moving_buffer , + if ( ( recv_len = _slurm_recv_timeout ( open_fd , + moving_buffer , (sizeof ( uint32_t ) - total_len), - SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , timeout ) ) == SLURM_SOCKET_ERROR ) + SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , timeout ) ) + == SLURM_SOCKET_ERROR ) { if ( errno == EINTR ) continue ; @@ -118,14 +127,16 @@ ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t si } else if ( recv_len == 0 ) { - /*debug ( "Error receiving length of datagram. recv_len = 0 ") ; */ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_ZERO_RECV_LENGTH ) ; + /*debug ( "Error datagram recv_len = 0 ") ; */ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_ZERO_RECV_LENGTH); return SLURM_PROTOCOL_ERROR ; } else { - /*debug ( "We don't handle negative return codes > -1") ;*/ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_NEGATIVE_RECV_LENGTH ) ; + /*debug ( "Error datagram recv_len < -1") ;*/ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_NEGATIVE_RECV_LENGTH ) ; return SLURM_PROTOCOL_ERROR ; } } @@ -143,7 +154,10 @@ ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t si total_len = 0 ; while ( total_len < transmit_size ) { - if ( ( recv_len = _slurm_recv_timeout ( open_fd , moving_buffer , (transmit_size-total_len) , SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , timeout ) ) == SLURM_SOCKET_ERROR ) + if ( ( recv_len = _slurm_recv_timeout (open_fd, moving_buffer, + (transmit_size-total_len) , + SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , + timeout ) ) == SLURM_SOCKET_ERROR ) { if ( errno == EINTR ) { @@ -162,28 +176,32 @@ ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t si } else if ( recv_len == 0 ) { - /*debug ( "Error receiving length of datagram. recv_len = 0 ") ; */ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_ZERO_RECV_LENGTH ) ; + /*debug ( "Error datagram recv_len = 0 ") ; */ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_ZERO_RECV_LENGTH ) ; return SLURM_PROTOCOL_ERROR ; } else { - /*debug ( "We don't handle negative return codes > -1") ;*/ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_NEGATIVE_RECV_LENGTH ) ; + /*debug ( "Error datagram recv_len < -1") ;*/ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_NEGATIVE_RECV_LENGTH ) ; return SLURM_PROTOCOL_ERROR ; } } if ( excess_len ) { - /* read and toss any data transmitted that we lack the buffer for */ + /* read and toss any data transmitted over buffer size */ moving_buffer = size_buffer ; size_buffer_len = TEMP_BUFFER_SIZE; while ( excess_len ) { if (size_buffer_len > excess_len) size_buffer_len = excess_len; - if ( ( recv_len = _slurm_recv_timeout ( open_fd , moving_buffer , size_buffer_len , - SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , timeout ) ) == SLURM_SOCKET_ERROR ) + if ( ( recv_len = _slurm_recv_timeout ( open_fd , + moving_buffer , size_buffer_len , + SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , + timeout ) ) == SLURM_SOCKET_ERROR ) { if ( errno == EINTR ) continue ; @@ -196,14 +214,16 @@ ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t si } else if ( recv_len == 0 ) { - /*debug ( "Error receiving length of datagram. recv_len = 0 ") ; */ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_ZERO_RECV_LENGTH ) ; + /*debug ( "Error datagram recv_len = 0 ") ; */ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_ZERO_RECV_LENGTH ) ; return SLURM_PROTOCOL_ERROR ; } else { - /*debug ( "We don't handle negative return codes > -1") ;*/ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_NEGATIVE_RECV_LENGTH ) ; + /*debug ( "Error datagram recv_len < -1") ;*/ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_NEGATIVE_RECV_LENGTH ) ; return SLURM_PROTOCOL_ERROR ; } } @@ -214,13 +234,17 @@ ssize_t _slurm_msg_recvfrom_timeout ( slurm_fd open_fd, char *buffer , size_t si return total_len ; } -ssize_t _slurm_msg_sendto ( slurm_fd open_fd, char *buffer , size_t size , uint32_t flags, slurm_addr * slurm_address ) +ssize_t _slurm_msg_sendto ( slurm_fd open_fd, char *buffer , size_t size , + uint32_t flags, slurm_addr * slurm_address ) { return _slurm_msg_sendto_timeout ( open_fd, buffer , size , flags, - slurm_address , SLURM_MESSGE_TIMEOUT_MSEC_STATIC ) ; + slurm_address , + SLURM_MESSGE_TIMEOUT_MSEC_STATIC ) ; } -ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , size_t size , uint32_t flags, slurm_addr * slurm_address , int timeout ) +ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , + size_t size , uint32_t flags, + slurm_addr * slurm_address , int timeout ) { size_t send_len ; @@ -231,7 +255,8 @@ ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , size_t size newaction . sa_handler = SIG_IGN ; - /* ignore SIGPIPE so that send can return a error code if the other side closes the socket */ + /* ignore SIGPIPE so that send can return a error code if the + * other side closes the socket */ sigaction(SIGPIPE, &newaction , & oldaction ); usize = htonl(size); @@ -240,8 +265,8 @@ ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , size_t size { if ( ( send_len = _slurm_send_timeout ( open_fd , (char *) &usize , sizeof ( uint32_t ) , - SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , timeout ) ) == - SLURM_PROTOCOL_ERROR ) + SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , + timeout ) ) == SLURM_PROTOCOL_ERROR ) { if ( errno == EINTR ) continue ; @@ -250,8 +275,10 @@ ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , size_t size } else if ( send_len != sizeof ( uint32_t ) ) { - /*debug ( "_slurm_msg_sendto only transmitted %i of %i bytes", send_len , sizeof ( uint32_t ) ) ;*/ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_NOT_ALL_DATA_SENT ) ; + /*debug ( "_slurm_msg_sendto only transmitted %i of %i bytes", + send_len , sizeof ( uint32_t ) ) ;*/ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_NOT_ALL_DATA_SENT ) ; goto _slurm_msg_sendto_exit_error ; } else @@ -260,7 +287,8 @@ ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , size_t size while ( true ) { if ( ( send_len = _slurm_send_timeout ( open_fd , buffer , size , - SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , timeout ) ) == SLURM_PROTOCOL_ERROR ) + SLURM_PROTOCOL_NO_SEND_RECV_FLAGS , + timeout ) ) == SLURM_PROTOCOL_ERROR ) { if ( errno == EINTR ) continue ; @@ -269,8 +297,10 @@ ssize_t _slurm_msg_sendto_timeout ( slurm_fd open_fd, char *buffer , size_t size } else if ( send_len != size ) { - /*debug ( "_slurm_msg_sendto only transmitted %i of %i bytes", send_len , size ) ;*/ - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_IMPL_NOT_ALL_DATA_SENT ) ; + /*debug ( "_slurm_msg_sendto only transmitted %i of %i bytes", + send_len , size ) ;*/ + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_IMPL_NOT_ALL_DATA_SENT ) ; goto _slurm_msg_sendto_exit_error ; } else @@ -326,7 +356,8 @@ int _slurm_send_timeout ( slurm_fd open_fd, char *buffer , size_t size , } else if ( rc == 0 ) { - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_ZERO_BYTES_SENT ) ; + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_ZERO_BYTES_SENT ) ; goto _slurm_send_timeout_exit_error; } else @@ -393,7 +424,8 @@ int _slurm_recv_timeout ( slurm_fd open_fd, char *buffer , size_t size , } else if ( rc == 0 ) { - slurm_seterrno ( SLURM_PROTOCOL_SOCKET_ZERO_BYTES_SENT ) ; + slurm_seterrno ( + SLURM_PROTOCOL_SOCKET_ZERO_BYTES_SENT ) ; goto _slurm_recv_timeout_exit_error; } else @@ -427,25 +459,31 @@ slurm_fd _slurm_listen_stream ( slurm_addr * slurm_address ) int rc ; slurm_fd connection_fd ; const int one = 1; - if ( ( connection_fd =_slurm_create_socket ( SLURM_STREAM ) ) == SLURM_SOCKET_ERROR ) + if ( ( connection_fd =_slurm_create_socket ( SLURM_STREAM ) ) + == SLURM_SOCKET_ERROR ) { debug ( "Error creating slurm stream socket: %m" ) ; return connection_fd ; } - if ( ( rc = _slurm_setsockopt(connection_fd , SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one) ) ) ) + if ( ( rc = _slurm_setsockopt(connection_fd , SOL_SOCKET, + SO_REUSEADDR, &one, sizeof(one) ) ) ) { debug ("setsockopt SO_REUSEADDR failed"); goto error_cleanup ; } - if ( ( rc = _slurm_bind ( connection_fd , ( struct sockaddr const * ) slurm_address , sizeof ( slurm_addr ) ) ) == SLURM_SOCKET_ERROR ) + if ( ( rc = _slurm_bind ( connection_fd , + ( struct sockaddr const * ) slurm_address , + sizeof ( slurm_addr ) ) ) == SLURM_SOCKET_ERROR ) { debug ( "Error binding slurm stream socket: %m" ) ; goto error_cleanup ; } - if ( ( rc = _slurm_listen ( connection_fd , SLURM_PROTOCOL_DEFAULT_LISTEN_BACKLOG ) ) == SLURM_SOCKET_ERROR ) + if ( ( rc = _slurm_listen ( connection_fd , + SLURM_PROTOCOL_DEFAULT_LISTEN_BACKLOG ) ) + == SLURM_SOCKET_ERROR ) { debug ( "Error listening on slurm stream socket: %m" ) ; goto error_cleanup ; @@ -464,7 +502,9 @@ slurm_fd _slurm_accept_stream ( slurm_fd open_fd , slurm_addr * slurm_address ) { size_t addr_len = sizeof ( slurm_addr ) ; slurm_fd connection_fd ; - if ( ( connection_fd = _slurm_accept ( open_fd , ( struct sockaddr * ) slurm_address , & addr_len ) ) == SLURM_SOCKET_ERROR ) + if ( ( connection_fd = _slurm_accept ( open_fd , + ( struct sockaddr * ) slurm_address , + & addr_len ) ) == SLURM_SOCKET_ERROR ) { debug ( "Error accepting slurm stream socket: %m" ) ; } @@ -484,13 +524,17 @@ slurm_fd _slurm_open_stream ( slurm_addr * slurm_address ) return SLURM_SOCKET_ERROR; } - if ( ( connection_fd =_slurm_create_socket ( SLURM_STREAM ) ) == SLURM_SOCKET_ERROR ) + if ( ( connection_fd =_slurm_create_socket ( SLURM_STREAM ) ) + == SLURM_SOCKET_ERROR ) { debug ( "Error creating slurm stream socket: %m" ) ; return connection_fd ; } - if ( ( rc = _slurm_connect ( connection_fd , ( struct sockaddr const * ) slurm_address , sizeof ( slurm_addr ) ) ) == SLURM_SOCKET_ERROR ) + if ( ( rc = _slurm_connect ( connection_fd , + ( struct sockaddr const * ) slurm_address , + sizeof ( slurm_addr ) ) ) + == SLURM_SOCKET_ERROR ) { debug ( "Error connecting on slurm stream socket: %m" ) ; goto error_cleanup ; @@ -508,7 +552,8 @@ int _slurm_get_stream_addr ( slurm_fd open_fd , slurm_addr * address ) int size ; size = sizeof ( address ) ; - return _slurm_getsockname ( open_fd , ( struct sockaddr * ) address , & size ) ; + return _slurm_getsockname ( open_fd , ( struct sockaddr * ) address , + & size ) ; } int _slurm_close_stream ( slurm_fd open_fd ) @@ -520,7 +565,8 @@ int _slurm_close_stream ( slurm_fd open_fd ) int _slurm_set_stream_non_blocking ( slurm_fd open_fd ) { int flags ; - if ( ( flags = _slurm_fcntl ( open_fd , F_GETFL ) ) == SLURM_SOCKET_ERROR ) + if ( ( flags = _slurm_fcntl ( open_fd , F_GETFL ) ) + == SLURM_SOCKET_ERROR ) { return SLURM_SOCKET_ERROR ; } @@ -531,7 +577,8 @@ int _slurm_set_stream_non_blocking ( slurm_fd open_fd ) int _slurm_set_stream_blocking ( slurm_fd open_fd ) { int flags ; - if ( ( flags = _slurm_fcntl ( open_fd , F_GETFL ) ) == SLURM_SOCKET_ERROR ) + if ( ( flags = _slurm_fcntl ( open_fd , F_GETFL ) ) + == SLURM_SOCKET_ERROR ) { return SLURM_SOCKET_ERROR ; } @@ -549,10 +596,12 @@ extern slurm_fd _slurm_create_socket ( slurm_socket_type_t type ) switch ( type ) { case SLURM_STREAM : - return _slurm_socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP) ; + return _slurm_socket ( AF_INET, SOCK_STREAM, + IPPROTO_TCP) ; break; case SLURM_MESSAGE : - return _slurm_socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ; + return _slurm_socket ( AF_INET, SOCK_DGRAM, + IPPROTO_UDP ) ; break; default : return SLURM_SOCKET_ERROR; @@ -563,19 +612,22 @@ extern slurm_fd _slurm_create_socket ( slurm_socket_type_t type ) * protocol PROTOCOL, which are connected to each other, and put file * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, * one will be chosen automatically. Returns 0 on success, -1 for errors. */ -extern int _slurm_socketpair (int __domain, int __type, int __protocol, int __fds[2]) +extern int _slurm_socketpair (int __domain, int __type, + int __protocol, int __fds[2]) { return SLURM_PROTOCOL_FUNCTION_NOT_IMPLEMENTED ; } /* Give the socket FD the local address ADDR (which is LEN bytes long). */ -extern int _slurm_bind (int __fd, struct sockaddr const * __addr, socklen_t __len) +extern int _slurm_bind (int __fd, struct sockaddr const * __addr, + socklen_t __len) { return bind ( __fd , __addr , __len ) ; } /* Put the local address of FD into *ADDR and its length in *LEN. */ -extern int _slurm_getsockname (int __fd, struct sockaddr * __addr, socklen_t *__restrict __len) +extern int _slurm_getsockname (int __fd, struct sockaddr * __addr, + socklen_t *__restrict __len) { return getsockname ( __fd , __addr , __len ) ; } @@ -584,20 +636,23 @@ extern int _slurm_getsockname (int __fd, struct sockaddr * __addr, socklen_t *__ * For connectionless socket types, just set the default address to send to * and the only address from which to accept transmissions. * Return 0 on success, -1 for errors. */ -extern int _slurm_connect (int __fd, struct sockaddr const * __addr, socklen_t __len) +extern int _slurm_connect (int __fd, struct sockaddr const * __addr, + socklen_t __len) { return connect ( __fd , __addr , __len ) ; } /* Put the address of the peer connected to socket FD into *ADDR * (which is *LEN bytes long), and its actual length into *LEN. */ -extern int _slurm_getpeername (int __fd, struct sockaddr * __addr, socklen_t *__restrict __len) +extern int _slurm_getpeername (int __fd, struct sockaddr * __addr, + socklen_t *__restrict __len) { return getpeername ( __fd , __addr , __len ) ; } /* Send N bytes of BUF to socket FD. Returns the number sent or -1. */ -extern ssize_t _slurm_send (int __fd, __const void *__buf, size_t __n, int __flags) +extern ssize_t _slurm_send (int __fd, __const void *__buf, size_t __n, + int __flags) { return send ( __fd , __buf , __n , __flags ) ; } @@ -611,7 +666,9 @@ extern ssize_t _slurm_recv (int __fd, void *__buf, size_t __n, int __flags) /* Send N bytes of BUF on socket FD to peer at address ADDR (which is * ADDR_LEN bytes long). Returns the number sent, or -1 for errors. */ -extern ssize_t _slurm_sendto (int __fd, __const void *__buf, size_t __n, int __flags, struct sockaddr const * __addr, socklen_t __addr_len) +extern ssize_t _slurm_sendto (int __fd, __const void *__buf, size_t __n, + int __flags, struct sockaddr const * __addr, + socklen_t __addr_len) { return sendto ( __fd , __buf , __n , __flags , __addr, __addr_len) ; } @@ -619,14 +676,18 @@ extern ssize_t _slurm_sendto (int __fd, __const void *__buf, size_t __n, int __f * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of * the sender, and store the actual size of the address in *ADDR_LEN. * Returns the number of bytes read or -1 for errors. */ -extern ssize_t _slurm_recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags, struct sockaddr * __addr, socklen_t *__restrict __addr_len) +extern ssize_t _slurm_recvfrom (int __fd, void *__restrict __buf, + size_t __n, int __flags, + struct sockaddr * __addr, + socklen_t *__restrict __addr_len) { return recvfrom ( __fd , __buf , __n , __flags , __addr, __addr_len) ; } /* Send a msg described MESSAGE on socket FD. * Returns the number of bytes sent, or -1 for errors. */ -extern ssize_t _slurm_sendmsg (int __fd, __const struct msghdr *__msg, int __flags) +extern ssize_t _slurm_sendmsg (int __fd, __const struct msghdr *__msg, + int __flags) { return sendmsg ( __fd , __msg , __flags ) ; } @@ -641,7 +702,9 @@ extern ssize_t _slurm_recvmsg (int __fd, struct msghdr *__msg, int __flags) /* Put the current value for socket FD's option OPTNAME at protocol level LEVEL * into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's * actual length. Returns 0 on success, -1 for errors. */ -extern int _slurm_getsockopt (int __fd, int __level, int __optname, void *__restrict __optval, socklen_t *__restrict __optlen) +extern int _slurm_getsockopt (int __fd, int __level, int __optname, + void *__restrict __optval, + socklen_t *__restrict __optlen) { return getsockopt ( __fd , __level , __optname , __optval , __optlen ) ; } @@ -649,7 +712,8 @@ extern int _slurm_getsockopt (int __fd, int __level, int __optname, void *__rest /* Set socket FD's option OPTNAME at protocol level LEVEL * to *OPTVAL (which is OPTLEN bytes long). * Returns 0 on success, -1 for errors. */ -extern int _slurm_setsockopt (int __fd, int __level, int __optname, __const void *__optval, socklen_t __optlen) +extern int _slurm_setsockopt (int __fd, int __level, int __optname, + __const void *__optval, socklen_t __optlen) { return setsockopt ( __fd , __level , __optname , __optval , __optlen ) ; } @@ -668,7 +732,8 @@ extern int _slurm_listen (int __fd, int __n) * set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting * peer and *ADDR_LEN to the address's actual length, and return the * new socket's descriptor, or -1 for errors. */ -extern int _slurm_accept (int __fd, struct sockaddr * __addr, socklen_t *__restrict __addr_len) +extern int _slurm_accept (int __fd, struct sockaddr * __addr, + socklen_t *__restrict __addr_len) { return accept ( __fd , __addr , __addr_len ) ; } @@ -689,7 +754,8 @@ extern int _slurm_close (int __fd ) return close ( __fd ) ; } -extern int _slurm_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +extern int _slurm_select(int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) { assert (n <= FD_SETSIZE); /* select data structure overflows */; return select ( n , readfds , writefds , exceptfds , timeout ) ; @@ -745,14 +811,15 @@ extern int _slurm_vfcntl(int fd, int cmd, va_list va ) } /* sets the fields of a slurm_addr */ -void _slurm_set_addr_uint ( slurm_addr * slurm_address , uint16_t port , uint32_t ip_address ) +void _slurm_set_addr_uint ( slurm_addr * slurm_address , uint16_t port , + uint32_t ip_address ) { slurm_address -> sin_family = AF_SLURM ; slurm_address -> sin_port = htons ( port ) ; slurm_address -> sin_addr.s_addr = htonl ( ip_address ) ; } -/* resets the address field of a slurm_addr, port and family remain unchanged */ +/* resets the address field of a slurm_addr, port and family are unchanged */ void _reset_slurm_addr ( slurm_addr * slurm_address , slurm_addr new_address ) { slurm_address -> sin_addr.s_addr = new_address.sin_addr.s_addr ; @@ -763,31 +830,49 @@ void _slurm_set_addr ( slurm_addr * slurm_address , uint16_t port , char * host { _slurm_set_addr_char ( slurm_address , port , host ) ; } -void _slurm_set_addr_char ( slurm_addr * slurm_address , uint16_t port , char * host ) +void _slurm_set_addr_char ( slurm_addr * slurm_address , uint16_t port , + char * host ) { /* If NULL hostname passed in, we only update the port * of slurm_address */ if (host != NULL) { - struct hostent * host_info = gethostbyname( host ); + struct hostent * host_info; + char hostent_buf[TEMP_BUFFER_SIZE]; + host_info = get_host_by_name( host, (void *) &hostent_buf, + sizeof(hostent_buf), NULL ); if (host_info == NULL) { - error ("gethostbyname failure on %s", host); + fatal ("get_host_by_name failure on %s", host); slurm_address->sin_family = 0; slurm_address->sin_port = 0; return; } memcpy ( & slurm_address -> sin_addr . s_addr , host_info -> h_addr , host_info -> h_length ) ; - } + } slurm_address -> sin_family = AF_SLURM ; slurm_address -> sin_port = htons ( port ) ; } -void _slurm_get_addr ( slurm_addr * slurm_address , uint16_t * port , char * host , unsigned int buf_len ) -{ - struct hostent * host_info = gethostbyaddr ( ( char * ) &( slurm_address -> sin_addr . s_addr ) , sizeof ( slurm_address -> sin_addr . s_addr ) , AF_SLURM ) ; - *port = slurm_address -> sin_port ; - strncpy ( host , host_info -> h_name , buf_len ) ; +void _slurm_get_addr ( slurm_addr * slurm_address , uint16_t * port , + char * host , unsigned int buf_len ) +{ + struct hostent * host_info; + char hostent_buf[TEMP_BUFFER_SIZE]; + + host_info = get_host_by_addr ( + ( char * ) &( slurm_address -> sin_addr . s_addr ) , + sizeof ( slurm_address -> sin_addr . s_addr ) , + AF_SLURM, + (void *) &hostent_buf, sizeof(hostent_buf), NULL ); + if (host_info == NULL) { + fatal ("get_host_by_addr failure"); + *port = 0; + strncpy ( host, "", buf_len); + } else { + *port = slurm_address -> sin_port ; + strncpy ( host , host_info -> h_name , buf_len ) ; + } } void _slurm_print_slurm_addr ( slurm_addr * address, char *buf, size_t n ) @@ -808,7 +893,8 @@ int _slurm_unpack_slurm_addr_no_alloc ( slurm_addr * slurm_address , Buf buffer { slurm_address -> sin_family = AF_SLURM ; safe_unpack32 ( & slurm_address -> sin_addr.s_addr , buffer ) ; - slurm_address -> sin_addr.s_addr = htonl ( slurm_address -> sin_addr.s_addr ); + slurm_address -> sin_addr.s_addr = + htonl ( slurm_address -> sin_addr.s_addr ); safe_unpack16 ( & slurm_address -> sin_port , buffer ) ; slurm_address -> sin_port = htons ( slurm_address -> sin_port ) ; return SLURM_SUCCESS; diff --git a/src/common/util-net.c b/src/common/util-net.c new file mode 100644 index 0000000000000000000000000000000000000000..da8179195a35776cc8f32c863fa4a478b12b3652 --- /dev/null +++ b/src/common/util-net.c @@ -0,0 +1,357 @@ +/*****************************************************************************\ + * $Id$ + ***************************************************************************** + * Copyright (C) 2001-2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Chris Dunlap <cdunlap@llnl.gov>. + * UCRL-CODE-2002-009. + * + * This file is part of ConMan, a remote console management program. + * For details, see <http://www.llnl.gov/linux/conman/>. + * + * ConMan is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * ConMan is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with ConMan; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + ***************************************************************************** + * Refer to "util-net.h" for documentation on public functions. +\*****************************************************************************/ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> +#include <netdb.h> +#include <netinet/in.h> +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> + +#include "strlcpy.h" +#include "util-net.h" +#include "wrapper.h" + + +#ifndef INET_ADDRSTRLEN +# define INET_ADDRSTRLEN 16 +#endif /* !INET_ADDRSTRLEN */ + + +static pthread_mutex_t hostentLock = PTHREAD_MUTEX_INITIALIZER; + + +static int copy_hostent(const struct hostent *src, char *dst, int len); +#ifndef NDEBUG +static int validate_hostent_copy( + const struct hostent *src, const struct hostent *dst); +#endif /* !NDEBUG */ + + +struct hostent * get_host_by_name(const char *name, + void *buf, int buflen, int *h_err) +{ +/* gethostbyname() is not thread-safe, and there is no frelling standard + * for gethostbyname_r() -- the arg list varies from system to system! + */ + struct hostent *hptr; + int n = 0; + + assert(name != NULL); + assert(buf != NULL); + + x_pthread_mutex_lock(&hostentLock); + if ((hptr = gethostbyname(name))) + n = copy_hostent(hptr, buf, buflen); + if (h_err) + *h_err = h_errno; + x_pthread_mutex_unlock(&hostentLock); + + if (n < 0) { + errno = ERANGE; + return(NULL); + } + return(hptr ? (struct hostent *) buf : NULL); +} + + +struct hostent * get_host_by_addr(const char *addr, int len, int type, + void *buf, int buflen, int *h_err) +{ +/* gethostbyaddr() is not thread-safe, and there is no frelling standard + * for gethostbyaddr_r() -- the arg list varies from system to system! + */ + struct hostent *hptr; + int n = 0; + + assert(addr != NULL); + assert(buf != NULL); + + x_pthread_mutex_lock(&hostentLock); + if ((hptr = gethostbyaddr(addr, len, type))) + n = copy_hostent(hptr, buf, buflen); + if (h_err) + *h_err = h_errno; + x_pthread_mutex_unlock(&hostentLock); + + if (n < 0) { + errno = ERANGE; + return(NULL); + } + return(hptr ? (struct hostent *) buf : NULL); +} + + +const char * host_strerror(int h_err) +{ + if (h_err == HOST_NOT_FOUND) + return("Unknown host"); + else if (h_err == TRY_AGAIN) + return("Transient host name lookup failure"); + else if (h_err == NO_RECOVERY) + return("Unknown server error"); + else if ((h_err == NO_ADDRESS) || (h_err == NO_DATA)) + return("No address associated with name"); + return("Unknown error"); +} + + +int host_name_to_addr4(const char *name, struct in_addr *addr) +{ + struct hostent *hptr; + unsigned char buf[HOSTENT_SIZE]; + + assert(name != NULL); + assert(addr != NULL); + + if (!(hptr = get_host_by_name(name, buf, sizeof(buf), NULL))) + return(-1); + if (hptr->h_length > 4) { + errno = ERANGE; + return(-1); + } + memcpy(addr, hptr->h_addr_list[0], hptr->h_length); + return(0); +} + + +char * host_addr4_to_name(const struct in_addr *addr, char *dst, int dstlen) +{ + struct hostent *hptr; + unsigned char buf[HOSTENT_SIZE]; + + assert(addr != NULL); + assert(dst != NULL); + + if (!(hptr = get_host_by_addr((char *) addr, 4, AF_INET, + buf, sizeof(buf), NULL))) + return(NULL); + if (strlen(hptr->h_name) >= dstlen) { + errno = ERANGE; + return(NULL); + } + strcpy(dst, hptr->h_name); + return(dst); +} + + +char * host_name_to_cname(const char *src, char *dst, int dstlen) +{ + struct hostent *hptr; + unsigned char buf[HOSTENT_SIZE]; + struct in_addr addr; + + assert(src != NULL); + assert(dst != NULL); + + if (!(hptr = get_host_by_name(src, buf, sizeof(buf), NULL))) + return(NULL); + /* + * If 'src' is an ip-addr string, it will simply be copied to h_name. + * So, we need to perform a reverse query based on the in_addr + * in order to obtain the canonical name of the host. + * Besides, this additional query helps protect against DNS spoofing. + */ + memcpy(&addr, hptr->h_addr_list[0], hptr->h_length); + if (!(hptr = get_host_by_addr((char *) &addr, 4, AF_INET, + buf, sizeof(buf), NULL))) + return(NULL); + if (strlen(hptr->h_name) >= dstlen) { + errno = ERANGE; + return(NULL); + } + strcpy(dst, hptr->h_name); + return(dst); +} + + +static int copy_hostent(const struct hostent *src, char *buf, int len) +{ +/* Copies the (src) hostent struct (and all of its associated data) + * into the buffer (buf) of length (len). + * Returns 0 if the copy is successful, or -1 if the length of the buffer + * is not large enough to hold the result. + * + * Note that the order in which data is copied into (buf) is done + * in such a way as to ensure everything is properly word-aligned. + * There is a method to the madness. + */ + struct hostent *dst; + int n; + char **p, **q; + + assert(src != NULL); + assert(buf != NULL); + + dst = (struct hostent *) buf; + if ((len -= sizeof(struct hostent)) < 0) + return(-1); + dst->h_addrtype = src->h_addrtype; + dst->h_length = src->h_length; + buf += sizeof(struct hostent); + + /* Reserve space for h_aliases[]. + */ + dst->h_aliases = (char **) buf; + for (p=src->h_aliases, q=dst->h_aliases, n=0; *p; p++, q++, n++) {;} + if ((len -= ++n * sizeof(char *)) < 0) + return(-1); + buf = (char *) (q + 1); + + /* Reserve space for h_addr_list[]. + */ + dst->h_addr_list = (char **) buf; + for (p=src->h_addr_list, q=dst->h_addr_list, n=0; *p; p++, q++, n++) {;} + if ((len -= ++n * sizeof(char *)) < 0) + return(-1); + buf = (char *) (q + 1); + + /* Copy h_addr_list[] in_addr structs. + */ + for (p=src->h_addr_list, q=dst->h_addr_list; *p; p++, q++) { + if ((len -= src->h_length) < 0) + return(-1); + memcpy(buf, *p, src->h_length); + *q = buf; + buf += src->h_length; + } + *q = NULL; + + /* Copy h_aliases[] strings. + */ + for (p=src->h_aliases, q=dst->h_aliases; *p; p++, q++) { + n = strlcpy(buf, *p, len); + *q = buf; + buf += ++n; /* allow for trailing NUL char */ + if ((len -= n) < 0) + return(-1); + } + *q = NULL; + + /* Copy h_name string. + */ + dst->h_name = buf; + n = strlcpy(buf, src->h_name, len); + buf += ++n; /* allow for trailing NUL char */ + if ((len -= n) < 0) + return(-1); + + assert(validate_hostent_copy(src, dst) >= 0); + return(0); +} + + +#ifndef NDEBUG +static int validate_hostent_copy( + const struct hostent *src, const struct hostent *dst) +{ +/* Validates the src hostent struct has been successfully copied into dst. + * Returns 0 if the copy is good; o/w, returns -1. + */ + char **p, **q; + + assert(src != NULL); + assert(dst != NULL); + + if (!dst->h_name) + return(-1); + if (src->h_name == dst->h_name) + return(-1); + if (strcmp(src->h_name, dst->h_name)) + return(-1); + if (src->h_addrtype != dst->h_addrtype) + return(-1); + if (src->h_length != dst->h_length) + return(-1); + for (p=src->h_aliases, q=dst->h_aliases; *p; p++, q++) + if ((!q) || (p == q) || (strcmp(*p, *q))) + return(-1); + for (p=src->h_addr_list, q=dst->h_addr_list; *p; p++, q++) + if ((!q) || (p == q) || (memcmp(*p, *q, src->h_length))) + return(-1); + return(0); +} +#endif /* !NDEBUG */ + + +#ifndef HAVE_INET_PTON +int inet_pton(int family, const char *str, void *addr) +{ +/* cf. Stevens UNPv1 p72. + */ + struct in_addr tmpaddr; + + if (family != AF_INET) { + errno = EAFNOSUPPORT; + return(-1); + } +#ifdef HAVE_INET_ATON + if (!inet_aton(str, &tmpaddr)) + return(0); +#else /* !HAVE_INET_ATON */ + if ((tmpaddr.s_addr = inet_addr(str)) == -1) + return(0); +#endif /* !HAVE_INET_ATON */ + + memcpy(addr, &tmpaddr, sizeof(struct in_addr)); + return(1); +} +#endif /* !HAVE_INET_PTON */ + + +#ifndef HAVE_INET_NTOP +const char * inet_ntop(int family, const void *addr, char *str, size_t len) +{ +/* cf. Stevens UNPv1 p72. + */ + const unsigned char *p = (const unsigned char *) addr; + char tmpstr[INET_ADDRSTRLEN]; + + assert(str != NULL); + + if (family != AF_INET) { + errno = EAFNOSUPPORT; + return(NULL); + } + snprintf(tmpstr, sizeof(tmpstr), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + if (strlen(tmpstr) >= len) { + errno = ENOSPC; + return(NULL); + } + strcpy(str, tmpstr); + return(str); +} +#endif /* !HAVE_INET_NTOP */ diff --git a/src/common/util-net.h b/src/common/util-net.h new file mode 100644 index 0000000000000000000000000000000000000000..967a5fb1f85e54539a5b7b0951930a62e5780732 --- /dev/null +++ b/src/common/util-net.h @@ -0,0 +1,116 @@ +/*****************************************************************************\ + * $Id$ + ***************************************************************************** + * Copyright (C) 2001-2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Chris Dunlap <cdunlap@llnl.gov>. + * UCRL-CODE-2002-009. + * + * This file is part of ConMan, a remote console management program. + * For details, see <http://www.llnl.gov/linux/conman/>. + * + * ConMan is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * ConMan is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with ConMan; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + + +#ifndef _UTIL_NET_H +#define _UTIL_NET_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <netdb.h> +#include <netinet/in.h> +#include <unistd.h> + + +#define HOSTENT_SIZE 8192 /* cf. Stevens UNPv1 11.15 p304 */ + + +struct hostent * get_host_by_name(const char *name, + void *buf, int buflen, int *h_err); +/* + * A portable thread-safe alternative to be used in place of gethostbyname(). + * The result is stored in the buffer (buf) of length (buflen); if the buffer + * is too small to hold the result, NULL is returned with errno = ERANGE. + * Returns a ptr into (buf) on success; returns NULL on error, setting the + * (h_err) variable reference (if not NULL) to indicate the h_error. + */ + +struct hostent * get_host_by_addr(const char *addr, int len, int type, + void *buf, int buflen, int *h_err); +/* + * A portable thread-safe alternative to be used in place of gethostbyaddr(). + * The result is stored in the buffer (buf) of length (buflen); if the buffer + * is too small to hold the result, NULL is returned with errno = ERANGE. + * Returns a ptr into (buf) on success; returns NULL on error, setting the + * (h_err) variable reference (if not NULL) to indicate the h_error. + */ + +const char * host_strerror(int h_err); +/* + * Returns a string describing the error code (h_err) returned by + * get_host_by_name() or get_host_by_addr(). + */ + +int host_name_to_addr4(const char *name, struct in_addr *addr); +/* + * Converts the string (name) to an IPv4 address (addr). + * Returns 0 on success, or -1 on error. + * Note that this routine is thread-safe. + */ + +char * host_addr4_to_name(const struct in_addr *addr, char *dst, int dstlen); +/* + * Converts an IPv4 address (addr) to a host name string residing in + * buffer (dst) of length (dstlen). + * Returns a ptr to the NULL-terminated string (dst) on success, + * or NULL on error. + * Note that this routine is thread-safe. + */ + +char * host_name_to_cname(const char *src, char *dst, int dstlen); +/* + * Converts the hostname or IP address string (src) to the + * canonical name of the host residing in buffer (dst) of length (dstlen). + * Returns a ptr to the NULL-terminated string (dst) on success, + * or NULL on error. + * Note that this routine is thread-safe. + */ + +#ifndef HAVE_INET_PTON +int inet_pton(int family, const char *str, void *addr); +/* + * Convert from presentation format of an internet number in (str) + * to the binary network format, storing the result for interface + * type (family) in the socket address structure specified by (addr). + * Returns 1 if OK, 0 if input not a valid presentation format, -1 on error. + */ +#endif /* !HAVE_INET_PTON */ + +#ifndef HAVE_INET_NTOP +const char * inet_ntop(int family, const void *addr, char *str, size_t len); +/* + * Convert an Internet address in binary network format for interface + * type (family) in the socket address structure specified by (addr), + * storing the result in the buffer (str) of length (len). + * Returns ptr to result buffer if OK, or NULL on error. + */ +#endif /* !HAVE_INET_NTOP */ + + +#endif /* !_UTIL_NET_H */ diff --git a/src/common/wrapper.h b/src/common/wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..ad9c35e38ab08d2f2bdd731077697e9d02fcb7c3 --- /dev/null +++ b/src/common/wrapper.h @@ -0,0 +1,83 @@ +/*****************************************************************************\ + * $Id$ + ***************************************************************************** + * Copyright (C) 2001-2002 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Chris Dunlap <cdunlap@llnl.gov>. + * UCRL-CODE-2002-009. + * + * This file is part of ConMan, a remote console management program. + * For details, see <http://www.llnl.gov/linux/conman/>. + * + * ConMan is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * ConMan is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with ConMan; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +\*****************************************************************************/ + + +#ifndef _WRAPPER_H +#define _WRAPPER_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <errno.h> +#include "log.h" + + +#ifdef WITH_PTHREADS + +# define x_pthread_mutex_init(MUTEX,ATTR) \ + do { \ + if ((errno = pthread_mutex_init((MUTEX), (ATTR))) != 0) \ + error("pthread_mutex_init() failed: %m"); \ + } while (0) + +# define x_pthread_mutex_lock(MUTEX) \ + do { \ + if ((errno = pthread_mutex_lock(MUTEX)) != 0) \ + error("pthread_mutex_lock() failed: %m"); \ + } while (0) + +# define x_pthread_mutex_unlock(MUTEX) \ + do { \ + if ((errno = pthread_mutex_unlock(MUTEX)) != 0) \ + error("pthread_mutex_unlock() failed: %m"); \ + } while (0) + +# define x_pthread_mutex_destroy(MUTEX) \ + do { \ + if ((errno = pthread_mutex_destroy(MUTEX)) != 0) \ + error("pthread_mutex_destroy() failed: %m"); \ + } while (0) + +# define x_pthread_detach(THREAD) \ + do { \ + if ((errno = pthread_detach(THREAD)) != 0) \ + error("pthread_detach() failed: %m"); \ + } while (0) + +#else /* !WITH_PTHREADS */ + +# define x_pthread_mutex_init(MUTEX,ATTR) +# define x_pthread_mutex_lock(MUTEX) +# define x_pthread_mutex_unlock(MUTEX) +# define x_pthread_mutex_destroy(MUTEX) +# define x_pthread_detach(THREAD) + +#endif /* !WITH_PTHREADS */ + + +#endif /* !_WRAPPER_H */