Return to dhcp_lease_time.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / contrib / wrt |
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: }