diff options
Diffstat (limited to '')
-rw-r--r-- | src/network.c | 470 |
1 files changed, 246 insertions, 224 deletions
diff --git a/src/network.c b/src/network.c index 42feac3..7b4bb52 100644 --- a/src/network.c +++ b/src/network.c @@ -33,35 +33,37 @@ * again. Keep sending until the buffer has been sent. */ ssize_t -safe_write(int fd, const char *buffer, size_t count) +safe_write (int fd, const char *buffer, size_t count) { - ssize_t len; - size_t bytestosend; + ssize_t len; + size_t bytestosend; - assert(fd >= 0); - assert(buffer != NULL); - assert(count > 0); + assert (fd >= 0); + assert (buffer != NULL); + assert (count > 0); - bytestosend = count; + bytestosend = count; - while (1) { - len = send(fd, buffer, bytestosend, MSG_NOSIGNAL); + while (1) + { + len = send (fd, buffer, bytestosend, MSG_NOSIGNAL); - if (len < 0) { - if (errno == EINTR) - continue; - else - return -errno; - } + if (len < 0) + { + if (errno == EINTR) + continue; + else + return -errno; + } - if (len == bytestosend) - break; + if (len == bytestosend) + break; - buffer += len; - bytestosend -= len; - } + buffer += len; + bytestosend -= len; + } - return count; + return count; } /* @@ -69,15 +71,17 @@ safe_write(int fd, const char *buffer, size_t count) * again. */ ssize_t -safe_read(int fd, char *buffer, size_t count) +safe_read (int fd, char *buffer, size_t count) { - ssize_t len; + ssize_t len; - do { - len = read(fd, buffer, count); - } while (len < 0 && errno == EINTR); + do + { + len = read (fd, buffer, count); + } + while (len < 0 && errno == EINTR); - return len; + return len; } /* @@ -87,47 +91,51 @@ safe_read(int fd, char *buffer, size_t count) * (although I did fix a memory leak. :) */ int -write_message(int fd, const char *fmt, ...) +write_message (int fd, const char *fmt, ...) { - ssize_t n; - size_t size = (1024 * 8); /* start with 8 KB and go from there */ - char *buf, *tmpbuf; - va_list ap; - - if ((buf = safemalloc(size)) == NULL) - return -1; - - while (1) { - va_start(ap, fmt); - n = vsnprintf(buf, size, fmt, ap); - va_end(ap); - - /* If that worked, break out so we can send the buffer */ - if (n > -1 && n < size) - break; - - /* Else, try again with more space */ - if (n > -1) - /* precisely what is needed (glibc2.1) */ - size = n + 1; - else - /* twice the old size (glibc2.0) */ - size *= 2; - - if ((tmpbuf = saferealloc(buf, size)) == NULL) { - safefree(buf); - return -1; - } else - buf = tmpbuf; - } - - if (safe_write(fd, buf, n) < 0) { - safefree(buf); - return -1; - } - - safefree(buf); - return 0; + ssize_t n; + size_t size = (1024 * 8); /* start with 8 KB and go from there */ + char *buf, *tmpbuf; + va_list ap; + + if ((buf = safemalloc (size)) == NULL) + return -1; + + while (1) + { + va_start (ap, fmt); + n = vsnprintf (buf, size, fmt, ap); + va_end (ap); + + /* If that worked, break out so we can send the buffer */ + if (n > -1 && n < size) + break; + + /* Else, try again with more space */ + if (n > -1) + /* precisely what is needed (glibc2.1) */ + size = n + 1; + else + /* twice the old size (glibc2.0) */ + size *= 2; + + if ((tmpbuf = saferealloc (buf, size)) == NULL) + { + safefree (buf); + return -1; + } + else + buf = tmpbuf; + } + + if (safe_write (fd, buf, n) < 0) + { + safefree (buf); + return -1; + } + + safefree (buf); + return 0; } /* @@ -142,103 +150,113 @@ write_message(int fd, const char *fmt, ...) #define SEGMENT_LEN (512) #define MAXIMUM_BUFFER_LENGTH (128 * 1024) ssize_t -readline(int fd, char **whole_buffer) +readline (int fd, char **whole_buffer) { - ssize_t whole_buffer_len; - char buffer[SEGMENT_LEN]; - char *ptr; - - ssize_t ret; - ssize_t diff; - - struct read_lines_s { - char *data; - size_t len; - struct read_lines_s *next; - }; - struct read_lines_s *first_line, *line_ptr; - - first_line = safecalloc(sizeof(struct read_lines_s), 1); - if (!first_line) - return -ENOMEM; - - line_ptr = first_line; - - whole_buffer_len = 0; - for (;;) { - ret = recv(fd, buffer, SEGMENT_LEN, MSG_PEEK); - if (ret <= 0) - goto CLEANUP; - - ptr = memchr(buffer, '\n', ret); - if (ptr) - diff = ptr - buffer + 1; - else - diff = ret; - - whole_buffer_len += diff; - - /* - * Don't allow the buffer to grow without bound. If we - * get to more than MAXIMUM_BUFFER_LENGTH close. - */ - if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH) { - ret = -ERANGE; - goto CLEANUP; - } - - line_ptr->data = safemalloc(diff); - if (!line_ptr->data) { - ret = -ENOMEM; - goto CLEANUP; - } - - recv(fd, line_ptr->data, diff, 0); - line_ptr->len = diff; - - if (ptr) { - line_ptr->next = NULL; - break; - } - - line_ptr->next = safecalloc(sizeof(struct read_lines_s), 1); - if (!line_ptr->next) { - ret = -ENOMEM; - goto CLEANUP; - } - line_ptr = line_ptr->next; - } - - *whole_buffer = safemalloc(whole_buffer_len + 1); - if (!*whole_buffer) { - ret = -ENOMEM; - goto CLEANUP; - } - - *(*whole_buffer + whole_buffer_len) = '\0'; - - whole_buffer_len = 0; - line_ptr = first_line; - while (line_ptr) { - memcpy(*whole_buffer + whole_buffer_len, line_ptr->data, - line_ptr->len); - whole_buffer_len += line_ptr->len; - - line_ptr = line_ptr->next; - } - - ret = whole_buffer_len; - - CLEANUP: - do { - line_ptr = first_line->next; - if (first_line->data) - safefree(first_line->data); - safefree(first_line); - first_line = line_ptr; - } while (first_line); - - return ret; + ssize_t whole_buffer_len; + char buffer[SEGMENT_LEN]; + char *ptr; + + ssize_t ret; + ssize_t diff; + + struct read_lines_s + { + char *data; + size_t len; + struct read_lines_s *next; + }; + struct read_lines_s *first_line, *line_ptr; + + first_line = safecalloc (sizeof (struct read_lines_s), 1); + if (!first_line) + return -ENOMEM; + + line_ptr = first_line; + + whole_buffer_len = 0; + for (;;) + { + ret = recv (fd, buffer, SEGMENT_LEN, MSG_PEEK); + if (ret <= 0) + goto CLEANUP; + + ptr = memchr (buffer, '\n', ret); + if (ptr) + diff = ptr - buffer + 1; + else + diff = ret; + + whole_buffer_len += diff; + + /* + * Don't allow the buffer to grow without bound. If we + * get to more than MAXIMUM_BUFFER_LENGTH close. + */ + if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH) + { + ret = -ERANGE; + goto CLEANUP; + } + + line_ptr->data = safemalloc (diff); + if (!line_ptr->data) + { + ret = -ENOMEM; + goto CLEANUP; + } + + recv (fd, line_ptr->data, diff, 0); + line_ptr->len = diff; + + if (ptr) + { + line_ptr->next = NULL; + break; + } + + line_ptr->next = safecalloc (sizeof (struct read_lines_s), 1); + if (!line_ptr->next) + { + ret = -ENOMEM; + goto CLEANUP; + } + line_ptr = line_ptr->next; + } + + *whole_buffer = safemalloc (whole_buffer_len + 1); + if (!*whole_buffer) + { + ret = -ENOMEM; + goto CLEANUP; + } + + *(*whole_buffer + whole_buffer_len) = '\0'; + + whole_buffer_len = 0; + line_ptr = first_line; + while (line_ptr) + { + memcpy (*whole_buffer + whole_buffer_len, line_ptr->data, + line_ptr->len); + whole_buffer_len += line_ptr->len; + + line_ptr = line_ptr->next; + } + + ret = whole_buffer_len; + +CLEANUP: + do + { + line_ptr = first_line->next; + if (first_line->data) + safefree (first_line->data); + safefree (first_line); + first_line = line_ptr; + } + while (first_line); + + return ret; } /* @@ -246,32 +264,35 @@ readline(int fd, char **whole_buffer) * hex string. */ char * -get_ip_string(struct sockaddr *sa, char *buf, size_t buflen) +get_ip_string (struct sockaddr *sa, char *buf, size_t buflen) { - assert(sa != NULL); - assert(buf != NULL); - assert(buflen != 0); - buf[0] = '\0'; /* start with an empty string */ - - switch (sa->sa_family) { - case AF_INET:{ - struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; - - inet_ntop(AF_INET, &sa_in->sin_addr, buf, buflen); - break; - } - case AF_INET6:{ - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; - - inet_ntop(AF_INET6, &sa_in6->sin6_addr, buf, buflen); - break; - } - default: - /* no valid family */ - return NULL; - } - - return buf; + assert (sa != NULL); + assert (buf != NULL); + assert (buflen != 0); + buf[0] = '\0'; /* start with an empty string */ + + switch (sa->sa_family) + { + case AF_INET: + { + struct sockaddr_in *sa_in = (struct sockaddr_in *) sa; + + inet_ntop (AF_INET, &sa_in->sin_addr, buf, buflen); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) sa; + + inet_ntop (AF_INET6, &sa_in6->sin6_addr, buf, buflen); + break; + } + default: + /* no valid family */ + return NULL; + } + + return buf; } /* @@ -282,41 +303,42 @@ get_ip_string(struct sockaddr *sa, char *buf, size_t buflen) * Returns the same as inet_pton(). */ int -full_inet_pton(const char *ip, void *dst) +full_inet_pton (const char *ip, void *dst) { - char buf[24], tmp[24]; /* IPv4->IPv6 = ::FFFF:xxx.xxx.xxx.xxx\0 */ - int n; - - assert(ip != NULL && strlen(ip) != 0); - assert(dst != NULL); - - /* - * Check if the string is an IPv4 numeric address. We use the - * older inet_aton() call since it handles more IPv4 numeric - * address formats. - */ - n = inet_aton(ip, (struct in_addr *)dst); - if (n == 0) { - /* - * Simple case: "ip" wasn't an IPv4 numeric address, so - * try doing the conversion as an IPv6 address. This - * will either succeed or fail, but we can't do any - * more processing anyway. - */ - return inet_pton(AF_INET6, ip, dst); - } - - /* - * "ip" was an IPv4 address, so we need to convert it to - * an IPv4-mapped IPv6 address and do the conversion - * again to get the IPv6 network structure. - * - * We convert the IPv4 binary address back into the - * standard dotted-decimal format using inet_ntop() - * so we can be sure that inet_pton will accept the - * full string. - */ - snprintf(buf, sizeof(buf), "::ffff:%s", - inet_ntop(AF_INET, dst, tmp, sizeof(tmp))); - return inet_pton(AF_INET6, buf, dst); + char buf[24], tmp[24]; /* IPv4->IPv6 = ::FFFF:xxx.xxx.xxx.xxx\0 */ + int n; + + assert (ip != NULL && strlen (ip) != 0); + assert (dst != NULL); + + /* + * Check if the string is an IPv4 numeric address. We use the + * older inet_aton() call since it handles more IPv4 numeric + * address formats. + */ + n = inet_aton (ip, (struct in_addr *) dst); + if (n == 0) + { + /* + * Simple case: "ip" wasn't an IPv4 numeric address, so + * try doing the conversion as an IPv6 address. This + * will either succeed or fail, but we can't do any + * more processing anyway. + */ + return inet_pton (AF_INET6, ip, dst); + } + + /* + * "ip" was an IPv4 address, so we need to convert it to + * an IPv4-mapped IPv6 address and do the conversion + * again to get the IPv6 network structure. + * + * We convert the IPv4 binary address back into the + * standard dotted-decimal format using inet_ntop() + * so we can be sure that inet_pton will accept the + * full string. + */ + snprintf (buf, sizeof (buf), "::ffff:%s", + inet_ntop (AF_INET, dst, tmp, sizeof (tmp))); + return inet_pton (AF_INET6, buf, dst); } |