Annotation of embedaddon/dnsmasq/contrib/wrt/dhcp_lease_time.c, revision 1.1
1.1 ! misho 1: /* Copyright (c) 2007 Simon Kelley
! 2:
! 3: This program is free software; you can redistribute it and/or modify
! 4: it under the terms of the GNU General Public License as published by
! 5: the Free Software Foundation; version 2 dated June, 1991.
! 6:
! 7: This program is distributed in the hope that it will be useful,
! 8: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 9: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 10: GNU General Public License for more details.
! 11: */
! 12:
! 13: /* dhcp_lease_time <address> */
! 14:
! 15: /* Send a DHCPINFORM message to a dnsmasq server running on the local host
! 16: and print (to stdout) the time remaining in any lease for the given
! 17: address. The time is given as string printed to stdout.
! 18:
! 19: If an error occurs or no lease exists for the given address,
! 20: nothing is sent to stdout a message is sent to stderr and a
! 21: non-zero error code is returned.
! 22:
! 23: Requires dnsmasq 2.40 or later.
! 24: */
! 25:
! 26: #include <sys/types.h>
! 27: #include <netinet/in.h>
! 28: #include <net/if.h>
! 29: #include <arpa/inet.h>
! 30: #include <sys/socket.h>
! 31: #include <unistd.h>
! 32: #include <stdio.h>
! 33: #include <string.h>
! 34: #include <stdlib.h>
! 35: #include <net/if_arp.h>
! 36: #include <sys/ioctl.h>
! 37: #include <linux/types.h>
! 38: #include <linux/netlink.h>
! 39: #include <linux/rtnetlink.h>
! 40: #include <errno.h>
! 41:
! 42: #define DHCP_CHADDR_MAX 16
! 43: #define BOOTREQUEST 1
! 44: #define DHCP_COOKIE 0x63825363
! 45: #define OPTION_PAD 0
! 46: #define OPTION_LEASE_TIME 51
! 47: #define OPTION_OVERLOAD 52
! 48: #define OPTION_MESSAGE_TYPE 53
! 49: #define OPTION_END 255
! 50: #define DHCPINFORM 8
! 51: #define DHCP_SERVER_PORT 67
! 52:
! 53: #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
! 54: #define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2]))
! 55:
! 56:
! 57: typedef unsigned char u8;
! 58: typedef unsigned short u16;
! 59: typedef unsigned int u32;
! 60:
! 61: struct dhcp_packet {
! 62: u8 op, htype, hlen, hops;
! 63: u32 xid;
! 64: u16 secs, flags;
! 65: struct in_addr ciaddr, yiaddr, siaddr, giaddr;
! 66: u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
! 67: u32 cookie;
! 68: unsigned char options[308];
! 69: };
! 70:
! 71: static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
! 72: {
! 73: while (*p != OPTION_END)
! 74: {
! 75: if (p >= end)
! 76: return NULL; /* malformed packet */
! 77: else if (*p == OPTION_PAD)
! 78: p++;
! 79: else
! 80: {
! 81: int opt_len;
! 82: if (p >= end - 2)
! 83: return NULL; /* malformed packet */
! 84: opt_len = option_len(p);
! 85: if (p >= end - (2 + opt_len))
! 86: return NULL; /* malformed packet */
! 87: if (*p == opt && opt_len >= minsize)
! 88: return p;
! 89: p += opt_len + 2;
! 90: }
! 91: }
! 92:
! 93: return opt == OPTION_END ? p : NULL;
! 94: }
! 95:
! 96: static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
! 97: {
! 98: unsigned char *ret, *overload;
! 99:
! 100: /* skip over DHCP cookie; */
! 101: if ((ret = option_find1(&mess->options[0], ((unsigned char *)mess) + size, opt_type, minsize)))
! 102: return ret;
! 103:
! 104: /* look for overload option. */
! 105: if (!(overload = option_find1(&mess->options[0], ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
! 106: return NULL;
! 107:
! 108: /* Can we look in filename area ? */
! 109: if ((overload[2] & 1) &&
! 110: (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
! 111: return ret;
! 112:
! 113: /* finally try sname area */
! 114: if ((overload[2] & 2) &&
! 115: (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
! 116: return ret;
! 117:
! 118: return NULL;
! 119: }
! 120:
! 121: static unsigned int option_uint(unsigned char *opt, int size)
! 122: {
! 123: /* this worries about unaligned data and byte order */
! 124: unsigned int ret = 0;
! 125: int i;
! 126: unsigned char *p = option_ptr(opt);
! 127:
! 128: for (i = 0; i < size; i++)
! 129: ret = (ret << 8) | *p++;
! 130:
! 131: return ret;
! 132: }
! 133:
! 134: int main(int argc, char **argv)
! 135: {
! 136: struct in_addr lease;
! 137: struct dhcp_packet packet;
! 138: unsigned char *p = packet.options;
! 139: struct sockaddr_in dest;
! 140: int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
! 141: ssize_t rc;
! 142:
! 143: if (argc < 2)
! 144: {
! 145: fprintf(stderr, "usage: dhcp_lease_time <address>\n");
! 146: exit(1);
! 147: }
! 148:
! 149: if (fd == -1)
! 150: {
! 151: perror("cannot create socket");
! 152: exit(1);
! 153: }
! 154:
! 155: lease.s_addr = inet_addr(argv[1]);
! 156:
! 157: memset(&packet, 0, sizeof(packet));
! 158:
! 159: packet.hlen = 0;
! 160: packet.htype = 0;
! 161:
! 162: packet.op = BOOTREQUEST;
! 163: packet.ciaddr = lease;
! 164: packet.cookie = htonl(DHCP_COOKIE);
! 165:
! 166: *(p++) = OPTION_MESSAGE_TYPE;
! 167: *(p++) = 1;
! 168: *(p++) = DHCPINFORM;
! 169:
! 170: *(p++) = OPTION_END;
! 171:
! 172: dest.sin_family = AF_INET;
! 173: dest.sin_addr.s_addr = inet_addr("127.0.0.1");
! 174: dest.sin_port = ntohs(DHCP_SERVER_PORT);
! 175:
! 176: if (sendto(fd, &packet, sizeof(packet), 0,
! 177: (struct sockaddr *)&dest, sizeof(dest)) == -1)
! 178: {
! 179: perror("sendto failed");
! 180: exit(1);
! 181: }
! 182:
! 183: alarm(3); /* noddy timeout. */
! 184:
! 185: rc = recv(fd, &packet, sizeof(packet), 0);
! 186:
! 187: if (rc < (ssize_t)(sizeof(packet) - sizeof(packet.options)))
! 188: {
! 189: perror("recv failed");
! 190: exit(1);
! 191: }
! 192:
! 193: if ((p = option_find(&packet, (size_t)rc, OPTION_LEASE_TIME, 4)))
! 194: {
! 195: unsigned int t = option_uint(p, 4);
! 196: if (t == 0xffffffff)
! 197: printf("infinite");
! 198: else
! 199: {
! 200: unsigned int x;
! 201: if ((x = t/86400))
! 202: printf("%dd", x);
! 203: if ((x = (t/3600)%24))
! 204: printf("%dh", x);
! 205: if ((x = (t/60)%60))
! 206: printf("%dm", x);
! 207: if ((x = t%60))
! 208: printf("%ds", x);
! 209: }
! 210: return 0;
! 211: }
! 212:
! 213: return 1; /* no lease */
! 214: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>