From 2b5ed83fec55f5d96338fe3ae5e394bed1a407f4 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 21 Jun 2018 15:44:41 +0900 Subject: Imported Upstream version 2.79 Change-Id: I9a2f4c945e0481ab803bdf0c85921433f33a9256 Signed-off-by: Seonah Moon --- contrib/MacOSX-launchd/launchd-README.txt | 2 +- contrib/Suse/README.susefirewall | 4 +- contrib/conntrack/README | 6 +- contrib/lease-access/lease.access.patch | 2 +- contrib/lease-tools/Makefile | 6 + contrib/lease-tools/dhcp_lease_time.1 | 25 ++ contrib/lease-tools/dhcp_lease_time.c | 221 +++++++++ contrib/lease-tools/dhcp_release.1 | 37 ++ contrib/lease-tools/dhcp_release.c | 332 ++++++++++++++ contrib/lease-tools/dhcp_release6.1 | 38 ++ contrib/lease-tools/dhcp_release6.c | 496 +++++++++++++++++++++ contrib/mactable/macscript | 2 +- contrib/port-forward/portforward | 2 +- contrib/reverse-dns/README | 36 +- contrib/reverse-dns/reverse_replace.sh | 4 +- contrib/systemd/dbus_activation | 114 ++--- contrib/try-all-ns/README-2.47 | 2 +- contrib/try-all-ns/README-2.78 | 10 + contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch | 20 + contrib/webmin/README | 4 +- contrib/wrt/Makefile | 6 - contrib/wrt/README | 4 +- contrib/wrt/dhcp_lease_time.1 | 25 -- contrib/wrt/dhcp_lease_time.c | 221 --------- contrib/wrt/dhcp_release.1 | 37 -- contrib/wrt/dhcp_release.c | 332 -------------- 26 files changed, 1276 insertions(+), 712 deletions(-) create mode 100644 contrib/lease-tools/Makefile create mode 100644 contrib/lease-tools/dhcp_lease_time.1 create mode 100644 contrib/lease-tools/dhcp_lease_time.c create mode 100644 contrib/lease-tools/dhcp_release.1 create mode 100644 contrib/lease-tools/dhcp_release.c create mode 100644 contrib/lease-tools/dhcp_release6.1 create mode 100644 contrib/lease-tools/dhcp_release6.c create mode 100644 contrib/try-all-ns/README-2.78 create mode 100644 contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch delete mode 100644 contrib/wrt/Makefile delete mode 100644 contrib/wrt/dhcp_lease_time.1 delete mode 100644 contrib/wrt/dhcp_lease_time.c delete mode 100644 contrib/wrt/dhcp_release.1 delete mode 100644 contrib/wrt/dhcp_release.c (limited to 'contrib') diff --git a/contrib/MacOSX-launchd/launchd-README.txt b/contrib/MacOSX-launchd/launchd-README.txt index 4783221..cf245ff 100644 --- a/contrib/MacOSX-launchd/launchd-README.txt +++ b/contrib/MacOSX-launchd/launchd-README.txt @@ -22,7 +22,7 @@ sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist Optionally, edit your dnsmasq configuration file to your liking. -To start the launchd job, which starts dnsmaq, reboot or use the command: +To start the launchd job, which starts dnsmasq, reboot or use the command: sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist To stop the launchd job, which stops dnsmasq, use the command: diff --git a/contrib/Suse/README.susefirewall b/contrib/Suse/README.susefirewall index 2f19ca6..0b94108 100644 --- a/contrib/Suse/README.susefirewall +++ b/contrib/Suse/README.susefirewall @@ -1,9 +1,9 @@ This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older) -It fixes the depancy from the dns daemon name 'named' +It fixes the dependency from the dns daemon name 'named' After appending the patch, the SuSEfirewall is again able to autodetect the dnsmasq named service. This is a very old bug in the SuSEfirewall script. -The SuSE people think the name of the dns server will allways 'named' +The SuSE people think the name of the dns server will always 'named' --- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100 diff --git a/contrib/conntrack/README b/contrib/conntrack/README index c0d17aa..e883447 100644 --- a/contrib/conntrack/README +++ b/contrib/conntrack/README @@ -13,10 +13,10 @@ connection comes out of the other side. However, sometimes, we want to maintain that relationship through the proxy and continue the connection mark on packets upstream of our proxy -DNSMasq includes such a feature enabled by the --conntrack +Dnsmasq includes such a feature enabled by the --conntrack option. This allows, for example, using iptables to mark traffic from a particular IP, and that mark to be persisted to requests made *by* -DNSMasq. Such a feature could be useful for bandwidth accounting, +Dnsmasq. Such a feature could be useful for bandwidth accounting, captive portals and the like. Note a similar feature has been implemented in Squid 2.2 @@ -40,7 +40,7 @@ on IP address. 3) Saves the firewall mark back to the connection mark (which will persist it across related packets) 4) is applied to the OUTPUT table, which is where we first see packets -generated locally. DNSMasq will have already copied the firewall mark +generated locally. Dnsmasq will have already copied the firewall mark from the request, across to the new packet, and so all that remains is for iptables to copy it to the connection mark so it's persisted across packets. diff --git a/contrib/lease-access/lease.access.patch b/contrib/lease-access/lease.access.patch index ad76e25..911ee7e 100644 --- a/contrib/lease-access/lease.access.patch +++ b/contrib/lease-access/lease.access.patch @@ -55,7 +55,7 @@ Index: src/dnsmasq.c } @@ -434,7 +433,7 @@ - /* lose the setuid and setgid capbilities */ + /* lose the setuid and setgid capabilities */ if (capset(hdr, data) == -1) { - send_event(err_pipe[1], EVENT_CAP_ERR, errno); diff --git a/contrib/lease-tools/Makefile b/contrib/lease-tools/Makefile new file mode 100644 index 0000000..f38f2ed --- /dev/null +++ b/contrib/lease-tools/Makefile @@ -0,0 +1,6 @@ +CFLAGS?= -O2 -Wall -W + +all: dhcp_release dhcp_release6 dhcp_lease_time + +clean: + rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time diff --git a/contrib/lease-tools/dhcp_lease_time.1 b/contrib/lease-tools/dhcp_lease_time.1 new file mode 100644 index 0000000..2fa78d3 --- /dev/null +++ b/contrib/lease-tools/dhcp_lease_time.1 @@ -0,0 +1,25 @@ +.TH DHCP_LEASE_TIME 1 +.SH NAME +dhcp_lease_time \- Query remaining time of a lease on a the local dnsmasq DHCP server. +.SH SYNOPSIS +.B dhcp_lease_time
+.SH "DESCRIPTION" +Send a DHCPINFORM message to a dnsmasq server running on the local host +and print (to stdout) the time remaining in any lease for the given +address. The time is given as string printed to stdout. + +If an error occurs or no lease exists for the given address, +nothing is sent to stdout a message is sent to stderr and a +non-zero error code is returned. + +Requires dnsmasq 2.67 or later and may not work with other DHCP servers. + +The address argument is a dotted-quad IP addresses and mandatory. +.SH LIMITATIONS +Only works with IPv4 addresses and DHCP leases. +.SH SEE ALSO +.BR dnsmasq (8) +.SH AUTHOR +This manual page was written by Simon Kelley . + + diff --git a/contrib/lease-tools/dhcp_lease_time.c b/contrib/lease-tools/dhcp_lease_time.c new file mode 100644 index 0000000..f9d7a85 --- /dev/null +++ b/contrib/lease-tools/dhcp_lease_time.c @@ -0,0 +1,221 @@ +/* Copyright (c) 2007 Simon Kelley + + 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; version 2 dated June, 1991. + + 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. +*/ + +/* dhcp_lease_time
*/ + +/* Send a DHCPINFORM message to a dnsmasq server running on the local host + and print (to stdout) the time remaining in any lease for the given + address. The time is given as string printed to stdout. + + If an error occurs or no lease exists for the given address, + nothing is sent to stdout a message is sent to stderr and a + non-zero error code is returned. + + This version requires dnsmasq 2.67 or later. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DHCP_CHADDR_MAX 16 +#define BOOTREQUEST 1 +#define DHCP_COOKIE 0x63825363 +#define OPTION_PAD 0 +#define OPTION_LEASE_TIME 51 +#define OPTION_OVERLOAD 52 +#define OPTION_MESSAGE_TYPE 53 +#define OPTION_REQUESTED_OPTIONS 55 +#define OPTION_END 255 +#define DHCPINFORM 8 +#define DHCP_SERVER_PORT 67 + +#define option_len(opt) ((int)(((unsigned char *)(opt))[1])) +#define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2])) + + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +struct dhcp_packet { + u8 op, htype, hlen, hops; + u32 xid; + u16 secs, flags; + struct in_addr ciaddr, yiaddr, siaddr, giaddr; + u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128]; + u32 cookie; + unsigned char options[308]; +}; + +static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize) +{ + while (*p != OPTION_END) + { + if (p >= end) + return NULL; /* malformed packet */ + else if (*p == OPTION_PAD) + p++; + else + { + int opt_len; + if (p >= end - 2) + return NULL; /* malformed packet */ + opt_len = option_len(p); + if (p >= end - (2 + opt_len)) + return NULL; /* malformed packet */ + if (*p == opt && opt_len >= minsize) + return p; + p += opt_len + 2; + } + } + + return opt == OPTION_END ? p : NULL; +} + +static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize) +{ + unsigned char *ret, *overload; + + /* skip over DHCP cookie; */ + if ((ret = option_find1(&mess->options[0], ((unsigned char *)mess) + size, opt_type, minsize))) + return ret; + + /* look for overload option. */ + if (!(overload = option_find1(&mess->options[0], ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1))) + return NULL; + + /* Can we look in filename area ? */ + if ((overload[2] & 1) && + (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize))) + return ret; + + /* finally try sname area */ + if ((overload[2] & 2) && + (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize))) + return ret; + + return NULL; +} + +static unsigned int option_uint(unsigned char *opt, int size) +{ + /* this worries about unaligned data and byte order */ + unsigned int ret = 0; + int i; + unsigned char *p = option_ptr(opt); + + for (i = 0; i < size; i++) + ret = (ret << 8) | *p++; + + return ret; +} + +int main(int argc, char **argv) +{ + struct in_addr lease; + struct dhcp_packet packet; + unsigned char *p = packet.options; + struct sockaddr_in dest; + int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + ssize_t rc; + + if (argc < 2) + { + fprintf(stderr, "usage: dhcp_lease_time
\n"); + exit(1); + } + + if (fd == -1) + { + perror("cannot create socket"); + exit(1); + } + + lease.s_addr = inet_addr(argv[1]); + + memset(&packet, 0, sizeof(packet)); + + packet.hlen = 0; + packet.htype = 0; + + packet.op = BOOTREQUEST; + packet.ciaddr = lease; + packet.cookie = htonl(DHCP_COOKIE); + + *(p++) = OPTION_MESSAGE_TYPE; + *(p++) = 1; + *(p++) = DHCPINFORM; + + /* Explicitly request the lease time, it won't be sent otherwise: + this is a dnsmasq extension, not standard. */ + *(p++) = OPTION_REQUESTED_OPTIONS; + *(p++) = 1; + *(p++) = OPTION_LEASE_TIME; + + *(p++) = OPTION_END; + + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = inet_addr("127.0.0.1"); + dest.sin_port = ntohs(DHCP_SERVER_PORT); + + if (sendto(fd, &packet, sizeof(packet), 0, + (struct sockaddr *)&dest, sizeof(dest)) == -1) + { + perror("sendto failed"); + exit(1); + } + + alarm(3); /* noddy timeout. */ + + rc = recv(fd, &packet, sizeof(packet), 0); + + if (rc < (ssize_t)(sizeof(packet) - sizeof(packet.options))) + { + perror("recv failed"); + exit(1); + } + + if ((p = option_find(&packet, (size_t)rc, OPTION_LEASE_TIME, 4))) + { + unsigned int t = option_uint(p, 4); + if (t == 0xffffffff) + printf("infinite"); + else + { + unsigned int x; + if ((x = t/86400)) + printf("%ud", x); + if ((x = (t/3600)%24)) + printf("%uh", x); + if ((x = (t/60)%60)) + printf("%um", x); + if ((x = t%60)) + printf("%us", x); + } + return 0; + } + + return 1; /* no lease */ +} diff --git a/contrib/lease-tools/dhcp_release.1 b/contrib/lease-tools/dhcp_release.1 new file mode 100644 index 0000000..e71aba0 --- /dev/null +++ b/contrib/lease-tools/dhcp_release.1 @@ -0,0 +1,37 @@ +.TH DHCP_RELEASE 1 +.SH NAME +dhcp_release \- Release a DHCP lease on a the local dnsmasq DHCP server. +.SH SYNOPSIS +.B dhcp_release
+.SH "DESCRIPTION" +A utility which forces the DHCP server running on this machine to release a +DHCP lease. +.PP +Send a DHCPRELEASE message via the specified interface to tell the +local DHCP server to delete a particular lease. + +The interface argument is the interface in which a DHCP +request _would_ be received if it was coming from the client, +rather than being faked up here. + +The address argument is a dotted-quad IP addresses and mandatory. + +The MAC address is colon separated hex, and is mandatory. It may be +prefixed by an address-type byte followed by -, eg + +10-11:22:33:44:55:66 + +but if the address-type byte is missing it is assumed to be 1, the type +for ethernet. This encoding is the one used in dnsmasq lease files. + +The client-id is optional. If it is "*" then it treated as being missing. +.SH NOTES +MUST be run as root - will fail otherwise. +.SH LIMITATIONS +Only usable on IPv4 DHCP leases. +.SH SEE ALSO +.BR dnsmasq (8) +.SH AUTHOR +This manual page was written by Simon Kelley . + + diff --git a/contrib/lease-tools/dhcp_release.c b/contrib/lease-tools/dhcp_release.c new file mode 100644 index 0000000..201fcd3 --- /dev/null +++ b/contrib/lease-tools/dhcp_release.c @@ -0,0 +1,332 @@ +/* Copyright (c) 2006 Simon Kelley + + 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; version 2 dated June, 1991. + + 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. +*/ + +/* dhcp_release
+ MUST be run as root - will fail otherwise. */ + +/* Send a DHCPRELEASE message via the specified interface + to tell the local DHCP server to delete a particular lease. + + The interface argument is the interface in which a DHCP + request _would_ be received if it was coming from the client, + rather than being faked up here. + + The address argument is a dotted-quad IP addresses and mandatory. + + The MAC address is colon separated hex, and is mandatory. It may be + prefixed by an address-type byte followed by -, eg + + 10-11:22:33:44:55:66 + + but if the address-type byte is missing it is assumed to be 1, the type + for ethernet. This encoding is the one used in dnsmasq lease files. + + The client-id is optional. If it is "*" then it treated as being missing. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DHCP_CHADDR_MAX 16 +#define BOOTREQUEST 1 +#define DHCP_COOKIE 0x63825363 +#define OPTION_SERVER_IDENTIFIER 54 +#define OPTION_CLIENT_ID 61 +#define OPTION_MESSAGE_TYPE 53 +#define OPTION_END 255 +#define DHCPRELEASE 7 +#define DHCP_SERVER_PORT 67 + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +struct dhcp_packet { + u8 op, htype, hlen, hops; + u32 xid; + u16 secs, flags; + struct in_addr ciaddr, yiaddr, siaddr, giaddr; + u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128]; + u32 cookie; + unsigned char options[308]; +}; + +static struct iovec iov; + +static int expand_buf(struct iovec *iov, size_t size) +{ + void *new; + + if (size <= iov->iov_len) + return 1; + + if (!(new = malloc(size))) + { + errno = ENOMEM; + return 0; + } + + if (iov->iov_base) + { + memcpy(new, iov->iov_base, iov->iov_len); + free(iov->iov_base); + } + + iov->iov_base = new; + iov->iov_len = size; + + return 1; +} + +static ssize_t netlink_recv(int fd) +{ + struct msghdr msg; + ssize_t rc; + + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + while (1) + { + msg.msg_flags = 0; + while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR); + + /* 2.2.x doesn't support MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a + big buffer and pray in that case. */ + if (rc == -1 && errno == EOPNOTSUPP) + { + if (!expand_buf(&iov, 2000)) + return -1; + break; + } + + if (rc == -1 || !(msg.msg_flags & MSG_TRUNC)) + break; + + if (!expand_buf(&iov, iov.iov_len + 100)) + return -1; + } + + /* finally, read it for real */ + while ((rc = recvmsg(fd, &msg, 0)) == -1 && errno == EINTR); + + return rc; +} + +static int parse_hex(char *in, unsigned char *out, int maxlen, int *mac_type) +{ + int i = 0; + char *r; + + if (mac_type) + *mac_type = 0; + + while (maxlen == -1 || i < maxlen) + { + for (r = in; *r != 0 && *r != ':' && *r != '-'; r++); + if (*r == 0) + maxlen = i; + + if (r != in ) + { + if (*r == '-' && i == 0 && mac_type) + { + *r = 0; + *mac_type = strtol(in, NULL, 16); + mac_type = NULL; + } + else + { + *r = 0; + out[i] = strtol(in, NULL, 16); + i++; + } + } + in = r+1; + } + return i; +} + +static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) +{ + return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); +} + +static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index) +{ + struct sockaddr_nl addr; + struct nlmsghdr *h; + ssize_t len; + + struct { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + + addr.nl_family = AF_NETLINK; + addr.nl_pad = 0; + addr.nl_groups = 0; + addr.nl_pid = 0; /* address to kernel */ + + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = RTM_GETADDR; + req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 1; + req.g.rtgen_family = AF_INET; + + if (sendto(fd, (void *)&req, sizeof(req), 0, + (struct sockaddr *)&addr, sizeof(addr)) == -1) + { + perror("sendto failed"); + exit(1); + } + + while (1) + { + if ((len = netlink_recv(fd)) == -1) + { + perror("netlink"); + exit(1); + } + + for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) + if (h->nlmsg_type == NLMSG_DONE) + exit(0); + else if (h->nlmsg_type == RTM_NEWADDR) + { + struct ifaddrmsg *ifa = NLMSG_DATA(h); + struct rtattr *rta; + unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)); + + if (ifa->ifa_index == index && ifa->ifa_family == AF_INET) + { + struct in_addr netmask, addr; + + netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen)); + addr.s_addr = 0; + + for (rta = IFA_RTA(ifa); RTA_OK(rta, len1); rta = RTA_NEXT(rta, len1)) + if (rta->rta_type == IFA_LOCAL) + addr = *((struct in_addr *)(rta+1)); + + if (addr.s_addr && is_same_net(addr, client, netmask)) + return addr; + } + } + } + + exit(0); +} + +int main(int argc, char **argv) +{ + struct in_addr server, lease; + int mac_type; + struct dhcp_packet packet; + unsigned char *p = packet.options; + struct sockaddr_in dest; + struct ifreq ifr; + int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + + if (argc < 4 || argc > 5) + { + fprintf(stderr, "usage: dhcp_release []\n"); + exit(1); + } + + if (fd == -1 || nl == -1) + { + perror("cannot create socket"); + exit(1); + } + + /* This voodoo fakes up a packet coming from the correct interface, which really matters for + a DHCP server */ + strcpy(ifr.ifr_name, argv[1]); + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) + { + perror("cannot setup interface"); + exit(1); + } + + if (inet_addr(argv[2]) == INADDR_NONE) + { + perror("invalid ip address"); + exit(1); + } + + lease.s_addr = inet_addr(argv[2]); + server = find_interface(lease, nl, if_nametoindex(argv[1])); + + memset(&packet, 0, sizeof(packet)); + + packet.hlen = parse_hex(argv[3], packet.chaddr, DHCP_CHADDR_MAX, &mac_type); + if (mac_type == 0) + packet.htype = ARPHRD_ETHER; + else + packet.htype = mac_type; + + packet.op = BOOTREQUEST; + packet.ciaddr = lease; + packet.cookie = htonl(DHCP_COOKIE); + + *(p++) = OPTION_MESSAGE_TYPE; + *(p++) = 1; + *(p++) = DHCPRELEASE; + + *(p++) = OPTION_SERVER_IDENTIFIER; + *(p++) = sizeof(server); + memcpy(p, &server, sizeof(server)); + p += sizeof(server); + + if (argc == 5 && strcmp(argv[4], "*") != 0) + { + unsigned int clid_len = parse_hex(argv[4], p+2, 255, NULL); + *(p++) = OPTION_CLIENT_ID; + *(p++) = clid_len; + p += clid_len; + } + + *(p++) = OPTION_END; + + dest.sin_family = AF_INET; + dest.sin_port = ntohs(DHCP_SERVER_PORT); + dest.sin_addr = server; + + if (sendto(fd, &packet, sizeof(packet), 0, + (struct sockaddr *)&dest, sizeof(dest)) == -1) + { + perror("sendto failed"); + exit(1); + } + + return 0; +} diff --git a/contrib/lease-tools/dhcp_release6.1 b/contrib/lease-tools/dhcp_release6.1 new file mode 100644 index 0000000..763e01c --- /dev/null +++ b/contrib/lease-tools/dhcp_release6.1 @@ -0,0 +1,38 @@ +.TH DHCP_RELEASE 1 +.SH NAME +dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server. +.SH SYNOPSIS +.B dhcp_release6 --iface --client-id --server-id +server-id --iaid --ip [--dry-run] [--help] +.SH "DESCRIPTION" +A utility which forces the DHCP server running on this machine to release a +DHCPv6 lease. +.SS OPTIONS +.IP "-a, --ip" +IPv6 address to release. +.IP "-c, --client-id" +Colon-separated hex string representing DHCPv6 client id. Normally +it can be found in leases file both on client and server. +.IP "-d, --dry-run" +Print hexadecimal representation of generated DHCPv6 release packet to standard +output and exit. +.IP "-h, --help" +print usage information to standard output and exit. +.IP "-i, --iaid" +Decimal representation of DHCPv6 IAID. Normally it can be found in leases file +both on client and server. +.IP "-n, --iface" +Network interface to send a DHCPv6 release packet from. +.IP "-s, --server-id" +Colon-separated hex string representing DHCPv6 server id. Normally +it can be found in leases file both on client and server. +.SH NOTES +MUST be run as root - will fail otherwise. +.SH LIMITATIONS +Only usable on IPv6 DHCP leases. +.SH SEE ALSO +.BR dnsmasq (8) +.SH AUTHOR +This manual page was written by Simon Kelley . + + diff --git a/contrib/lease-tools/dhcp_release6.c b/contrib/lease-tools/dhcp_release6.c new file mode 100644 index 0000000..7f79fa7 --- /dev/null +++ b/contrib/lease-tools/dhcp_release6.c @@ -0,0 +1,496 @@ +/* + dhcp_release6 --iface --client-id --server-id + server-id --iaid --ip [--dry-run] [--help] + MUST be run as root - will fail otherwise + */ + +/* Send a DHCPRELEASE message to IPv6 multicast address via the specified interface + to tell the local DHCP server to delete a particular lease. + + The interface argument is the interface in which a DHCP + request _would_ be received if it was coming from the client, + rather than being faked up here. + + The client-id argument is colon-separated hex string and mandatory. Normally + it can be found in leases file both on client and server + + The server-id argument is colon-separated hex string and mandatory. Normally + it can be found in leases file both on client and server. + + The iaid argument is numeric string and mandatory. Normally + it can be found in leases file both on client and server. + + IP is an IPv6 address to release + + If --dry-run is specified, dhcp_release6 just prints hexadecimal representation of + packet to send to stdout and exits. + + If --help is specified, dhcp_release6 print usage information to stdout and exits + + + + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NOT_REPLY_CODE 115 +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +enum DHCP6_TYPES + { + SOLICIT = 1, + ADVERTISE = 2, + REQUEST = 3, + CONFIRM = 4, + RENEW = 5, + REBIND = 6, + REPLY = 7, + RELEASE = 8, + DECLINE = 9, + RECONFIGURE = 10, + INFORMATION_REQUEST = 11, + RELAY_FORW = 12, + RELAY_REPL = 13 + + }; + +enum DHCP6_OPTIONS + { + CLIENTID = 1, + SERVERID = 2, + IA_NA = 3, + IA_TA = 4, + IAADDR = 5, + ORO = 6, + PREFERENCE = 7, + ELAPSED_TIME = 8, + RELAY_MSG = 9, + AUTH = 11, + UNICAST = 12, + STATUS_CODE = 13, + RAPID_COMMIT = 14, + USER_CLASS = 15, + VENDOR_CLASS = 16, + VENDOR_OPTS = 17, + INTERFACE_ID = 18, + RECONF_MSG = 19, + RECONF_ACCEPT = 20, + }; + +enum DHCP6_STATUSES + { + SUCCESS = 0, + UNSPEC_FAIL = 1, + NOADDR_AVAIL=2, + NO_BINDING = 3, + NOT_ON_LINK = 4, + USE_MULTICAST =5 + }; + +static struct option longopts[] = { + {"ip", required_argument, 0, 'a' }, + {"server-id", required_argument, 0, 's' }, + {"client-id", required_argument, 0, 'c' }, + {"iface", required_argument, 0, 'n' }, + {"iaid", required_argument, 0, 'i' }, + {"dry-run", no_argument, 0, 'd' }, + {"help", no_argument, 0, 'h' }, + {0, 0, 0, 0 } +}; + +const short DHCP6_CLIENT_PORT = 546; +const short DHCP6_SERVER_PORT = 547; + +const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2"; + +struct dhcp6_option { + uint16_t type; + uint16_t len; + char value[1024]; +}; + +struct dhcp6_iaaddr_option { + uint16_t type; + uint16_t len; + struct in6_addr ip; + uint32_t preferred_lifetime; + uint32_t valid_lifetime; +}; + +struct dhcp6_iana_option { + uint16_t type; + uint16_t len; + uint32_t iaid; + uint32_t t1; + uint32_t t2; + char options[1024]; +}; + + +struct dhcp6_packet { + size_t len; + char buf[2048]; +}; + +size_t pack_duid(const char* str, char* dst) +{ + char* tmp = strdup(str); + char* tmp_to_free = tmp; + char *ptr; + uint8_t write_pos = 0; + while ((ptr = strtok (tmp, ":"))) + { + dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16); + write_pos += 1; + tmp = NULL; + } + + free(tmp_to_free); + return write_pos; +} + +struct dhcp6_option create_client_id_option(const char* duid) +{ + struct dhcp6_option option; + option.type = htons(CLIENTID); + bzero(option.value, sizeof(option.value)); + option.len = htons(pack_duid(duid, option.value)); + return option; +} + +struct dhcp6_option create_server_id_option(const char* duid) +{ + struct dhcp6_option option; + option.type = htons(SERVERID); + bzero(option.value, sizeof(option.value)); + option.len = htons(pack_duid(duid, option.value)); + return option; +} + +struct dhcp6_iaaddr_option create_iaadr_option(const char* ip) +{ + struct dhcp6_iaaddr_option result; + result.type =htons(IAADDR); + /* no suboptions needed here, so length is 24 */ + result.len = htons(24); + result.preferred_lifetime = 0; + result.valid_lifetime = 0; + int s = inet_pton(AF_INET6, ip, &(result.ip)); + if (s <= 0) { + if (s == 0) + fprintf(stderr, "Not in presentation format"); + else + perror("inet_pton"); + exit(EXIT_FAILURE); + } + + return result; +} + +struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr) +{ + struct dhcp6_iana_option result; + result.type = htons(IA_NA); + result.iaid = htonl(atoi(iaid)); + result.t1 = 0; + result.t2 = 0; + result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t)); + memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t)); + return result; +} + +struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id) +{ + struct dhcp6_packet result; + bzero(result.buf, sizeof(result.buf)); + /* message_type */ + result.buf[0] = RELEASE; + /* tx_id */ + bzero(result.buf+1, 3); + + struct dhcp6_option client_option = create_client_id_option(client_id); + struct dhcp6_option server_option = create_server_id_option(server_id); + struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip); + struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option); + int offset = 4; + memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t)); + offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) ); + memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) ); + offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t)); + memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) ); + offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t)); + result.len = offset; + return result; +} + +uint16_t parse_iana_suboption(char* buf, size_t len) +{ + size_t current_pos = 0; + char option_value[1024]; + while (current_pos < len) + { + uint16_t option_type, option_len; + memcpy(&option_type,buf + current_pos, sizeof(uint16_t)); + memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t)); + option_type = ntohs(option_type); + option_len = ntohs(option_len); + current_pos += 2 * sizeof(uint16_t); + if (option_type == STATUS_CODE) + { + uint16_t status; + memcpy(&status, buf + current_pos, sizeof(uint16_t)); + status = ntohs(status); + if (status != SUCCESS) + { + memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t)); + option_value[option_len-sizeof(uint16_t)] ='\0'; + fprintf(stderr, "Error: %s\n", option_value); + } + return status; + } + } + + return -2; +} + +int16_t parse_packet(char* buf, size_t len) +{ + int16_t ret = -1; + uint8_t type = buf[0]; + /*skipping tx id. you need it, uncomment following line + uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]); + */ + size_t current_pos = 4; + if (type != REPLY ) + return NOT_REPLY_CODE; + + char option_value[1024]; + while (current_pos < len) + { + uint16_t option_type, option_len; + memcpy(&option_type,buf + current_pos, sizeof(uint16_t)); + memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t)); + option_type = ntohs(option_type); + option_len = ntohs(option_len); + current_pos += 2 * sizeof(uint16_t); + if (option_type == STATUS_CODE) + { + uint16_t status; + memcpy(&status, buf + current_pos, sizeof(uint16_t)); + status = ntohs(status); + if (status != SUCCESS) + { + memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t)); + fprintf(stderr, "Error: %d %s\n", status, option_value); + return status; + } + + /* Got success status, return that if there's no specific error in an IA_NA. */ + ret = SUCCESS; + } + + if (option_type == IA_NA ) + { + uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24); + if (result) + return result; + } + + current_pos += option_len; + } + + return ret; +} + +void usage(const char* arg, FILE* stream) +{ + const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help"; + fprintf (stream, "Usage: %s %s\n", arg, usage_string); +} + +int send_release_packet(const char* iface, struct dhcp6_packet* packet) +{ + struct sockaddr_in6 server_addr, client_addr; + char response[1400]; + int sock = socket(PF_INET6, SOCK_DGRAM, 0); + int i = 0; + if (sock < 0) + { + perror("creating socket"); + return -1; + } + + if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) + { + perror("SO_BINDTODEVICE"); + close(sock); + return -1; + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin6_family = AF_INET6; + client_addr.sin6_family = AF_INET6; + client_addr.sin6_port = htons(DHCP6_CLIENT_PORT); + client_addr.sin6_flowinfo = 0; + client_addr.sin6_scope_id =0; + inet_pton(AF_INET6, "::", &client_addr.sin6_addr); + bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)); + inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr); + server_addr.sin6_port = htons(DHCP6_SERVER_PORT); + int16_t recv_size = 0; + for (i = 0; i < 5; i++) + { + if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) + { + perror("sendto failed"); + exit(4); + } + + recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0); + if (recv_size == -1) + { + if (errno == EAGAIN) + { + sleep(1); + continue; + } + else + { + perror("recvfrom"); + } + } + + int16_t result = parse_packet(response, recv_size); + if (result == NOT_REPLY_CODE) + { + sleep(1); + continue; + } + return result; + } + + fprintf(stderr, "Response timed out\n"); + return -1; +} + + +int main(int argc, char * const argv[]) +{ + const char* UNINITIALIZED = ""; + const char* iface = UNINITIALIZED; + const char* ip = UNINITIALIZED; + const char* client_id = UNINITIALIZED; + const char* server_id = UNINITIALIZED; + const char* iaid = UNINITIALIZED; + int dry_run = 0; + while (1) + { + int option_index = 0; + int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index); + if (c == -1) + break; + + switch(c) + { + case 0: + if (longopts[option_index].flag !=0) + break; + + printf ("option %s", longopts[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case 'i': + iaid = optarg; + break; + case 'n': + iface = optarg; + break; + case 'a': + ip = optarg; + break; + case 'c': + client_id = optarg; + break; + case 'd': + dry_run = 1; + break; + case 's': + server_id = optarg; + break; + case 'h': + usage(argv[0], stdout); + return 0; + case '?': + usage(argv[0], stderr); + return -1; + default: + abort(); + + } + } + + if (iaid == UNINITIALIZED) + { + fprintf(stderr, "Missing required iaid parameter\n"); + usage(argv[0], stderr); + return -1; + } + + if (server_id == UNINITIALIZED) + { + fprintf(stderr, "Missing required server-id parameter\n"); + usage(argv[0], stderr); + return -1; + } + + if (client_id == UNINITIALIZED) + { + fprintf(stderr, "Missing required client-id parameter\n"); + usage(argv[0], stderr); + return -1; + } + + if (ip == UNINITIALIZED) + { + fprintf(stderr, "Missing required ip parameter\n"); + usage(argv[0], stderr); + return -1; + } + + if (iface == UNINITIALIZED) + { + fprintf(stderr, "Missing required iface parameter\n"); + usage(argv[0], stderr); + return -1; + } + + + + struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id); + + if (dry_run) + { + uint16_t i; + + for(i=0; i diff --git a/contrib/systemd/dbus_activation b/contrib/systemd/dbus_activation index 38f0822..94a8820 100644 --- a/contrib/systemd/dbus_activation +++ b/contrib/systemd/dbus_activation @@ -1,57 +1,57 @@ -To: dnsmasq-discuss@lists.thekelleys.org.uk -From: Alex Elsayed -Date: Tue, 15 May 2012 01:53:54 -0700 -Subject: [Dnsmasq-discuss] [PATCH] Support dbus activation - -Introduce dbus service file and turn dbus on in the systemd -unit. - -Note to packagers: -To add support for dbus activation, you must install the dbus -service file (dbus/uk.org.thekelleys.dnsmasq.service) into -$DATADIR/dbus-1/system-services. - ---- - contrib/systemd/dnsmasq.service | 2 +- - dbus/uk.org.thekelleys.dnsmasq.service | 7 +++++++ - 2 files changed, 8 insertions(+), 1 deletion(-) - create mode 100644 dbus/uk.org.thekelleys.dnsmasq.service - -diff --git a/contrib/systemd/dnsmasq.service -b/contrib/systemd/dnsmasq.service -index a27fe6d..4a784d3 100644 ---- a/contrib/systemd/dnsmasq.service -+++ b/contrib/systemd/dnsmasq.service -@@ -5,7 +5,7 @@ Description=A lightweight DHCP and caching DNS server - Type=dbus - BusName=uk.org.thekelleys.dnsmasq - ExecStartPre=/usr/sbin/dnsmasq --test --ExecStart=/usr/sbin/dnsmasq -k -+ExecStart=/usr/sbin/dnsmasq -k -1 - ExecReload=/bin/kill -HUP $MAINPID - - [Install] -diff --git a/dbus/uk.org.thekelleys.dnsmasq.service -b/dbus/uk.org.thekelleys.dnsmasq.service -new file mode 100644 -index 0000000..f5fe98d ---- /dev/null -+++ b/dbus/uk.org.thekelleys.dnsmasq.service -@@ -0,0 +1,7 @@ -+[D-BUS Service] -+Name=uk.org.thekelleys.dnsmasq -+Exec=/usr/sbin/dnsmasq -k -1 -+User=root -+SystemdService=dnsmasq.service -+ -+ --- -1.7.10.2 - - - -_______________________________________________ -Dnsmasq-discuss mailing list -Dnsmasq-discuss@lists.thekelleys.org.uk -http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss - +To: dnsmasq-discuss@lists.thekelleys.org.uk +From: Alex Elsayed +Date: Tue, 15 May 2012 01:53:54 -0700 +Subject: [Dnsmasq-discuss] [PATCH] Support dbus activation + +Introduce dbus service file and turn dbus on in the systemd +unit. + +Note to packagers: +To add support for dbus activation, you must install the dbus +service file (dbus/uk.org.thekelleys.dnsmasq.service) into +$DATADIR/dbus-1/system-services. + +--- + contrib/systemd/dnsmasq.service | 2 +- + dbus/uk.org.thekelleys.dnsmasq.service | 7 +++++++ + 2 files changed, 8 insertions(+), 1 deletion(-) + create mode 100644 dbus/uk.org.thekelleys.dnsmasq.service + +diff --git a/contrib/systemd/dnsmasq.service +b/contrib/systemd/dnsmasq.service +index a27fe6d..4a784d3 100644 +--- a/contrib/systemd/dnsmasq.service ++++ b/contrib/systemd/dnsmasq.service +@@ -5,7 +5,7 @@ Description=A lightweight DHCP and caching DNS server + Type=dbus + BusName=uk.org.thekelleys.dnsmasq + ExecStartPre=/usr/sbin/dnsmasq --test +-ExecStart=/usr/sbin/dnsmasq -k ++ExecStart=/usr/sbin/dnsmasq -k -1 + ExecReload=/bin/kill -HUP $MAINPID + + [Install] +diff --git a/dbus/uk.org.thekelleys.dnsmasq.service +b/dbus/uk.org.thekelleys.dnsmasq.service +new file mode 100644 +index 0000000..f5fe98d +--- /dev/null ++++ b/dbus/uk.org.thekelleys.dnsmasq.service +@@ -0,0 +1,7 @@ ++[D-BUS Service] ++Name=uk.org.thekelleys.dnsmasq ++Exec=/usr/sbin/dnsmasq -k -1 ++User=root ++SystemdService=dnsmasq.service ++ ++ +-- +1.7.10.2 + + + +_______________________________________________ +Dnsmasq-discuss mailing list +Dnsmasq-discuss@lists.thekelleys.org.uk +http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss + diff --git a/contrib/try-all-ns/README-2.47 b/contrib/try-all-ns/README-2.47 index 3ebec65..bfe4ec7 100644 --- a/contrib/try-all-ns/README-2.47 +++ b/contrib/try-all-ns/README-2.47 @@ -2,7 +2,7 @@ A remake of patch Bob Carroll had posted to dnsmasq, now compatible with version 2.47. Hopefully he doesn't mind (sending a copy of this mail to him too). -Maybe the patch in question is not acceptible +Maybe the patch in question is not acceptable as it doesn't add new switch, rather it binds itself to "strict-order". What it does is: if you have strict-order in the diff --git a/contrib/try-all-ns/README-2.78 b/contrib/try-all-ns/README-2.78 new file mode 100644 index 0000000..3dfd200 --- /dev/null +++ b/contrib/try-all-ns/README-2.78 @@ -0,0 +1,10 @@ +Hi, +I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly. + +Find the patch attached. + +Regards, + +Rasmus Ahlberg +Software Developer, R&D +Electrolux Small Appliances diff --git a/contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch b/contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch new file mode 100644 index 0000000..700439e --- /dev/null +++ b/contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch @@ -0,0 +1,20 @@ +diff --git a/src/forward.c b/src/forward.c +index e3fa94b..ecf3b98 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now) + + /* Note: if we send extra options in the EDNS0 header, we can't recreate + the query from the reply. */ +- if (RCODE(header) == REFUSED && +- forward->forwardall == 0 && +- !(forward->flags & FREC_HAS_EXTRADATA)) ++ if ((RCODE(header) == REFUSED && ++ forward->forwardall == 0 && ++ !(forward->flags & FREC_HAS_EXTRADATA)) || ++ /* If strict-order is set, try next server on NXDOMAIN reply */ ++ (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) && ++ server->next != NULL)) + /* for broken servers, attempt to send to another one. */ + { + unsigned char *pheader; diff --git a/contrib/webmin/README b/contrib/webmin/README index 8a8f937..2278871 100644 --- a/contrib/webmin/README +++ b/contrib/webmin/README @@ -1,5 +1,5 @@ -This is the README for the DNSmasq webmin module. +This is the README for the Dnsmasq webmin module. Problems: @@ -48,7 +48,7 @@ wade through the config file and man pages again. If you modify it, or add a language file, and you have a spare moment, please e-mail me - I won't be upset at all if you fix my poor coding! -(rather the opposite - I'd be pleased someone found it usefull) +(rather the opposite - I'd be pleased someone found it useful) Cheers, Neil Fisher diff --git a/contrib/wrt/Makefile b/contrib/wrt/Makefile deleted file mode 100644 index 68e8d32..0000000 --- a/contrib/wrt/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -CFLAGS?= -O2 -Wall -W - -all: dhcp_release dhcp_lease_time - -clean: - rm -f *~ *.o core dhcp_release dhcp_lease_time diff --git a/contrib/wrt/README b/contrib/wrt/README index 862046f..981db9f 100644 --- a/contrib/wrt/README +++ b/contrib/wrt/README @@ -4,7 +4,7 @@ reboot, then it will eventually be restored as hosts renew their leases. Until a host renews (which may take hours/days) it will not exist in the DNS if dnsmasq's DDNS function is in use. -*WRT systems remount all non-volatile fileystems read-only after boot, +*WRT systems remount all non-volatile filesystems read-only after boot, so the normal leasefile will not work. They do, however have NV storage, accessed with the nvram command: @@ -62,7 +62,7 @@ about 100 bytes, so restricting the number of leases to 50 will limit use to half that. (The default limit in the distributed source is 150) Any UI script which reads the dnsmasq leasefile will have to be -ammended, probably by changing it to read the output of +amended, probably by changing it to read the output of `lease_update init` instead. diff --git a/contrib/wrt/dhcp_lease_time.1 b/contrib/wrt/dhcp_lease_time.1 deleted file mode 100644 index 2fa78d3..0000000 --- a/contrib/wrt/dhcp_lease_time.1 +++ /dev/null @@ -1,25 +0,0 @@ -.TH DHCP_LEASE_TIME 1 -.SH NAME -dhcp_lease_time \- Query remaining time of a lease on a the local dnsmasq DHCP server. -.SH SYNOPSIS -.B dhcp_lease_time
-.SH "DESCRIPTION" -Send a DHCPINFORM message to a dnsmasq server running on the local host -and print (to stdout) the time remaining in any lease for the given -address. The time is given as string printed to stdout. - -If an error occurs or no lease exists for the given address, -nothing is sent to stdout a message is sent to stderr and a -non-zero error code is returned. - -Requires dnsmasq 2.67 or later and may not work with other DHCP servers. - -The address argument is a dotted-quad IP addresses and mandatory. -.SH LIMITATIONS -Only works with IPv4 addresses and DHCP leases. -.SH SEE ALSO -.BR dnsmasq (8) -.SH AUTHOR -This manual page was written by Simon Kelley . - - diff --git a/contrib/wrt/dhcp_lease_time.c b/contrib/wrt/dhcp_lease_time.c deleted file mode 100644 index b438ef7..0000000 --- a/contrib/wrt/dhcp_lease_time.c +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (c) 2007 Simon Kelley - - 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; version 2 dated June, 1991. - - 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. -*/ - -/* dhcp_lease_time
*/ - -/* Send a DHCPINFORM message to a dnsmasq server running on the local host - and print (to stdout) the time remaining in any lease for the given - address. The time is given as string printed to stdout. - - If an error occurs or no lease exists for the given address, - nothing is sent to stdout a message is sent to stderr and a - non-zero error code is returned. - - This version requires dnsmasq 2.67 or later. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DHCP_CHADDR_MAX 16 -#define BOOTREQUEST 1 -#define DHCP_COOKIE 0x63825363 -#define OPTION_PAD 0 -#define OPTION_LEASE_TIME 51 -#define OPTION_OVERLOAD 52 -#define OPTION_MESSAGE_TYPE 53 -#define OPTION_REQUESTED_OPTIONS 55 -#define OPTION_END 255 -#define DHCPINFORM 8 -#define DHCP_SERVER_PORT 67 - -#define option_len(opt) ((int)(((unsigned char *)(opt))[1])) -#define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2])) - - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; - -struct dhcp_packet { - u8 op, htype, hlen, hops; - u32 xid; - u16 secs, flags; - struct in_addr ciaddr, yiaddr, siaddr, giaddr; - u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128]; - u32 cookie; - unsigned char options[308]; -}; - -static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize) -{ - while (*p != OPTION_END) - { - if (p >= end) - return NULL; /* malformed packet */ - else if (*p == OPTION_PAD) - p++; - else - { - int opt_len; - if (p >= end - 2) - return NULL; /* malformed packet */ - opt_len = option_len(p); - if (p >= end - (2 + opt_len)) - return NULL; /* malformed packet */ - if (*p == opt && opt_len >= minsize) - return p; - p += opt_len + 2; - } - } - - return opt == OPTION_END ? p : NULL; -} - -static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize) -{ - unsigned char *ret, *overload; - - /* skip over DHCP cookie; */ - if ((ret = option_find1(&mess->options[0], ((unsigned char *)mess) + size, opt_type, minsize))) - return ret; - - /* look for overload option. */ - if (!(overload = option_find1(&mess->options[0], ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1))) - return NULL; - - /* Can we look in filename area ? */ - if ((overload[2] & 1) && - (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize))) - return ret; - - /* finally try sname area */ - if ((overload[2] & 2) && - (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize))) - return ret; - - return NULL; -} - -static unsigned int option_uint(unsigned char *opt, int size) -{ - /* this worries about unaligned data and byte order */ - unsigned int ret = 0; - int i; - unsigned char *p = option_ptr(opt); - - for (i = 0; i < size; i++) - ret = (ret << 8) | *p++; - - return ret; -} - -int main(int argc, char **argv) -{ - struct in_addr lease; - struct dhcp_packet packet; - unsigned char *p = packet.options; - struct sockaddr_in dest; - int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - ssize_t rc; - - if (argc < 2) - { - fprintf(stderr, "usage: dhcp_lease_time
\n"); - exit(1); - } - - if (fd == -1) - { - perror("cannot create socket"); - exit(1); - } - - lease.s_addr = inet_addr(argv[1]); - - memset(&packet, 0, sizeof(packet)); - - packet.hlen = 0; - packet.htype = 0; - - packet.op = BOOTREQUEST; - packet.ciaddr = lease; - packet.cookie = htonl(DHCP_COOKIE); - - *(p++) = OPTION_MESSAGE_TYPE; - *(p++) = 1; - *(p++) = DHCPINFORM; - - /* Explicity request the lease time, it won't be sent otherwise: - this is a dnsmasq extension, not standard. */ - *(p++) = OPTION_REQUESTED_OPTIONS; - *(p++) = 1; - *(p++) = OPTION_LEASE_TIME; - - *(p++) = OPTION_END; - - dest.sin_family = AF_INET; - dest.sin_addr.s_addr = inet_addr("127.0.0.1"); - dest.sin_port = ntohs(DHCP_SERVER_PORT); - - if (sendto(fd, &packet, sizeof(packet), 0, - (struct sockaddr *)&dest, sizeof(dest)) == -1) - { - perror("sendto failed"); - exit(1); - } - - alarm(3); /* noddy timeout. */ - - rc = recv(fd, &packet, sizeof(packet), 0); - - if (rc < (ssize_t)(sizeof(packet) - sizeof(packet.options))) - { - perror("recv failed"); - exit(1); - } - - if ((p = option_find(&packet, (size_t)rc, OPTION_LEASE_TIME, 4))) - { - unsigned int t = option_uint(p, 4); - if (t == 0xffffffff) - printf("infinite"); - else - { - unsigned int x; - if ((x = t/86400)) - printf("%dd", x); - if ((x = (t/3600)%24)) - printf("%dh", x); - if ((x = (t/60)%60)) - printf("%dm", x); - if ((x = t%60)) - printf("%ds", x); - } - return 0; - } - - return 1; /* no lease */ -} diff --git a/contrib/wrt/dhcp_release.1 b/contrib/wrt/dhcp_release.1 deleted file mode 100644 index e71aba0..0000000 --- a/contrib/wrt/dhcp_release.1 +++ /dev/null @@ -1,37 +0,0 @@ -.TH DHCP_RELEASE 1 -.SH NAME -dhcp_release \- Release a DHCP lease on a the local dnsmasq DHCP server. -.SH SYNOPSIS -.B dhcp_release
-.SH "DESCRIPTION" -A utility which forces the DHCP server running on this machine to release a -DHCP lease. -.PP -Send a DHCPRELEASE message via the specified interface to tell the -local DHCP server to delete a particular lease. - -The interface argument is the interface in which a DHCP -request _would_ be received if it was coming from the client, -rather than being faked up here. - -The address argument is a dotted-quad IP addresses and mandatory. - -The MAC address is colon separated hex, and is mandatory. It may be -prefixed by an address-type byte followed by -, eg - -10-11:22:33:44:55:66 - -but if the address-type byte is missing it is assumed to be 1, the type -for ethernet. This encoding is the one used in dnsmasq lease files. - -The client-id is optional. If it is "*" then it treated as being missing. -.SH NOTES -MUST be run as root - will fail otherwise. -.SH LIMITATIONS -Only usable on IPv4 DHCP leases. -.SH SEE ALSO -.BR dnsmasq (8) -.SH AUTHOR -This manual page was written by Simon Kelley . - - diff --git a/contrib/wrt/dhcp_release.c b/contrib/wrt/dhcp_release.c deleted file mode 100644 index a51f04b..0000000 --- a/contrib/wrt/dhcp_release.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (c) 2006 Simon Kelley - - 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; version 2 dated June, 1991. - - 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. -*/ - -/* dhcp_release
- MUST be run as root - will fail otherwise. */ - -/* Send a DHCPRELEASE message via the specified interface - to tell the local DHCP server to delete a particular lease. - - The interface argument is the interface in which a DHCP - request _would_ be received if it was coming from the client, - rather than being faked up here. - - The address argument is a dotted-quad IP addresses and mandatory. - - The MAC address is colon separated hex, and is mandatory. It may be - prefixed by an address-type byte followed by -, eg - - 10-11:22:33:44:55:66 - - but if the address-type byte is missing it is assumed to be 1, the type - for ethernet. This encoding is the one used in dnsmasq lease files. - - The client-id is optional. If it is "*" then it treated as being missing. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DHCP_CHADDR_MAX 16 -#define BOOTREQUEST 1 -#define DHCP_COOKIE 0x63825363 -#define OPTION_SERVER_IDENTIFIER 54 -#define OPTION_CLIENT_ID 61 -#define OPTION_MESSAGE_TYPE 53 -#define OPTION_END 255 -#define DHCPRELEASE 7 -#define DHCP_SERVER_PORT 67 - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; - -struct dhcp_packet { - u8 op, htype, hlen, hops; - u32 xid; - u16 secs, flags; - struct in_addr ciaddr, yiaddr, siaddr, giaddr; - u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128]; - u32 cookie; - unsigned char options[308]; -}; - -static struct iovec iov; - -static int expand_buf(struct iovec *iov, size_t size) -{ - void *new; - - if (size <= iov->iov_len) - return 1; - - if (!(new = malloc(size))) - { - errno = ENOMEM; - return 0; - } - - if (iov->iov_base) - { - memcpy(new, iov->iov_base, iov->iov_len); - free(iov->iov_base); - } - - iov->iov_base = new; - iov->iov_len = size; - - return 1; -} - -static ssize_t netlink_recv(int fd) -{ - struct msghdr msg; - ssize_t rc; - - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - while (1) - { - msg.msg_flags = 0; - while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR); - - /* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a - big buffer and pray in that case. */ - if (rc == -1 && errno == EOPNOTSUPP) - { - if (!expand_buf(&iov, 2000)) - return -1; - break; - } - - if (rc == -1 || !(msg.msg_flags & MSG_TRUNC)) - break; - - if (!expand_buf(&iov, iov.iov_len + 100)) - return -1; - } - - /* finally, read it for real */ - while ((rc = recvmsg(fd, &msg, 0)) == -1 && errno == EINTR); - - return rc; -} - -static int parse_hex(char *in, unsigned char *out, int maxlen, int *mac_type) -{ - int i = 0; - char *r; - - if (mac_type) - *mac_type = 0; - - while (maxlen == -1 || i < maxlen) - { - for (r = in; *r != 0 && *r != ':' && *r != '-'; r++); - if (*r == 0) - maxlen = i; - - if (r != in ) - { - if (*r == '-' && i == 0 && mac_type) - { - *r = 0; - *mac_type = strtol(in, NULL, 16); - mac_type = NULL; - } - else - { - *r = 0; - out[i] = strtol(in, NULL, 16); - i++; - } - } - in = r+1; - } - return i; -} - -static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) -{ - return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); -} - -static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index) -{ - struct sockaddr_nl addr; - struct nlmsghdr *h; - ssize_t len; - - struct { - struct nlmsghdr nlh; - struct rtgenmsg g; - } req; - - addr.nl_family = AF_NETLINK; - addr.nl_pad = 0; - addr.nl_groups = 0; - addr.nl_pid = 0; /* address to kernel */ - - req.nlh.nlmsg_len = sizeof(req); - req.nlh.nlmsg_type = RTM_GETADDR; - req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK; - req.nlh.nlmsg_pid = 0; - req.nlh.nlmsg_seq = 1; - req.g.rtgen_family = AF_INET; - - if (sendto(fd, (void *)&req, sizeof(req), 0, - (struct sockaddr *)&addr, sizeof(addr)) == -1) - { - perror("sendto failed"); - exit(1); - } - - while (1) - { - if ((len = netlink_recv(fd)) == -1) - { - perror("netlink"); - exit(1); - } - - for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) - if (h->nlmsg_type == NLMSG_DONE) - exit(0); - else if (h->nlmsg_type == RTM_NEWADDR) - { - struct ifaddrmsg *ifa = NLMSG_DATA(h); - struct rtattr *rta; - unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)); - - if (ifa->ifa_index == index && ifa->ifa_family == AF_INET) - { - struct in_addr netmask, addr; - - netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen)); - addr.s_addr = 0; - - for (rta = IFA_RTA(ifa); RTA_OK(rta, len1); rta = RTA_NEXT(rta, len1)) - if (rta->rta_type == IFA_LOCAL) - addr = *((struct in_addr *)(rta+1)); - - if (addr.s_addr && is_same_net(addr, client, netmask)) - return addr; - } - } - } - - exit(0); -} - -int main(int argc, char **argv) -{ - struct in_addr server, lease; - int mac_type; - struct dhcp_packet packet; - unsigned char *p = packet.options; - struct sockaddr_in dest; - struct ifreq ifr; - int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - - if (argc < 4 || argc > 5) - { - fprintf(stderr, "usage: dhcp_release []\n"); - exit(1); - } - - if (fd == -1 || nl == -1) - { - perror("cannot create socket"); - exit(1); - } - - /* This voodoo fakes up a packet coming from the correct interface, which really matters for - a DHCP server */ - strcpy(ifr.ifr_name, argv[1]); - if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) - { - perror("cannot setup interface"); - exit(1); - } - - if (inet_addr(argv[2]) == INADDR_NONE) - { - perror("invalid ip address"); - exit(1); - } - - lease.s_addr = inet_addr(argv[2]); - server = find_interface(lease, nl, if_nametoindex(argv[1])); - - memset(&packet, 0, sizeof(packet)); - - packet.hlen = parse_hex(argv[3], packet.chaddr, DHCP_CHADDR_MAX, &mac_type); - if (mac_type == 0) - packet.htype = ARPHRD_ETHER; - else - packet.htype = mac_type; - - packet.op = BOOTREQUEST; - packet.ciaddr = lease; - packet.cookie = htonl(DHCP_COOKIE); - - *(p++) = OPTION_MESSAGE_TYPE; - *(p++) = 1; - *(p++) = DHCPRELEASE; - - *(p++) = OPTION_SERVER_IDENTIFIER; - *(p++) = sizeof(server); - memcpy(p, &server, sizeof(server)); - p += sizeof(server); - - if (argc == 5 && strcmp(argv[4], "*") != 0) - { - unsigned int clid_len = parse_hex(argv[4], p+2, 255, NULL); - *(p++) = OPTION_CLIENT_ID; - *(p++) = clid_len; - p += clid_len; - } - - *(p++) = OPTION_END; - - dest.sin_family = AF_INET; - dest.sin_port = ntohs(DHCP_SERVER_PORT); - dest.sin_addr = server; - - if (sendto(fd, &packet, sizeof(packet), 0, - (struct sockaddr *)&dest, sizeof(dest)) == -1) - { - perror("sendto failed"); - exit(1); - } - - return 0; -} -- cgit v1.2.3