Annotation of embedaddon/dnsmasq/contrib/lease-tools/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: This version requires dnsmasq 2.67 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_REQUESTED_OPTIONS 55
! 50: #define OPTION_END 255
! 51: #define DHCPINFORM 8
! 52: #define DHCP_SERVER_PORT 67
! 53:
! 54: #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
! 55: #define option_ptr(opt) ((void *)&(((unsigned char *)(opt))[2]))
! 56:
! 57:
! 58: typedef unsigned char u8;
! 59: typedef unsigned short u16;
! 60: typedef unsigned int u32;
! 61:
! 62: struct dhcp_packet {
! 63: u8 op, htype, hlen, hops;
! 64: u32 xid;
! 65: u16 secs, flags;
! 66: struct in_addr ciaddr, yiaddr, siaddr, giaddr;
! 67: u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
! 68: u32 cookie;
! 69: unsigned char options[308];
! 70: };
! 71:
! 72: static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
! 73: {
! 74: while (*p != OPTION_END)
! 75: {
! 76: if (p >= end)
! 77: return NULL; /* malformed packet */
! 78: else if (*p == OPTION_PAD)
! 79: p++;
! 80: else
! 81: {
! 82: int opt_len;
! 83: if (p >= end - 2)
! 84: return NULL; /* malformed packet */
! 85: opt_len = option_len(p);
! 86: if (p >= end - (2 + opt_len))
! 87: return NULL; /* malformed packet */
! 88: if (*p == opt && opt_len >= minsize)
! 89: return p;
! 90: p += opt_len + 2;
! 91: }
! 92: }
! 93:
! 94: return opt == OPTION_END ? p : NULL;
! 95: }
! 96:
! 97: static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
! 98: {
! 99: unsigned char *ret, *overload;
! 100:
! 101: /* skip over DHCP cookie; */
! 102: if ((ret = option_find1(&mess->options[0], ((unsigned char *)mess) + size, opt_type, minsize)))
! 103: return ret;
! 104:
! 105: /* look for overload option. */
! 106: if (!(overload = option_find1(&mess->options[0], ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
! 107: return NULL;
! 108:
! 109: /* Can we look in filename area ? */
! 110: if ((overload[2] & 1) &&
! 111: (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
! 112: return ret;
! 113:
! 114: /* finally try sname area */
! 115: if ((overload[2] & 2) &&
! 116: (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
! 117: return ret;
! 118:
! 119: return NULL;
! 120: }
! 121:
! 122: static unsigned int option_uint(unsigned char *opt, int size)
! 123: {
! 124: /* this worries about unaligned data and byte order */
! 125: unsigned int ret = 0;
! 126: int i;
! 127: unsigned char *p = option_ptr(opt);
! 128:
! 129: for (i = 0; i < size; i++)
! 130: ret = (ret << 8) | *p++;
! 131:
! 132: return ret;
! 133: }
! 134:
! 135: int main(int argc, char **argv)
! 136: {
! 137: struct in_addr lease;
! 138: struct dhcp_packet packet;
! 139: unsigned char *p = packet.options;
! 140: struct sockaddr_in dest;
! 141: int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
! 142: ssize_t rc;
! 143:
! 144: if (argc < 2)
! 145: {
! 146: fprintf(stderr, "usage: dhcp_lease_time <address>\n");
! 147: exit(1);
! 148: }
! 149:
! 150: if (fd == -1)
! 151: {
! 152: perror("cannot create socket");
! 153: exit(1);
! 154: }
! 155:
! 156: lease.s_addr = inet_addr(argv[1]);
! 157:
! 158: memset(&packet, 0, sizeof(packet));
! 159:
! 160: packet.hlen = 0;
! 161: packet.htype = 0;
! 162:
! 163: packet.op = BOOTREQUEST;
! 164: packet.ciaddr = lease;
! 165: packet.cookie = htonl(DHCP_COOKIE);
! 166:
! 167: *(p++) = OPTION_MESSAGE_TYPE;
! 168: *(p++) = 1;
! 169: *(p++) = DHCPINFORM;
! 170:
! 171: /* Explicity request the lease time, it won't be sent otherwise:
! 172: this is a dnsmasq extension, not standard. */
! 173: *(p++) = OPTION_REQUESTED_OPTIONS;
! 174: *(p++) = 1;
! 175: *(p++) = OPTION_LEASE_TIME;
! 176:
! 177: *(p++) = OPTION_END;
! 178:
! 179: dest.sin_family = AF_INET;
! 180: dest.sin_addr.s_addr = inet_addr("127.0.0.1");
! 181: dest.sin_port = ntohs(DHCP_SERVER_PORT);
! 182:
! 183: if (sendto(fd, &packet, sizeof(packet), 0,
! 184: (struct sockaddr *)&dest, sizeof(dest)) == -1)
! 185: {
! 186: perror("sendto failed");
! 187: exit(1);
! 188: }
! 189:
! 190: alarm(3); /* noddy timeout. */
! 191:
! 192: rc = recv(fd, &packet, sizeof(packet), 0);
! 193:
! 194: if (rc < (ssize_t)(sizeof(packet) - sizeof(packet.options)))
! 195: {
! 196: perror("recv failed");
! 197: exit(1);
! 198: }
! 199:
! 200: if ((p = option_find(&packet, (size_t)rc, OPTION_LEASE_TIME, 4)))
! 201: {
! 202: unsigned int t = option_uint(p, 4);
! 203: if (t == 0xffffffff)
! 204: printf("infinite");
! 205: else
! 206: {
! 207: unsigned int x;
! 208: if ((x = t/86400))
! 209: printf("%dd", x);
! 210: if ((x = (t/3600)%24))
! 211: printf("%dh", x);
! 212: if ((x = (t/60)%60))
! 213: printf("%dm", x);
! 214: if ((x = t%60))
! 215: printf("%ds", x);
! 216: }
! 217: return 0;
! 218: }
! 219:
! 220: return 1; /* no lease */
! 221: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>