Annotation of embedaddon/dhcping/dhcping.c, revision 1.1

1.1     ! misho       1: //
        !             2: // $Id: dhcping.c,v 1.3 2002/01/27 01:57:15 mavetju Exp $
        !             3: //
        !             4: 
        !             5: /*
        !             6:  * Copyright 2000, 2001, 2002 by Edwin Groothuis, edwin@mavetju.org
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  *
        !            29: */
        !            30: 
        !            31: #include <sys/types.h>
        !            32: #include <sys/socket.h>
        !            33: #include <sys/time.h>
        !            34: #include <sys/uio.h>
        !            35: #include <netinet/in.h>
        !            36: #include <unistd.h>
        !            37: #include <netdb.h>
        !            38: #include <stdio.h>
        !            39: #include <stdlib.h>
        !            40: #include <string.h>
        !            41: #include <time.h>
        !            42: 
        !            43: #include "dhcp_options.h"
        !            44: 
        !            45: #define BUF_SIZ 256*256
        !            46: 
        !            47: int offset=0;
        !            48: void addpacket(char *pktbuf,char *msgbuf,int size) {
        !            49:     memcpy(pktbuf+offset,msgbuf,size);
        !            50:     offset+=size;
        !            51: }
        !            52: 
        !            53: void dhcp_setup(char *);
        !            54: int  dhcp_read(void);
        !            55: void dhcp_close(void);
        !            56: void dhcp_dump(unsigned char *buffer,int size);
        !            57: void dhcp_inform(char *ipaddr,char *gwaddr,char *hardware);
        !            58: void dhcp_request(char *ipaddr,char *gwaddr,char *hardware);
        !            59: void dhcp_release(char *ipaddr,char *gwaddr,char *hardware);
        !            60: void dhcp_packet(int type,char *ciaddr,char *opt50,char *gwaddr,char *hardware);
        !            61: 
        !            62: int dhcp_socket;
        !            63: struct sockaddr_in dhcp_to;
        !            64: 
        !            65: int _serveripaddress;
        !            66: 
        !            67: int inform,request,verbose,VERBOSE,quiet;
        !            68: char *ci,*gi,*server,*hw;
        !            69: unsigned char serveridentifier[4];
        !            70: int maxwait=3;
        !            71: 
        !            72: void doargs(int argc,char **argv) {
        !            73:     char ch;
        !            74: 
        !            75:     inform=request=verbose=VERBOSE=quiet=0;
        !            76:     ci=gi=server="0.0.0.0";
        !            77:     hw="00:00:00:00:00:00";
        !            78: 
        !            79:     if (argc==1) {
        !            80:        printf("dhcping -c ciaddr -g giaddr -h chaddr -r -s server -t maxwait -i -v -q\n");
        !            81:        exit(1);
        !            82:     }
        !            83: 
        !            84:     while ((ch = getopt(argc,argv,"c:g:h:iqrs:t:vV"))>0) {
        !            85:        switch (ch) {
        !            86:        case 'c': ci=optarg;break;
        !            87:        case 'g': gi=optarg;break;
        !            88:        case 'h': hw=optarg;break;
        !            89:        case 'i': inform=1;break;
        !            90:        case 'q': quiet=1;break;
        !            91:        case 'r': request=1;break;
        !            92:        case 's': server=optarg;break;
        !            93:        case 't': maxwait=atoi(optarg);break;
        !            94:        case 'v': verbose=1;break;
        !            95:        case 'V': VERBOSE=1;break;
        !            96:        }
        !            97:     }
        !            98: 
        !            99:     if (request && inform) {
        !           100:        fprintf(stderr,"Error: -r and -i are mutally exclusive.\n");
        !           101:        exit(1);
        !           102:     }
        !           103: 
        !           104:     // DHCPREQUEST is by default.
        !           105:     if (!inform) request=1;
        !           106: }
        !           107: 
        !           108: int main(int argc,char **argv) {
        !           109:     fd_set read;
        !           110:     struct timeval timeout;
        !           111:     int foundpacket=0;
        !           112:     int returnvalue=0;
        !           113: 
        !           114:     if (geteuid()!=0) {
        !           115:        printf("This program should only be ran by root or be installed as setuid root.\n");
        !           116:        exit(1);
        !           117:     }
        !           118: 
        !           119:     doargs(argc,argv);
        !           120: 
        !           121:     if (VERBOSE) puts("setup");
        !           122:     dhcp_setup(server);
        !           123: 
        !           124:     if (setuid(getuid())!=0) {
        !           125:        perror("setuid");
        !           126:        printf("Can't drop privileges back to normal user, program aborted.\n");
        !           127:        exit(1);
        !           128:     }
        !           129: 
        !           130:     if (inform) {
        !           131:        if (VERBOSE) puts("inform");
        !           132:        dhcp_inform(ci,gi,hw);
        !           133:     }
        !           134:     if (request) {
        !           135:        if (VERBOSE) puts("request");
        !           136:        dhcp_request(ci,gi,hw);
        !           137:     }
        !           138: 
        !           139:     while (!foundpacket) {
        !           140:        FD_ZERO(&read);
        !           141:        FD_SET(dhcp_socket,&read);
        !           142:        timeout.tv_sec=maxwait;
        !           143:        timeout.tv_usec=0;
        !           144:        if(select(dhcp_socket+1,&read,NULL,NULL,&timeout)<0) {
        !           145:            perror("select");
        !           146:            exit(0);
        !           147:        }
        !           148:        if (FD_ISSET(dhcp_socket,&read)) {
        !           149:            if (VERBOSE) puts("read");
        !           150:            /* If a expected packet was found, then also release it. */
        !           151:            if ((foundpacket=dhcp_read())!=0) {
        !           152:                if (request) {
        !           153:                    if (VERBOSE) puts("release");
        !           154:                    dhcp_release(ci,gi,hw);
        !           155:                }
        !           156:            }
        !           157:        } else {
        !           158:            if (!quiet)
        !           159:                fprintf(stderr,"no answer\n");
        !           160:            returnvalue=1;
        !           161:            foundpacket=1;
        !           162:        }
        !           163:     }
        !           164:     if (VERBOSE) puts("close");
        !           165:     dhcp_close();
        !           166:     return returnvalue;
        !           167: }
        !           168: 
        !           169: 
        !           170: void dhcp_setup(char *serveripaddress) {
        !           171:     struct servent *servent,*clientent;
        !           172:     struct hostent *hostent;
        !           173:     int flag;
        !           174:     struct sockaddr_in name;
        !           175: 
        !           176:     /*
        !           177:     // setup sending socket
        !           178:     */
        !           179:     if ((servent=getservbyname("bootps",0))==NULL) {
        !           180:        perror("getservbyname: bootps");
        !           181:        exit(1);
        !           182:     }
        !           183:     if ((hostent=gethostbyname(serveripaddress))==NULL) {
        !           184:        perror("gethostbyname");
        !           185:        exit(1);
        !           186:     }
        !           187: 
        !           188:     dhcp_to.sin_family=AF_INET;
        !           189:     bcopy(hostent->h_addr,&dhcp_to.sin_addr.s_addr,hostent->h_length);
        !           190:     _serveripaddress=ntohl(dhcp_to.sin_addr.s_addr);
        !           191: /*  dhcp_to.sin_addr.s_addr=INADDR_BROADCAST; */
        !           192:     dhcp_to.sin_port=servent->s_port;
        !           193: 
        !           194:     if ((dhcp_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1) {
        !           195:        perror("dhcp_socket/socket");
        !           196:        exit(1);
        !           197:     }
        !           198: 
        !           199:     flag=1;
        !           200:     if (setsockopt (dhcp_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof flag) < 0) {
        !           201:        perror("dhcp_socket/setsockopt: SO_REUSEADDR");
        !           202:        exit(1);
        !           203:     }
        !           204: 
        !           205:     if (setsockopt(dhcp_socket,SOL_SOCKET,SO_BROADCAST,(char *)&flag, sizeof flag) < 0) {
        !           206:        perror ("dhcp_socket/setsockopt: SO_BROADCAST");
        !           207:        exit(1);
        !           208:     }
        !           209: 
        !           210:     if ((clientent=getservbyname("bootpc",0))==NULL) {
        !           211:        perror("getservbyname: bootpc");
        !           212:        exit(1);
        !           213:     }
        !           214:     name.sin_family = AF_INET;
        !           215:     name.sin_port = clientent->s_port;
        !           216:     name.sin_addr.s_addr = INADDR_ANY;
        !           217: /*  name.sin_addr.s_addr = INADDR_NONE; */
        !           218:     memset (name.sin_zero, 0, sizeof (name.sin_zero));
        !           219: 
        !           220:     if (bind (dhcp_socket, (struct sockaddr *)&name, sizeof name) < 0) {
        !           221:        perror("bind");
        !           222:        exit(1);
        !           223:     }
        !           224: }
        !           225: 
        !           226: void dhcp_request(char *ipaddr,char *gwaddr,char *hardware) {
        !           227:     dhcp_packet(3,ipaddr,ipaddr,gwaddr,hardware);
        !           228: }
        !           229: void dhcp_release(char *ipaddr,char *gwaddr,char *hardware) {
        !           230:     dhcp_packet(7,ipaddr,NULL,gwaddr,hardware);
        !           231: }
        !           232: void dhcp_inform(char *ipaddr,char *gwaddr,char *hardware) {
        !           233:     dhcp_packet(8,ipaddr,NULL,gwaddr,hardware);
        !           234: }
        !           235: 
        !           236: 
        !           237: void dhcp_packet(int type,char *ipaddr,char *opt50,char *gwaddr,char *hardware) {
        !           238:     static time_t l=0;
        !           239:     unsigned char msgbuf[BUF_SIZ];
        !           240:     unsigned char pktbuf[BUF_SIZ];
        !           241:     int ip[4],gw[4],hw[16],ip50[4];
        !           242:     int hwcount;
        !           243: 
        !           244:     sscanf(ipaddr,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3]);
        !           245:     sscanf(gwaddr,"%d.%d.%d.%d",&gw[0],&gw[1],&gw[2],&gw[3]);
        !           246:     if (opt50)
        !           247:        sscanf(opt50,"%d.%d.%d.%d",&ip50[0],&ip50[1],&ip50[2],&ip50[3]);
        !           248:     memset(&hw,0,sizeof(hw));
        !           249:     hwcount=sscanf(hardware,"%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x",
        !           250:        &hw[0],&hw[1],&hw[2],&hw[3],
        !           251:        &hw[4],&hw[5],&hw[6],&hw[7],
        !           252:        &hw[8],&hw[9],&hw[10],&hw[11],
        !           253:        &hw[12],&hw[13],&hw[14],&hw[15]);
        !           254: 
        !           255:     memset(msgbuf,0,sizeof(msgbuf));
        !           256:     sprintf(msgbuf,"\1\1%c%c",hwcount,0);
        !           257:     addpacket(pktbuf,msgbuf,4);
        !           258: 
        !           259:     /* xid */
        !           260:     if (l>time(NULL))
        !           261:        l++;
        !           262:     else
        !           263:        l=time(NULL);
        !           264:     memcpy(msgbuf,&l,4);
        !           265:     addpacket(pktbuf,msgbuf,4);
        !           266: 
        !           267:     /* secs and flags */
        !           268:     memset(msgbuf,0,4);
        !           269:     addpacket(pktbuf,msgbuf,4);
        !           270: /*  sprintf(msgbuf,"%c%c",0x80,0x00); */
        !           271: /*  sprintf(msgbuf,"%c%c",0x00,0x00); */
        !           272: /*  addpacket(pktbuf,msgbuf,2); */
        !           273: 
        !           274:     /* ciaddr */
        !           275:     memset(msgbuf,0,4);
        !           276:     sprintf(msgbuf,"%c%c%c%c",ip[0],ip[1],ip[2],ip[3]);
        !           277:     addpacket(pktbuf,msgbuf,4);
        !           278: 
        !           279:     /* yiaddr */
        !           280:     memset(msgbuf,0,4);
        !           281:     addpacket(pktbuf,msgbuf,4);
        !           282: 
        !           283:     /* siaddr */
        !           284:     memset(msgbuf,0,4);
        !           285:     addpacket(pktbuf,msgbuf,4);
        !           286: 
        !           287:     /* giaddr */
        !           288:     sprintf(msgbuf,"%c%c%c%c",gw[0],gw[1],gw[2],gw[3]);
        !           289:     addpacket(pktbuf,msgbuf,4);
        !           290: 
        !           291:     /* chaddr */
        !           292:     sprintf(msgbuf,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
        !           293:        hw[0],hw[1],hw[2],hw[3],hw[4],hw[5],hw[6],hw[7],
        !           294:        hw[8],hw[9],hw[10],hw[11],hw[12],hw[13],hw[14],hw[15]);
        !           295:     addpacket(pktbuf,msgbuf,16);
        !           296: 
        !           297:     /* sname */
        !           298:     memset(msgbuf,0,64);
        !           299:     addpacket(pktbuf,msgbuf,64);
        !           300: 
        !           301:     /* file */
        !           302:     memset(msgbuf,0,128);
        !           303:     addpacket(pktbuf,msgbuf,128);
        !           304: 
        !           305:     /* options */
        !           306:     {
        !           307:        /* cookie */
        !           308:        sprintf(msgbuf,"%c%c%c%c",99,130,83,99);
        !           309:        addpacket(pktbuf,msgbuf,4);
        !           310: 
        !           311:        /* dhcp-type */
        !           312:        sprintf(msgbuf,"%c%c%c",53,1,type);
        !           313:        addpacket(pktbuf,msgbuf,3);
        !           314: 
        !           315:        /* Not for inform */
        !           316:        if (type!=8) {
        !           317:            /* requested IP address */
        !           318:            if (opt50) {
        !           319:                sprintf(msgbuf,"%c%c%c%c%c%c",50,4,ip50[0],ip50[1],ip50[2],ip50[3]);
        !           320:                addpacket(pktbuf,msgbuf,6);
        !           321:            }
        !           322: 
        !           323:            /* server-identifier */
        !           324:            if (serveridentifier[0]) {
        !           325:                sprintf(msgbuf,"%c%c%c%c%c%c",54,4,
        !           326:                    serveridentifier[0],serveridentifier[1],
        !           327:                    serveridentifier[2],serveridentifier[3]);
        !           328:                addpacket(pktbuf,msgbuf,6);
        !           329:            }
        !           330:        }
        !           331: 
        !           332:        /* client-identifier */
        !           333: //     sprintf(msgbuf,"%c%c%c%c%c%c%c%c",61,6,
        !           334: //             hw[0],hw[1],hw[2],hw[3],hw[4],hw[5]);
        !           335: //     addpacket(pktbuf,msgbuf,8);
        !           336: 
        !           337:        /* parameter request list */
        !           338:        if (type==8) {
        !           339:            sprintf(msgbuf,"%c%c%c",55,1,1);
        !           340:            addpacket(pktbuf,msgbuf,3);
        !           341:        }
        !           342: 
        !           343:        /* end of options */
        !           344:        sprintf(msgbuf,"%c",255);
        !           345:        addpacket(pktbuf,msgbuf,1);
        !           346:     }
        !           347: 
        !           348:     dhcp_dump(pktbuf,offset);
        !           349: 
        !           350:     sendto(dhcp_socket,pktbuf,offset,0,(struct sockaddr *)&dhcp_to,sizeof(dhcp_to));
        !           351: 
        !           352:     offset=0;
        !           353: }
        !           354: 
        !           355: 
        !           356: int dhcp_read(void) {
        !           357:     unsigned char msgbuf[BUF_SIZ];
        !           358:     struct sockaddr_in fromsock;
        !           359:     socklen_t fromlen=sizeof(fromsock);
        !           360:     int addr;
        !           361:     int i;
        !           362: 
        !           363:     i=recvfrom(dhcp_socket,msgbuf,BUF_SIZ,0,(struct sockaddr *)&fromsock,&fromlen);
        !           364:     addr=ntohl(fromsock.sin_addr.s_addr);
        !           365: 
        !           366:     if (!quiet) {
        !           367:        printf( "Got answer from: %d.%d.%d.%d\n",
        !           368:            ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
        !           369:            ( addr >>  8 ) & 0xFF, ( addr       ) & 0xFF
        !           370:            );
        !           371:     }
        !           372: 
        !           373:     if (_serveripaddress!=addr) {
        !           374:        if (!quiet)
        !           375:            fprintf(stderr,"received from %d.%d.%d.%d, expected from %d.%d.%d.%d\n",
        !           376:                ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
        !           377:                ( addr >>  8 ) & 0xFF, ( addr       ) & 0xFF,
        !           378:                ( _serveripaddress >> 24 )&0xFF,(_serveripaddress >> 16 )&0xFF,
        !           379:                ( _serveripaddress >>  8 )&0xFF,(_serveripaddress       )&0xFF
        !           380:            );
        !           381:        return 0;
        !           382: 
        !           383:     }
        !           384: 
        !           385: 
        !           386:     dhcp_dump(msgbuf,i);
        !           387:     return 1;
        !           388: }
        !           389: 
        !           390: 
        !           391: 
        !           392: void dhcp_dump(unsigned char *buffer,int size) {
        !           393:     int j;
        !           394: 
        !           395:     if (VERBOSE)
        !           396:        printf("packet %d bytes\n",size);
        !           397: 
        !           398:     if (!VERBOSE)
        !           399:        return;
        !           400: 
        !           401:     //
        !           402:     // Are you sure you want to see this? Try dhcpdump, which is better
        !           403:     // suited for this kind of work... See http://www.mavetju.org
        !           404:     //
        !           405:     j=0;
        !           406:     while (j<size) {
        !           407:        printf("%02x ",buffer[j]);
        !           408:        if (j%16==15) printf("\n");
        !           409:        j++;
        !           410:     }
        !           411:     printf("\n");
        !           412: 
        !           413:     printf("op: %d\n",buffer[0]);
        !           414:     printf("htype: %d\n",buffer[1]);
        !           415:     printf("hlen: %d\n",buffer[2]);
        !           416:        printf("hops: %d\n",buffer[3]);
        !           417: 
        !           418:     printf("xid: %02x%02x%02x%02x\n",
        !           419:            buffer[4],buffer[5],buffer[6],buffer[7]);
        !           420:     printf("secs: %d\n",255*buffer[8]+buffer[9]);
        !           421:     printf("flags: %x\n",255*buffer[10]+buffer[11]);
        !           422: 
        !           423:     printf("ciaddr: %d.%d.%d.%d\n",
        !           424:            buffer[12],buffer[13],buffer[14],buffer[15]);
        !           425:     printf("yiaddr: %d.%d.%d.%d\n",
        !           426:            buffer[16],buffer[17],buffer[18],buffer[19]);
        !           427:     printf("siaddr: %d.%d.%d.%d\n",
        !           428:            buffer[20],buffer[21],buffer[22],buffer[23]);
        !           429:     printf("giaddr: %d.%d.%d.%d\n",
        !           430:            buffer[24],buffer[25],buffer[26],buffer[27]);
        !           431:     printf("chaddr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
        !           432:            buffer[28],buffer[29],buffer[30],buffer[31],
        !           433:            buffer[32],buffer[33],buffer[34],buffer[35],
        !           434:            buffer[36],buffer[37],buffer[38],buffer[39],
        !           435:            buffer[40],buffer[41],buffer[42],buffer[43]);
        !           436:     printf("sname : %s.\n",buffer+44);
        !           437:     printf("fname : %s.\n",buffer+108);
        !           438: 
        !           439:     j=236;
        !           440:     j+=4;      /* cookie */
        !           441:     while (j<size && buffer[j]!=255) {
        !           442:        printf("option %d %s\n",buffer[j],dhcp_options[buffer[j]]);
        !           443: 
        !           444:        switch (buffer[j]) {
        !           445:        case 1:
        !           446:            printf("\tSubnet mask: %d.%d.%d.%d\n",
        !           447:                buffer[j+2],buffer[j+3],buffer[j+4],buffer[j+5]);
        !           448:            break;
        !           449:        case 3:
        !           450:            printf("\tRouter: %d.%d.%d.%d\n",
        !           451:                buffer[j+2],buffer[j+3],buffer[j+4],buffer[j+5]);
        !           452:            break;
        !           453:        case 50:
        !           454:            printf("\tRequested IP address: %d.%d.%d.%d\n",
        !           455:                buffer[j+2],buffer[j+3],buffer[j+4],buffer[j+5]);
        !           456:            break;
        !           457:        case 53:
        !           458:            printf("\tDHCP message type: %d (%s)\n",
        !           459:                buffer[j+2],dhcp_message_types[buffer[j+2]]);
        !           460:            break;
        !           461:        case 54:
        !           462:            memcpy(serveridentifier,buffer+j+2,4);
        !           463:            printf("\tServer identifier: %d.%d.%d.%d\n",
        !           464:                serveridentifier[0],serveridentifier[1],
        !           465:                serveridentifier[2],serveridentifier[3]);
        !           466:            break;
        !           467:        case 61:
        !           468:            printf("\tClient identifier: %02x%02x%02x%02x%02x%02x\n",
        !           469:                buffer[j+2],buffer[j+3],buffer[j+4],
        !           470:                buffer[j+5],buffer[j+6],buffer[j+7]);
        !           471:            break;
        !           472:        }
        !           473: 
        !           474:        /*
        !           475:        // This might go wrong if a mallformed packet is received.
        !           476:        // Maybe from a bogus server which is instructed to reply
        !           477:        // with invalid data and thus causing an exploit.
        !           478:        // My head hurts... but I think it's solved by the checking
        !           479:        // for j<size at the begin of the while-loop.
        !           480:        */
        !           481:        j+=buffer[j+1]+2;
        !           482:     }
        !           483: }
        !           484: 
        !           485: 
        !           486: void dhcp_close(void) {
        !           487:     close(dhcp_socket);
        !           488: }
        !           489: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>