[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#496511: marked as done (Please include simpledhcpd binary)



Your message dated Mon, 17 Mar 2014 02:36:11 +0100
with message-id <20140317013611.GA9463@mraw.org>
and subject line Re: Bug#496511: Please include simpledhcpd binary
has caused the Debian Bug report #496511,
regarding Please include simpledhcpd binary
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
496511: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=496511
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: udhcp
Version: 0.9.8cvs20050303-2
Severity: wishlist
Tags: patch

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

a while ago, I wrote a simpledhcpd binary inside the udhcp code:
http://www.joachim-breitner.de/blog/archives/243-Spontanious-DHCP-Server-Done..html

Some people have shown interest in getting this packaged for Debian. I
think it would be unwise to copy the udhcpd code base, so I’m asking for
inclusion of the patch in the udhcp package. Of course I’ll be present
to reply to bugs in my code, and subscribe to the pts.

Greetings and thanks,
Joachim


- -- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.25-2-486
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkiyllMACgkQ9ijrk0dDIGztDQCeM+5HFfskwwstOYsW/KjK/D8i
idMAn2KsW6/EFuVKR/ZTaJ7xwrblHg+S
=QWlB
-----END PGP SIGNATURE-----
diff -u udhcp-0.9.8cvs20050303/samples/udhcpd.conf udhcp-0.9.8cvs20050303/samples/udhcpd.conf
--- udhcp-0.9.8cvs20050303/dhcpd.c
+++ udhcp-0.9.8cvs20050303/dhcpd.c
@@ -102,7 +102,7 @@
 	read_leases(server_config.lease_file);
 
 	if (read_interface(server_config.interface, &server_config.ifindex,
-			   &server_config.server, server_config.arp) < 0)
+			   &server_config.server, server_config.arp, NULL) < 0)
 		return 1;
 
 #ifndef UDHCP_DEBUG
diff -u udhcp-0.9.8cvs20050303/Makefile udhcp-0.9.8cvs20050303/Makefile
--- udhcp-0.9.8cvs20050303/Makefile
+++ udhcp-0.9.8cvs20050303/Makefile
@@ -25,6 +25,7 @@
 OBJS_SHARED = common.o options.o packet.o pidfile.o signalpipe.o socket.o
 DHCPD_OBJS = dhcpd.o arpping.o files.o leases.o serverpacket.o static_leases.o
 DHCPC_OBJS = dhcpc.o clientpacket.o clientsocket.o script.o
+SIMPLEDHCPD_OBJS = simpledhcpd.o arpping.o files.o leases.o serverpacket.o static_leases.o
 
 ifdef COMBINED_BINARY
 EXEC1 = udhcpd
@@ -41,6 +42,9 @@
 EXEC3 = dumpleases
 OBJS3 = dumpleases.o
 
+EXEC4 = simpledhcpd
+OBJS4 = $(SIMPLEDHCPD_OBJS) $(OBJS_SHARED)
+
 BOOT_PROGRAM = udhcpc
 DAEMON = udhcpd
 COMMAND = dumpleases
@@ -59,11 +63,11 @@
 STRIP=$(CROSS_COMPILE)strip
 endif
 
-all: $(EXEC1) $(EXEC2) $(EXEC3)
-	$(STRIP) --remove-section=.note --remove-section=.comment $(EXEC1) $(EXEC2) $(EXEC3)
+all: $(EXEC1) $(EXEC2) $(EXEC3) $(EXEC4)
+	$(STRIP) --remove-section=.note --remove-section=.comment $(EXEC1) $(EXEC2) $(EXEC3) $(EXEC4)
 
 $(OBJS1) $(OBJS2) $(OBJS3): *.h Makefile
-$(EXEC1) $(EXEC2) $(EXEC3): Makefile
+$(EXEC1) $(EXEC2) $(EXEC3) $(EXEC4): Makefile
 
 .c.o:
 	$(CC) -c $(CFLAGS) $<
@@ -77,6 +81,8 @@
 $(EXEC3): $(OBJS3)
 	$(LD) $(LDFLAGS) $(OBJS3) -o $(EXEC3)
 
+$(EXEC4): $(OBJS4)
+	$(LD) $(LDFLAGS) $(OBJS4) -o $(EXEC4)
 
 install: all
 	mkdir -p $(USRSBINDIR) $(USRBINDIR) 
@@ -103 +109 @@
-	-rm -f udhcpd udhcpc dumpleases *.o core
+	-rm -f udhcpd udhcpc dumpleases simpledhcpd *.o core
diff -u udhcp-0.9.8cvs20050303/socket.c udhcp-0.9.8cvs20050303/socket.c
--- udhcp-0.9.8cvs20050303/socket.c
+++ udhcp-0.9.8cvs20050303/socket.c
@@ -44,11 +44,12 @@
 #include "socket.h"
 #include "common.h"
 
-int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp)
+int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp, uint32_t *mask)
 {
 	int fd;
 	struct ifreq ifr;
 	struct sockaddr_in *our_ip;
+	struct sockaddr_in *our_mask;
 
 	memset(&ifr, 0, sizeof(struct ifreq));
 	if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {
@@ -70,0 +72,12 @@
+
+		if (mask) {
+			if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0) {
+				our_mask = (struct sockaddr_in *) &ifr.ifr_addr;
+				*mask = our_ip->sin_addr.s_addr;
+				DEBUG(LOG_INFO, "%s (our mask) = %s", ifr.ifr_name, inet_ntoa(our_mask->sin_addr));
+			} else {
+				LOG(LOG_ERR, "SIOCGIFNETMASK failed, is the interface up and configured?: %m");
+				close(fd);
+				return -1;
+			}
+		}
reverted:
--- udhcp-0.9.8cvs20050303/debian/changelog
+++ udhcp-0.9.8cvs20050303/debian/changelog
@@ -1,3 +1,9 @@
+udhcp (0.9.8cvs20050303-3) INOFFICIAL; urgency=low
+
+  * Add simpledhcpd 
+
+ -- Joachim Breitner <nomeata@debian.org>  Sun, 03 Jun 2007 01:54:07 +0200
+
 udhcp (0.9.8cvs20050303-2) unstable; urgency=low
 
   * Fix correct number of leases (closes: #341139 - thanks to Ferenc Wagner)
reverted:
--- udhcp-0.9.8cvs20050303/debian/control
+++ udhcp-0.9.8cvs20050303/debian/control
@@ -34,0 +35,12 @@
+
+Package: simpledhcpd
+Section: net
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: very small instant DHCP server
+ DHCP is a protocol like BOOTP (actually dhcpd includes much of
+ the functionality of BOOTPD!). It assigns IP addresses to clients
+ based on lease times.
+ .
+ You can use this program to quickly assign IP addresses in a 
+ spontanious network, without any configuration file.
reverted:
--- udhcp-0.9.8cvs20050303/debian/rules
+++ udhcp-0.9.8cvs20050303/debian/rules
@@ -105,6 +105,33 @@
 
 	rm -fr debian/tmp
 
+	# Build simpledhcpd package.
+	install -d -m 755 debian/tmp/DEBIAN
+
+	install -d -m 755 debian/tmp/usr/share/doc/simpledhcpd
+	#install -m 644 README debian/tmp/usr/share/doc/udhcpd
+	install -m 644 README.simpledhcpd debian/tmp/usr/share/doc/simpledhcpd/README
+	install -m 644 ChangeLog debian/tmp/usr/share/doc/simpledhcpd/changelog
+	install -m 644 debian/changelog debian/tmp/usr/share/doc/simpledhcpd/changelog.Debian
+	gzip -9v debian/tmp/usr/share/doc/simpledhcpd/*
+	install -m 644 debian/copyright debian/tmp/usr/share/doc/simpledhcpd
+
+	#install -d -m 755 debian/tmp/usr/share/man/man8
+	#install -m 644 udhcpd.8 debian/tmp/usr/share/man/man8
+	#gzip -9v debian/tmp/usr/share/man/man8/udhcpd.8
+
+	install -d -m 755 debian/tmp/usr/sbin
+	install -m 755 simpledhcpd debian/tmp/usr/sbin/simpledhcpd
+	strip --remove-section=.comment --remove-section=.note --strip-unneeded debian/tmp/usr/sbin/simpledhcpd
+
+	dpkg-shlibdeps simpledhcpd
+	dpkg-gencontrol -isp -psimpledhcpd
+	chown -R root.root debian/tmp
+	chmod -R go=rX debian/tmp
+	dpkg --build debian/tmp ..
+
+	rm -fr debian/tmp
+
 define checkdir
 	test -f dhcpc.c -a -f debian/rules
 endef
reverted:
--- udhcp-0.9.8cvs20050303.orig/simpledhcpd.c
+++ udhcp-0.9.8cvs20050303/simpledhcpd.c
@@ -0,0 +1,331 @@
+/* simpledhcpd.c
+ *
+ * simpledhcp Server
+ * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
+ *			Chris Trew <ctrew@moreton.com.au>
+ *
+ * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
+ *
+ * simpledhcpd copyright (C) 2007 Joachim Breitner <mail@joachim-breitner.de>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "dhcpd.h"
+#include "arpping.h"
+#include "socket.h"
+#include "options.h"
+#include "files.h"
+#include "serverpacket.h"
+#include "common.h"
+#include "signalpipe.h"
+#include "static_leases.h"
+
+
+/* globals */
+struct dhcpOfferedAddr *leases;
+struct server_config_t server_config;
+
+
+
+#define READ_BUF_SIZE 80
+int get_dns_server(uint32_t *dns)
+{
+	FILE *in;
+	int ret = 1;
+	char buffer[READ_BUF_SIZE], *token, *addr;
+
+	if (!(in = fopen("/etc/resolv.conf", "r"))) {
+		LOG(LOG_ERR, "unable to open /etc/resolv");
+		return 0;
+	}
+
+	while (fgets(buffer, READ_BUF_SIZE, in)) {
+		if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0';
+		if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0';
+	
+		if (!(token = strtok(buffer, " \t"))) continue;
+		if (!strcasecmp(token, "nameserver")) {
+			if (!(addr = strtok(NULL, ""))) continue;
+			if (inet_aton(addr,(struct in_addr *)dns))
+				ret = 0;
+		}
+	}
+
+	fclose(in);
+	return ret;
+}
+
+int main(int argc, char *argv[])
+{
+	fd_set rfds;
+	struct timeval tv;
+	int server_socket = -1;
+	int bytes, retval;
+	struct dhcpMessage packet;
+	uint8_t *state;
+	uint8_t *server_id, *requested;
+	uint32_t server_id_align, requested_align;
+	unsigned long timeout_end;
+	struct option_set *option;
+	struct dhcpOfferedAddr *lease;
+	struct dhcpOfferedAddr static_lease;
+	int max_sock;
+	unsigned long num_ips;
+
+	uint32_t static_lease_ip;
+
+	memset(&server_config, 0, sizeof(struct server_config_t));
+	
+	if (argc != 2) {
+		LOG(LOG_ERR, "Usage: Device");
+		return(2);
+	}
+
+	// read_config(argc < 2 ? DHCPD_CONF_FILE : argv[1]);
+	read_config("/dev/null"); // reads defaults
+
+	server_config.interface = argv[1];
+
+	/* Start the log, sanitize fd's, and write a pid file */
+	// start_log_and_pid("udhcpd", server_config.pidfile);
+
+	if ((option = find_option(server_config.options, DHCP_LEASE_TIME))) {
+		memcpy(&server_config.lease, option->data + 2, 4);
+		server_config.lease = ntohl(server_config.lease);
+	}
+	else server_config.lease = LEASE_TIME;
+
+
+	uint32_t mask;
+	if (read_interface(server_config.interface, &server_config.ifindex,
+			   &server_config.server, server_config.arp, &mask) < 0)
+		return 1;
+	
+	attach_option(&(server_config.options), &dhcp_options[0], (char *)&(mask), 4);
+	attach_option(&(server_config.options), &dhcp_options[2], (char *)&(server_config.server), 4);
+	
+	uint32_t dns;
+	if (!get_dns_server(&dns)) {
+		attach_option(&(server_config.options), &dhcp_options[5], (char *)&(dns), 4);
+		DEBUG(LOG_INFO, "(dns) = %s", inet_ntoa(*(struct in_addr *)&dns));
+	}
+	
+	if (server_config.server < (128<<24)) {
+		server_config.start = server_config.server + (10<<24);
+		server_config.end   = (server_config.server | 255<<24) - (1<<24);
+	} else {
+		server_config.start = (server_config.server & ~(255<<24)) + (10<<24);
+		server_config.end   = server_config.server  - (1<<24);
+	}
+
+	DEBUG(LOG_INFO, "(start) = %s", inet_ntoa(*(struct in_addr *)&server_config.start));
+	DEBUG(LOG_INFO, "(end) = %s", inet_ntoa(*(struct in_addr *)&server_config.end));
+
+	/* Sanity check */
+	// Let's try to fix http://bugs.debian.org/341139 (ericvb@debian.org - 16/12/05)
+	//num_ips = ntohl(server_config.end) - ntohl(server_config.start);
+	
+	num_ips = ntohl(server_config.end) - ntohl(server_config.start) + 1;
+	if (server_config.max_leases > num_ips) {
+		LOG(LOG_ERR, "max_leases value (%lu) not sane, "
+			"setting to %lu instead",
+			server_config.max_leases, num_ips);
+		server_config.max_leases = num_ips;
+	} 
+
+	leases = xcalloc(server_config.max_leases, sizeof(struct dhcpOfferedAddr));
+
+	// read_leases(server_config.lease_file);
+
+	/* Setup the signal pipe */
+	udhcp_sp_setup();
+
+	timeout_end = time(0) + server_config.auto_time;
+	while(1) { /* loop until universe collapses */
+
+		if (server_socket < 0)
+			if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) {
+				LOG(LOG_ERR, "FATAL: couldn't create server socket, %m");
+				return 2;
+			}
+
+		max_sock = udhcp_sp_fd_set(&rfds, server_socket);
+		if (server_config.auto_time) {
+			tv.tv_sec = timeout_end - time(0);
+			tv.tv_usec = 0;
+		}
+		if (!server_config.auto_time || tv.tv_sec > 0) {
+			retval = select(max_sock + 1, &rfds, NULL, NULL,
+					server_config.auto_time ? &tv : NULL);
+		} else retval = 0; /* If we already timed out, fall through */
+
+		if (retval == 0) {
+			write_leases();
+			timeout_end = time(0) + server_config.auto_time;
+			continue;
+		} else if (retval < 0 && errno != EINTR) {
+			DEBUG(LOG_INFO, "error on select");
+			continue;
+		}
+
+		switch (udhcp_sp_read(&rfds)) {
+		case SIGUSR1:
+			LOG(LOG_INFO, "Received a SIGUSR1");
+			write_leases();
+			/* why not just reset the timeout, eh */
+			timeout_end = time(0) + server_config.auto_time;
+			continue;
+		case SIGTERM:
+			LOG(LOG_INFO, "Received a SIGTERM");
+			return 0;
+		case 0: break;		/* no signal */
+		default: continue;	/* signal or error (probably EINTR) */
+		}
+
+		if ((bytes = get_packet(&packet, server_socket)) < 0) { /* this waits for a packet - idle */
+			if (bytes == -1 && errno != EINTR) {
+				DEBUG(LOG_INFO, "error on read, %m, reopening socket");
+				close(server_socket);
+				server_socket = -1;
+			}
+			continue;
+		}
+
+		if ((state = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
+			DEBUG(LOG_ERR, "couldn't get option from packet, ignoring");
+			continue;
+		}
+
+		/* Look for a static lease */
+		static_lease_ip = getIpByMac(server_config.static_leases, &packet.chaddr);
+
+		if(static_lease_ip)
+		{
+			printf("Found static lease: %x\n", static_lease_ip);
+
+			memcpy(&static_lease.chaddr, &packet.chaddr, 16);
+			static_lease.yiaddr = static_lease_ip;
+			static_lease.expires = 0;
+
+			lease = &static_lease;
+
+		}
+		else
+		{
+		lease = find_lease_by_chaddr(packet.chaddr);
+		}
+
+		switch (state[0]) {
+		case DHCPDISCOVER:
+			DEBUG(LOG_INFO,"received DISCOVER");
+
+			if (sendOffer(&packet) < 0) {
+				LOG(LOG_ERR, "send OFFER failed");
+			}
+			break;
+ 		case DHCPREQUEST:
+			DEBUG(LOG_INFO, "received REQUEST");
+
+			requested = get_option(&packet, DHCP_REQUESTED_IP);
+			server_id = get_option(&packet, DHCP_SERVER_ID);
+
+			if (requested) memcpy(&requested_align, requested, 4);
+			if (server_id) memcpy(&server_id_align, server_id, 4);
+
+			if (lease) {
+				if (server_id) {
+					/* SELECTING State */
+					DEBUG(LOG_INFO, "server_id = %08x", ntohl(server_id_align));
+					if (server_id_align == server_config.server && requested &&
+					    requested_align == lease->yiaddr) {
+						sendACK(&packet, lease->yiaddr);
+					}
+				} else {
+					if (requested) {
+						/* INIT-REBOOT State */
+						if (lease->yiaddr == requested_align)
+							sendACK(&packet, lease->yiaddr);
+						else sendNAK(&packet);
+					} else {
+						/* RENEWING or REBINDING State */
+						if (lease->yiaddr == packet.ciaddr)
+							sendACK(&packet, lease->yiaddr);
+						else {
+							/* don't know what to do!!!! */
+							sendNAK(&packet);
+						}
+					}
+				}
+
+			/* what to do if we have no record of the client */
+			} else if (server_id) {
+				/* SELECTING State */
+
+			} else if (requested) {
+				/* INIT-REBOOT State */
+				if ((lease = find_lease_by_yiaddr(requested_align))) {
+					if (lease_expired(lease)) {
+						/* probably best if we drop this lease */
+						memset(lease->chaddr, 0, 16);
+					/* make some contention for this address */
+					} else sendNAK(&packet);
+				} else if (requested_align < server_config.start ||
+					   requested_align > server_config.end) {
+					sendNAK(&packet);
+				} /* else remain silent */
+
+			} else {
+				 /* RENEWING or REBINDING State */
+			}
+			break;
+		case DHCPDECLINE:
+			DEBUG(LOG_INFO,"received DECLINE");
+			if (lease) {
+				memset(lease->chaddr, 0, 16);
+				lease->expires = time(0) + server_config.decline_time;
+			}
+			break;
+		case DHCPRELEASE:
+			DEBUG(LOG_INFO,"received RELEASE");
+			if (lease) lease->expires = time(0);
+			break;
+		case DHCPINFORM:
+			DEBUG(LOG_INFO,"received INFORM");
+			send_inform(&packet);
+			break;
+		default:
+			LOG(LOG_WARNING, "unsupported DHCP message (%02x) -- ignoring", state[0]);
+		}
+	}
+
+	return 0;
+}
+
only in patch2:
unchanged:
--- udhcp-0.9.8cvs20050303.orig/socket.h
+++ udhcp-0.9.8cvs20050303/socket.h
@@ -2,7 +2,7 @@
 #ifndef _SOCKET_H
 #define _SOCKET_H
 
-int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp);
+int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp, uint32_t *mask);
 int listen_socket(uint32_t ip, int port, char *inf);
 
 #endif
only in patch2:
unchanged:
--- udhcp-0.9.8cvs20050303.orig/README.simpledhcpd
+++ udhcp-0.9.8cvs20050303/README.simpledhcpd
@@ -0,0 +1,24 @@
+== simpledhcpd ==
+
+Usage:
+	simpledhcpd devicename
+	e.g.
+	simpledhcpd eth0
+
+Effect:
+	simpledhcpd will start listening on the given interface
+	for DHCP requests. These will be answered, handing out
+	the following information:
+	  * an IP from the same subnet as your own computer
+	  * the netmask as configured on the device
+	  * your IP address as the default gateway
+	  * the first DNS server from /etc/resolv.conf
+	
+	This should be sufficient to enable the other computers to
+	communicate with you and, if you have a connection to the 
+	internet and have set up routing, to share your internet
+	connection.
+
+Author:
+	(c) 2007 Joachim Breitner <mail@joachim-breitner.de>
+	Based on the udhcpd code
only in patch2:
unchanged:
--- udhcp-0.9.8cvs20050303.orig/dhcpc.c
+++ udhcp-0.9.8cvs20050303/dhcpc.c
@@ -290,7 +290,7 @@
 	start_log_and_pid("udhcpc", client_config.pidfile);
 
 	if (read_interface(client_config.interface, &client_config.ifindex,
-			   NULL, client_config.arp) < 0)
+			   NULL, client_config.arp, NULL) < 0)
 		return 1;
 
 	if (!client_config.clientid) {

--- End Message ---
--- Begin Message ---
Michael Tokarev <mjt@tls.msk.ru> (2011-07-02):
> tags 496511 + wontfix
> thanks
> 
> > a while ago, I wrote a simpledhcpd binary inside the udhcp code:
> > http://www.joachim-breitner.de/blog/archives/243-Spontanious-DHCP-Server-Done..html
> >
> > Some people have shown interest in getting this packaged for Debian. I
> > think it would be unwise to copy the udhcpd code base, so I’m asking for
> > inclusion of the patch in the udhcp package. Of course I’ll be present
> > to reply to bugs in my code, and subscribe to the pts.
> 
> There's really no need to have two dhcp servers inside busybox,
> one is enough I think.  Marking this bugreport as wontfix.
> 
> Thanks!
> 
> /mjt

Since there's been no further comments in the last 2+ years, I'm closing
this bug report.

Mraw,
KiBi.

Attachment: signature.asc
Description: Digital signature


--- End Message ---

Reply to: