Fix GCC-15, C23 compatibility and -Wincompatible-pointer-types errors

A bug in gentoo linux https://bugs.gentoo.org/945183 reported that dnsmasq 2.90 fails to compile with GCC 15.

The issue is that while previous versions of GCC defaulted to the C17 standard and C23 could be selected with
"-std=c23" or "-std=gnu23", GCC 15 defaults to C23. In C23 incompatible pointer types are an error instead of
a warning, so the "int (*callback)()" incomplete prototypes cause errors.

For example, compiling dnsmasq 2.90 with gcc 14.2.1 and "-std=gnu23" fails with errors such as:
    lease.c: In function `lease_find_interfaces':
    lease.c:467:34: warning: passing argument 3 of `iface_enumerate' from incompatible pointer type [-Wincompatible-pointer-types[https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wincompatible-pointer-types]]
      467 |   iface_enumerate(AF_INET, &now, find_interface_v4);
          |                                  ^~~~~~~~~~~~~~~~~
          |                                  |
          |                                  int (*)(struct in_addr,  int,  char *, struct in_addr,  struct in_addr,  void *)
    In file included from lease.c:17:
    dnsmasq.h:1662:50: note: expected `int (*)(void)' but argument is of type `int (*)(struct in_addr,  int,  char *, struct in_addr,  struct in_addr,  void *)'
     1662 | int iface_enumerate(int family, void *parm, int (callback)());
          |                                             ~~~~~^~~~~~~~~~~

This patch uses a typedef'ed union of pointer types to get type checking of the pointers. If that's too complicated,
another way might be to use (void *) casts to disable type checking.

Also, some of the IPv6 callbacks had "int preferred, int valid" and some had
"unsigned int preferred, unsigned int valid". This patch changes them all to "unsigned int"
so they're the same and to avoid casting "u32" to "int", eg:
    u32 preferred = 0xffffffff;
    callback(..., (int)preferred, ...)
Even if those cast values aren't used in the callback, casting u32 to "int" feels bad, especially if "int" is 32 bits.
This commit is contained in:
gen2dev
2024-12-01 22:53:16 +00:00
committed by Simon Kelley
parent a8088e331a
commit da2cc84854
9 changed files with 40 additions and 34 deletions

View File

@@ -239,7 +239,7 @@ void dhcp6_packet(time_t now)
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
return;
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
if (!iface_enumerate(AF_INET6, &parm, (callback_t){.af_inet6=complete_context6}))
return;
/* Check for a relay again after iface_enumerate/complete_context has had
@@ -617,7 +617,7 @@ void make_duid(time_t now)
newnow = now - 946684800;
#endif
iface_enumerate(AF_LOCAL, &newnow, make_duid1);
iface_enumerate(AF_LOCAL, &newnow, (callback_t){.af_local=make_duid1});
if(!daemon->duid)
die("Cannot create DHCPv6 server DUID: %s", NULL, EC_MISC);
@@ -667,7 +667,7 @@ struct cparam {
static int construct_worker(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
int preferred, int valid, void *vparam)
unsigned int preferred, unsigned int valid, void *vparam)
{
char ifrn_name[IFNAMSIZ];
struct in6_addr start6, end6;
@@ -801,7 +801,7 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_CONSTRUCTED)
context->flags |= CONTEXT_GC;
iface_enumerate(AF_INET6, &param, construct_worker);
iface_enumerate(AF_INET6, &param, (callback_t){.af_inet6=construct_worker});
for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
{