From: Arran Cudbard-Bell Date: Wed, 22 Feb 2023 19:24:00 +0000 (-0600) Subject: linelog: Hexdump what we're writing at >= debug level 3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41df26c459269776112e8ca3a3f14b93851768f5;p=thirdparty%2Ffreeradius-server.git linelog: Hexdump what we're writing at >= debug level 3 --- diff --git a/src/lib/util/iovec.c b/src/lib/util/iovec.c new file mode 100644 index 00000000000..495308e1bd4 --- /dev/null +++ b/src/lib/util/iovec.c @@ -0,0 +1,144 @@ +/* + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** Functions for a basic binary heaps + * + * @file src/lib/util/iovec.c + * + * @copyright 2023 Arran Cudbard-Bell + */ +RCSID("$Id$") + +#include +#include +#include + +/** Concatenate an iovec into a dbuff + * + * @param[out] out dbuff to write to. + * @param[in] vector to concatenate. + * @param[in] iovcnt length of vector array. + * @return + * - >= 0 on success. + * - <0 on failure. + */ +fr_slen_t fr_concatv(fr_dbuff_t *out, struct iovec vector[], int iovcnt) +{ + int i; + + fr_dbuff_t our_out = FR_DBUFF(out); + + for (i = 0; i < iovcnt; i++) FR_DBUFF_IN_MEMCPY_RETURN(&our_out, + (uint8_t *)vector[i].iov_base, vector[i].iov_len); + + return fr_dbuff_set(out, &our_out); +} + +/** Write out a vector to a file descriptor + * + * Wraps writev, calling it as necessary. If timeout is not NULL, + * timeout is applied to each call that returns EAGAIN or EWOULDBLOCK + * + * @note Should only be used on nonblocking file descriptors. + * @note Socket should likely be closed on timeout. + * @note iovec may be modified in such a way that it's not re-usable. + * @note Leaves errno set to the last error that occurred. + * + * @param fd to write to. + * @param vector to write. + * @param iovcnt number of elements in iovec. + * @param timeout how long to wait for fd to become writable before timing out. + * @return + * - Number of bytes written. + * - -1 on failure. + */ +ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t timeout) +{ + struct iovec *vector_p = vector; + ssize_t total = 0; + + while (iovcnt > 0) { + ssize_t wrote; + + wrote = writev(fd, vector_p, iovcnt); + if (wrote > 0) { + total += wrote; + while (wrote > 0) { + /* + * An entire vector element was written + */ + if (wrote >= (ssize_t)vector_p->iov_len) { + iovcnt--; + wrote -= vector_p->iov_len; + vector_p++; + continue; + } + + /* + * Partial vector element was written + */ + vector_p->iov_len -= wrote; + vector_p->iov_base = ((char *)vector_p->iov_base) + wrote; + break; + } + continue; + } else if (wrote == 0) return total; + + switch (errno) { + /* Write operation would block, use select() to implement a timeout */ +#if EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: + case EAGAIN: +#else + case EAGAIN: +#endif + { + int ret; + fd_set write_set; + + FD_ZERO(&write_set); + FD_SET(fd, &write_set); + + /* Don't let signals mess up the select */ + do { + ret = select(fd + 1, NULL, &write_set, NULL, &(fr_time_delta_to_timeval(timeout))); + } while ((ret == -1) && (errno == EINTR)); + + /* Select returned 0 which means it reached the timeout */ + if (ret == 0) { + fr_strerror_const("Write timed out"); + return -1; + } + + /* Other select error */ + if (ret < 0) { + fr_strerror_printf("Failed waiting on socket: %s", fr_syserror(errno)); + return -1; + } + + /* select said a file descriptor was ready for writing */ + if (!fr_cond_assert(FD_ISSET(fd, &write_set))) return -1; + + break; + } + + default: + return -1; + } + } + + return total; +} diff --git a/src/lib/util/iovec.h b/src/lib/util/iovec.h new file mode 100644 index 00000000000..43012ed109a --- /dev/null +++ b/src/lib/util/iovec.h @@ -0,0 +1,41 @@ +#pragma once +/* + * This program 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, or (at your option) + * any later version. + * + * This program 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** Structures and functions for parsing, printing, masking and retrieving IP addresses + * + * @file src/lib/util/inet.h + * + * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org) + * @copyright 2023 Arran Cudbard-Bell (a.cudbardb@freeradius.org) + */ +RCSIDH(iovec_h, "$Id$") + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +fr_slen_t fr_concatv(fr_dbuff_t *out, struct iovec vector[], int iovcnt); +ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t timeout); + +#ifdef __cplusplus +} +#endif diff --git a/src/lib/util/libfreeradius-util.mk b/src/lib/util/libfreeradius-util.mk index 86ed0cc8f71..5d4e3a6a7fb 100644 --- a/src/lib/util/libfreeradius-util.mk +++ b/src/lib/util/libfreeradius-util.mk @@ -46,6 +46,7 @@ SOURCES := \ htrie.c \ hw.c \ inet.c \ + iovec.c \ isaac.c \ log.c \ lst.c \ @@ -91,8 +92,8 @@ SOURCES := \ trie.c \ types.c \ udp.c \ - udpfromto.c \ udp_queue.c \ + udpfromto.c \ uri.c \ value.c \ version.c diff --git a/src/lib/util/misc.c b/src/lib/util/misc.c index 647e465423e..ce9344ab5bc 100644 --- a/src/lib/util/misc.c +++ b/src/lib/util/misc.c @@ -293,102 +293,6 @@ int fr_blocking(UNUSED int fd) } #endif -/** Write out a vector to a file descriptor - * - * Wraps writev, calling it as necessary. If timeout is not NULL, - * timeout is applied to each call that returns EAGAIN or EWOULDBLOCK - * - * @note Should only be used on nonblocking file descriptors. - * @note Socket should likely be closed on timeout. - * @note iovec may be modified in such a way that it's not re-usable. - * @note Leaves errno set to the last error that occurred. - * - * @param fd to write to. - * @param vector to write. - * @param iovcnt number of elements in iovec. - * @param timeout how long to wait for fd to become writable before timing out. - * @return - * - Number of bytes written. - * - -1 on failure. - */ -ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t timeout) -{ - struct iovec *vector_p = vector; - ssize_t total = 0; - - while (iovcnt > 0) { - ssize_t wrote; - - wrote = writev(fd, vector_p, iovcnt); - if (wrote > 0) { - total += wrote; - while (wrote > 0) { - /* - * An entire vector element was written - */ - if (wrote >= (ssize_t)vector_p->iov_len) { - iovcnt--; - wrote -= vector_p->iov_len; - vector_p++; - continue; - } - - /* - * Partial vector element was written - */ - vector_p->iov_len -= wrote; - vector_p->iov_base = ((char *)vector_p->iov_base) + wrote; - break; - } - continue; - } else if (wrote == 0) return total; - - switch (errno) { - /* Write operation would block, use select() to implement a timeout */ -#if EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: - case EAGAIN: -#else - case EAGAIN: -#endif - { - int ret; - fd_set write_set; - - FD_ZERO(&write_set); - FD_SET(fd, &write_set); - - /* Don't let signals mess up the select */ - do { - ret = select(fd + 1, NULL, &write_set, NULL, &(fr_time_delta_to_timeval(timeout))); - } while ((ret == -1) && (errno == EINTR)); - - /* Select returned 0 which means it reached the timeout */ - if (ret == 0) { - fr_strerror_const("Write timed out"); - return -1; - } - - /* Other select error */ - if (ret < 0) { - fr_strerror_printf("Failed waiting on socket: %s", fr_syserror(errno)); - return -1; - } - - /* select said a file descriptor was ready for writing */ - if (!fr_cond_assert(FD_ISSET(fd, &write_set))) return -1; - - break; - } - - default: - return -1; - } - } - - return total; -} - /** Convert UTF8 string to UCS2 encoding * * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/) diff --git a/src/lib/util/misc.h b/src/lib/util/misc.h index 033faa4c37f..97c3844c630 100644 --- a/src/lib/util/misc.h +++ b/src/lib/util/misc.h @@ -164,7 +164,6 @@ char *fr_trim(char const *str, size_t size); int fr_nonblock(int fd); int fr_blocking(int fd); -ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t timeout); ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen); size_t fr_snprint_uint128(char *out, size_t outlen, uint128_t const num); diff --git a/src/modules/rlm_linelog/rlm_linelog.c b/src/modules/rlm_linelog/rlm_linelog.c index e4120f0d101..a58090e80ed 100644 --- a/src/modules/rlm_linelog/rlm_linelog.c +++ b/src/modules/rlm_linelog/rlm_linelog.c @@ -28,6 +28,7 @@ RCSID("$Id$") #include #include #include +#include #include #ifdef HAVE_FCNTL_H @@ -303,6 +304,16 @@ static size_t linelog_escape_func(UNUSED request_t *request, return fr_snprint(out, outlen, in, -1, 0); } +static void linelog_hexdump(request_t *request, struct iovec *vector_p, size_t vector_len, char const *msg) +{ + fr_dbuff_t *agg; + + FR_DBUFF_TALLOC_THREAD_LOCAL(&agg, 1024, SIZE_MAX); + fr_concatv(agg, vector_p, vector_len); + + RHEXDUMP3(fr_dbuff_start(agg), fr_dbuff_used(agg), "%s", msg); +} + static int linelog_write(rlm_linelog_t const *inst, request_t *request, struct iovec *vector_p, size_t vector_len, bool with_delim) { int ret = 0; @@ -380,6 +391,8 @@ static int linelog_write(rlm_linelog_t const *inst, request_t *request, struct i head_vector_len = 2; } + if (RDEBUG_ENABLED3) linelog_hexdump(request, head_vector_s, head_vector_len, "linelog header"); + if (writev(fd, &head_vector_s[0], head_vector_len) < 0) { write_fail: RERROR("Failed writing to \"%s\": %s", path, fr_syserror(errno)); @@ -393,6 +406,8 @@ static int linelog_write(rlm_linelog_t const *inst, request_t *request, struct i } } + if (RDEBUG_ENABLED3) linelog_hexdump(request, vector_p, vector_len, "linelog data"); + ret = writev(fd, vector_p, vector_len); if (ret < 0) goto write_fail; @@ -431,6 +446,7 @@ static int linelog_write(rlm_linelog_t const *inst, request_t *request, struct i ssize_t wrote; char discard[64]; + if (RDEBUG_ENABLED3) linelog_hexdump(request, vector_p, vector_len, "linelog data"); wrote = fr_writev(conn->sockfd, vector_p, vector_len, timeout); if (wrote < 0) switch (errno) { /* Errors that indicate we should reconnect */