X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=net.c;h=e7c7724b4143e33ac7fbd7d79ba8ee1c5fd38bdf;hp=d4472c0e2805ecb898ef4caae85a96980fe6d447;hb=c4012aab461993e6c8a9930d27d924a8462a9775;hpb=c3db896887ec2c79d0fea9c29637709f5f844820 diff --git a/net.c b/net.c index d4472c0e..e7c7724b 100644 --- a/net.c +++ b/net.c @@ -21,11 +21,59 @@ #include "para.h" #include "net.h" #include "string.h" -#include #include "error.h" -extern void (*crypt_function_recv)(unsigned long len, const unsigned char *indata, unsigned char *outdata); -extern void (*crypt_function_send)(unsigned long len, const unsigned char *indata, unsigned char *outdata); + +/** \cond holds information about one encrypted connection */ +struct crypt_data { + crypt_function *recv; + crypt_function *send; + void *private_data; +}; +static unsigned cda_size = 0; +static struct crypt_data *crypt_data_array; +/** \endcond */ + + +/** + * activate encryption for one file descriptor + * + * \param fd the file descriptor + * \param recv_f the function used for decrypting received data + * \param send_f the function used for encrypting before sending + * \param private_data user data supplied by the caller + */ +void enable_crypt(int fd, crypt_function *recv_f, crypt_function *send_f, + void *private_data) +{ + if (fd + 1 > cda_size) { + crypt_data_array = para_realloc(crypt_data_array, + (fd + 1) * sizeof(struct crypt_data)); + memset(crypt_data_array + cda_size, 0, + (fd + 1 - cda_size) * sizeof(struct crypt_data)); + cda_size = fd + 1; + } + crypt_data_array[fd].recv = recv_f; + crypt_data_array[fd].send = send_f; + crypt_data_array[fd].private_data = private_data; + PARA_INFO_LOG("rc4 encryption activated for fd %d\n", fd); +} + +/** + * deactivate encryption for a given fd + * + * \param fd the file descriptor + * + * This must be called if and only if \p fd was activated via enable_crypt(). + */ +void disable_crypt(int fd) +{ + if (cda_size < fd + 1) + return; + crypt_data_array[fd].recv = NULL; + crypt_data_array[fd].send = NULL; + crypt_data_array[fd].private_data = NULL; +} /** @@ -96,12 +144,16 @@ static int sendall(int fd, const char *buf, size_t *len) int send_bin_buffer(int fd, const char *buf, size_t len) { int ret; + crypt_function *cf = NULL; if (!len) PARA_CRIT_LOG("%s", "len == 0\n"); - if (crypt_function_send) { + if (fd + 1 <= cda_size) + cf = crypt_data_array[fd].send; + if (cf) { + void *private = crypt_data_array[fd].private_data; unsigned char *outbuf = para_malloc(len); - crypt_function_send(len, (unsigned char *)buf, outbuf); + (*cf)(len, (unsigned char *)buf, outbuf, private); ret = sendall(fd, (char *)outbuf, &len); free(outbuf); } else @@ -160,12 +212,16 @@ __printf_2_3 int send_va_buffer(int fd, const char *fmt, ...) __must_check int recv_bin_buffer(int fd, char *buf, ssize_t size) { int n; + crypt_function *cf = NULL; - if (crypt_function_recv) { + if (fd + 1 <= cda_size) + cf = crypt_data_array[fd].recv; + if (cf) { unsigned char *tmp = para_malloc(size); + void *private = crypt_data_array[fd].private_data; n = recv(fd, tmp, size, 0); if (n > 0) - crypt_function_recv(n, tmp, (unsigned char *)buf); + (*cf)(n, tmp, (unsigned char *)buf, private); free(tmp); } else n = recv(fd, buf, size, 0); @@ -200,15 +256,20 @@ int recv_buffer(int fd, char *buf, ssize_t size) /** * wrapper around gethostbyname * - * @param host hostname or IPv4 address - * \return The hostent structure or a NULL pointer if an error occurs + * \param host hostname or IPv4 address + * \param ret the hostent structure is returned here + * + * \return positive on success, negative on errors. On success, \a ret + * contains the return value of the underlying gethostbyname() call. + * * \sa gethostbyname(2) */ -struct hostent *get_host_info(char *host) +int get_host_info(char *host, struct hostent **ret) { PARA_INFO_LOG("getting host info of %s\n", host); /* FIXME: gethostbyname() is obsolete */ - return gethostbyname(host); + *ret = gethostbyname(host); + return *ret? 1 : -E_HOST_INFO; } /** @@ -251,9 +312,9 @@ int para_connect(int fd, struct sockaddr_in *their_addr) /** * paraslash's wrapper around the accept system call * - * @param fd the listening socket - * @param addr structure which is filled in with the address of the peer socket - * @param size should contain the size of the structure pointed to by \a addr + * \param fd the listening socket + * \param addr structure which is filled in with the address of the peer socket + * \param size should contain the size of the structure pointed to by \a addr * * \sa accept(2). */ @@ -261,8 +322,10 @@ int para_accept(int fd, void *addr, socklen_t size) { int new_fd; - new_fd = accept(fd, (struct sockaddr *) addr, &size); - return new_fd == -1? -E_ACCEPT : new_fd; + do + new_fd = accept(fd, (struct sockaddr *) addr, &size); + while (new_fd < 0 && errno == EINTR); + return new_fd < 0? -E_ACCEPT : new_fd; } static int setserversockopts(int socket_fd) @@ -275,14 +338,6 @@ static int setserversockopts(int socket_fd) return 1; } -static int do_bind(int socket_fd, struct sockaddr_in *my_addr) -{ - if (bind(socket_fd, (struct sockaddr *)my_addr, - sizeof(struct sockaddr)) == -1) - return -E_BIND; - return 1; -} - /** * prepare a structure for \p AF_UNIX socket addresses * @@ -336,9 +391,6 @@ int create_pf_socket(const char *name, struct sockaddr_un *unix_addr, int mode) } #ifndef HAVE_UCRED - struct ucred { - uid_t uid, pid, gid; -}; ssize_t send_cred_buffer(int sock, char *buf) { return send_buffer(sock, buf); @@ -471,22 +523,30 @@ int recv_cred_buffer(int fd, char *buf, size_t size) */ int init_tcp_socket(int port) { - int sockfd, ret; struct sockaddr_in my_addr; + int fd, ret = get_socket(); - if ((sockfd = get_socket()) < 0) - return sockfd; - ret = setserversockopts(sockfd); if (ret < 0) return ret; - init_sockaddr(&my_addr, port, NULL); - ret = do_bind(sockfd, &my_addr); + fd = ret; + ret = setserversockopts(fd); if (ret < 0) - return ret; - if (listen(sockfd, BACKLOG) == -1) - return -E_LISTEN; - PARA_INFO_LOG("listening on port %d, fd %d\n", port, sockfd); - return sockfd; + goto err; + init_sockaddr(&my_addr, port, NULL); + ret = -E_BIND; + if (bind(fd, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr)) == -1) { + PARA_CRIT_LOG("bind error: %s\n", strerror(errno)); + goto err; + } + ret = -E_LISTEN; + if (listen(fd, BACKLOG) == -1) + goto err; + PARA_INFO_LOG("listening on port %d, fd %d\n", port, fd); + return fd; +err: + close(fd); + return ret; } /** @@ -517,8 +577,11 @@ int recv_pattern(int fd, const char *pattern, size_t bufsize) goto out; ret = 1; out: - if (ret < 0) - PARA_NOTICE_LOG("did not receive pattern '%s'\n", pattern); + if (ret < 0) { + PARA_NOTICE_LOG("n = %d, did not receive pattern '%s'\n", n, pattern); + if (n > 0) + PARA_NOTICE_LOG("recvd: %s\n", buf); + } free(buf); return ret; }