#include #include #include #include #include #include #include "main.h" #include "utils.h" static unsigned total_malloc_count = 0; static int malloc_count = 0; LIST_HEAD(malloc_list); struct allocation { void *caller; void *ptr; size_t size; struct list_head list; }; static void __add_allocation(void *caller, void *ptr, size_t size) { struct allocation *a = malloc(sizeof(*a)); a->caller = caller; a->ptr = ptr; a->size = size; list_add(&a->list, &malloc_list); } #define add_allocation(p, s) __add_allocation(__builtin_extract_return_addr(__builtin_return_address(0)), p, s) void * __zmalloc(size_t size) { void *ptr; fprintf(stderr, "zmalloc: Allocation size %zi\n", size); ptr = calloc(1, size); if (ptr) { add_allocation(ptr, size); total_malloc_count++; malloc_count++; } return ptr; } char * __xstrdup(const char *s) { char *r; fprintf(stderr, "xstrdup: Allocation size %zi\n", strlen(s) + 1); r = strdup(s); if (r) { add_allocation(r, strlen(s) + 1); total_malloc_count++; malloc_count++; } return r; } void xfree(void *ptr) { struct allocation *a, *tmp; unsigned delete_count = 0; if (!ptr) return; free(ptr); malloc_count--; list_for_each_entry_safe(a, tmp, &malloc_list, list) { if (a->ptr == ptr) { list_del(&a->list); free(a); delete_count++; } } if (delete_count != 1) { error("Delete count is %u for ptr 0x%p\n", delete_count, ptr); exit(EXIT_FAILURE); } } void debug_resource_usage() { struct allocation *a; fprintf(stderr, "Still malloced %i (total %u)\n", malloc_count, total_malloc_count); list_for_each_entry(a, &malloc_list, list) { fprintf(stderr, "* Allocation - caller: 0x%p, ptr: 0x%p, size %zu\n", a->caller, a->ptr, a->size); } } uint16_t sockaddr_port(struct sockaddr_in46 *addr) { switch (addr->storage.ss_family) { case AF_INET: return ntohs(addr->in4.sin_port); case AF_INET6: return ntohs(addr->in6.sin6_port); default: return 0; } } char * sockaddr_to_str(struct sockaddr_in46 *addr, char *buf, size_t buflen) { char abuf[ADDRSTRLEN]; switch (addr->storage.ss_family) { case AF_INET: snprintf(buf, buflen, "AF_INET4 %s %u", inet_ntop(addr->in4.sin_family, &addr->in4.sin_addr, abuf, sizeof(abuf)), (unsigned)ntohs(addr->in4.sin_port)); break; case AF_INET6: snprintf(buf, buflen, "AF_INET6 %s %u", inet_ntop(addr->in6.sin6_family, &addr->in6.sin6_addr, abuf, sizeof(abuf)), (unsigned)ntohs(addr->in6.sin6_port)); break; default: snprintf(buf, buflen, "AF_UNKNOWN"); break; } return buf; } int strtou16_strict(const char *str, uint16_t *result) { char *end; long val; if (!str) return -EINVAL; errno = 0; val = strtol(str, &end, 10); if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) return -EINVAL; if (errno != 0 && val == 0) return -EINVAL; if (end == str) return -EINVAL; if (*end != '\0') return -EINVAL; if (val < 1 || val > UINT16_MAX) return -EINVAL; if (result) *result = val; return 0; }