Annotation of embedaddon/dnsmasq/contrib/wrt/dhcp_lease_time.c, revision 1.1.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>