Add hooks to compile contrib/lease-tools/dhcp_release.c. This utility is used to send a DHCPRELEASE message to tell the local DHCP server to delete a particular lease. Solaris doesn't support AF_NETLINK, so use getifaddrs() to determine the IP address of an interface on which Dnsmasq process is listening. This patch was developed in-house. Since it is Solaris-specific it is not suitable for upstream. --- a/Makefile 2023-02-02 21:24:24.000000000 +0100 +++ b/Makefile 2023-05-12 10:41:49.982977448 +0200 @@ -19,6 +19,7 @@ # Variables you may well want to override. PREFIX = /usr/local +LIBDIR = $(PREFIX)/lib/inet BINDIR = $(PREFIX)/sbin MANDIR = $(PREFIX)/share/man LOCALEDIR = $(PREFIX)/share/locale @@ -43,6 +44,7 @@ SRC = src PO = po MAN = man +LEASE_TOOLS = contrib/lease-tools ################################################################# @@ -86,6 +88,8 @@ poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o \ metrics.o hash-questions.o domain-match.o nftset.o +dhcp_release_objs = dhcp_release.o + hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ dns-protocol.h radv-protocol.h ip6addr.h metrics.h @@ -94,11 +98,12 @@ top="$(top)" \ build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \ build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \ - -f $(top)/Makefile dnsmasq + -f $(top)/Makefile dnsmasq dhcp_release mostly_clean : rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot - rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq + rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq \ + $(BUILDDIR)/dhcp_release clean : mostly_clean rm -f $(BUILDDIR)/dnsmasq_baseline @@ -110,8 +115,10 @@ install-common : $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) -d $(DESTDIR)$(MANDIR)/man8 + $(INSTALL) -d $(DESTDIR)/$(LIBDIR) $(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8 $(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR) + $(INSTALL) -m 755 $(BUILDDIR)/dhcp_release $(DESTDIR)$(LIBDIR) all-i18n : $(BUILDDIR) @cd $(BUILDDIR) && $(MAKE) \ @@ -119,7 +126,7 @@ i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \ build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \ build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \ - -f $(top)/Makefile dnsmasq + -f $(top)/Makefile dnsmasq dhcp_release for f in `cd $(PO); echo *.po`; do \ cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/bakefile $${f%.po}.mo; \ done @@ -162,6 +169,9 @@ $(objs:.o=.c) $(hdrs): ln -s $(top)/$(SRC)/$@ . +$(dhcp_release_objs:.o=.c): + ln -s $(top)/$(LEASE_TOOLS)/$@ . + $(objs): $(copts_conf) $(hdrs) .c.o: @@ -170,6 +180,9 @@ dnsmasq : $(objs) $(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS) +dhcp_release : $(objs) $(dhcp_release_objs) + $(CC) $(LDFLAGS) -o $@ $(dhcp_release_objs) $(build_libs) $(LIBS) + dnsmasq.pot : $(objs:.o=.c) $(hdrs) $(XGETTEXT) -d dnsmasq --foreign-user --omit-header --keyword=_ -o $@ -i $(objs:.o=.c) --- a/contrib/lease-tools/dhcp_release.c 2021-09-08 22:21:22.000000000 +0000 +++ b/contrib/lease-tools/dhcp_release.c 2021-11-30 10:04:51.507053902 +0000 @@ -33,6 +33,10 @@ The client-id is optional. If it is "*" then it treated as being missing. */ +#if defined(__sun) || defined(__sun__) +#define HAVE_SOLARIS_NETWORK +#endif + #include #include #include @@ -44,9 +48,13 @@ #include #include #include +#ifdef HAVE_SOLARIS_NETWORK +#include +#else #include #include #include +#endif #include #define DHCP_CHADDR_MAX 16 @@ -73,6 +81,7 @@ unsigned char options[308]; }; +#if !defined(HAVE_SOLARIS_NETWORK) static struct iovec iov; static int expand_buf(struct iovec *iov, size_t size) @@ -139,6 +148,8 @@ return rc; } +#endif + static int parse_hex(char *in, unsigned char *out, int maxlen, int *mac_type) { int i = 0; @@ -178,6 +189,7 @@ return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); } +#if !defined(HAVE_SOLARIS_NETWORK) static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index, int ifrfd, struct ifreq *ifr) { struct sockaddr_nl addr; @@ -254,6 +266,7 @@ exit(0); } +#endif int main(int argc, char **argv) { @@ -264,7 +277,12 @@ struct sockaddr_in dest; struct ifreq ifr; int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); +#ifdef HAVE_SOLARIS_NETWORK + int nl = 0; + struct ifaddrs *ifp_head, *ifp; +#else int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); +#endif if (argc < 4 || argc > 5) { @@ -277,7 +295,8 @@ perror("cannot create socket"); exit(1); } - + +#if !defined(HAVE_SOLARIS_NETWORK) /* This voodoo fakes up a packet coming from the correct interface, which really matters for a DHCP server */ strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1); @@ -287,15 +306,46 @@ perror("cannot setup interface"); exit(1); } +#endif if (inet_pton(AF_INET, argv[2], &lease.s_addr) < 1) { perror("invalid ip address"); exit(1); } - + +#ifdef HAVE_SOLARIS_NETWORK + if (getifaddrs(&ifp_head) < 0) + { + perror("could not retrieve IP addresses"); + exit(1); + } + for (ifp = ifp_head; ifp != NULL; ifp = ifp->ifa_next) { + if (ifp->ifa_addr->sa_family != AF_INET) + continue; + if (strcmp(ifp->ifa_name, argv[1]) == 0 && + is_same_net(lease, ((struct sockaddr_in *)ifp->ifa_addr)->sin_addr, + ((struct sockaddr_in *)ifp->ifa_netmask)->sin_addr)) + break; + } + if (ifp == NULL) { + freeifaddrs(ifp_head); + exit(0); + } + memcpy(&server, &((struct sockaddr_in *)ifp->ifa_addr)->sin_addr, + sizeof(server)); + /* bind to the socket */ + if (bind(fd, ifp->ifa_addr, sizeof(struct sockaddr_in)) == -1) + { + freeifaddrs(ifp_head); + perror("cannot bind to socket"); + exit(1); + } + freeifaddrs(ifp_head); +#else /* HAVE_SOLARIS_NETWORK */ server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr); - +#endif /* HAVE_SOLARIS_NETWORK */ + memset(&packet, 0, sizeof(packet)); packet.hlen = parse_hex(argv[3], packet.chaddr, DHCP_CHADDR_MAX, &mac_type);