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>