File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / contrib / wrt / dhcp_lease_time.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (11 years ago) by misho
Branches: elwix, MAIN
CVS tags: v2_66p0, v2_66, HEAD
dnsmasq

    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>