ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

options.c
Go to the documentation of this file.
00001 /*  $OpenBSD: options.c,v 1.15 2004/12/26 03:17:07 deraadt Exp $    */
00002 
00003 /* DHCP options parsing and reassembly. */
00004 
00005 /*
00006  * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  *
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. Neither the name of The Internet Software Consortium nor the names
00019  *    of its contributors may be used to endorse or promote products derived
00020  *    from this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
00023  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
00024  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00025  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
00027  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00030  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00033  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00034  * SUCH DAMAGE.
00035  *
00036  * This software has been written for the Internet Software Consortium
00037  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
00038  * Enterprises.  To learn more about the Internet Software Consortium,
00039  * see ``http://www.vix.com/isc''.  To learn more about Vixie
00040  * Enterprises, see ``http://www.vix.com''.
00041  */
00042 
00043 #define DHCP_OPTION_DATA
00044 #include "rosdhcp.h"
00045 
00046 int bad_options = 0;
00047 int bad_options_max = 5;
00048 
00049 void    parse_options(struct packet *);
00050 void    parse_option_buffer(struct packet *, unsigned char *, int);
00051 int store_options(unsigned char *, int, struct tree_cache **,
00052         unsigned char *, int, int, int, int);
00053 
00054 
00055 /*
00056  * Parse all available options out of the specified packet.
00057  */
00058 void
00059 parse_options(struct packet *packet)
00060 {
00061     /* Initially, zero all option pointers. */
00062     memset(packet->options, 0, sizeof(packet->options));
00063 
00064     /* If we don't see the magic cookie, there's nothing to parse. */
00065     if (memcmp(packet->raw->options, DHCP_OPTIONS_COOKIE, 4)) {
00066         packet->options_valid = 0;
00067         return;
00068     }
00069 
00070     /*
00071      * Go through the options field, up to the end of the packet or
00072      * the End field.
00073      */
00074     parse_option_buffer(packet, &packet->raw->options[4],
00075         packet->packet_length - DHCP_FIXED_NON_UDP - 4);
00076 
00077     /*
00078      * If we parsed a DHCP Option Overload option, parse more
00079      * options out of the buffer(s) containing them.
00080      */
00081     if (packet->options_valid &&
00082         packet->options[DHO_DHCP_OPTION_OVERLOAD].data) {
00083         if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)
00084             parse_option_buffer(packet,
00085                 (unsigned char *)packet->raw->file,
00086                 sizeof(packet->raw->file));
00087         if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)
00088             parse_option_buffer(packet,
00089                 (unsigned char *)packet->raw->sname,
00090                 sizeof(packet->raw->sname));
00091     }
00092 }
00093 
00094 /*
00095  * Parse options out of the specified buffer, storing addresses of
00096  * option values in packet->options and setting packet->options_valid if
00097  * no errors are encountered.
00098  */
00099 void
00100 parse_option_buffer(struct packet *packet,
00101     unsigned char *buffer, int length)
00102 {
00103     unsigned char *s, *t, *end = buffer + length;
00104     int len, code;
00105 
00106     for (s = buffer; *s != DHO_END && s < end; ) {
00107         code = s[0];
00108 
00109         /* Pad options don't have a length - just skip them. */
00110         if (code == DHO_PAD) {
00111             s++;
00112             continue;
00113         }
00114         if (s + 2 > end) {
00115             len = 65536;
00116             goto bogus;
00117         }
00118 
00119         /*
00120          * All other fields (except end, see above) have a
00121          * one-byte length.
00122          */
00123         len = s[1];
00124 
00125         /*
00126          * If the length is outrageous, silently skip the rest,
00127          * and mark the packet bad. Unfortunately some crappy
00128          * dhcp servers always seem to give us garbage on the
00129          * end of a packet. so rather than keep refusing, give
00130          * up and try to take one after seeing a few without
00131          * anything good.
00132          */
00133         if (s + len + 2 > end) {
00134             bogus:
00135             bad_options++;
00136             warning("option %s (%d) %s.",
00137                 dhcp_options[code].name, len,
00138                 "larger than buffer");
00139             if (bad_options == bad_options_max) {
00140                 packet->options_valid = 1;
00141                 bad_options = 0;
00142                 warning("Many bogus options seen in offers. "
00143                     "Taking this offer in spite of bogus "
00144                     "options - hope for the best!");
00145             } else {
00146                 warning("rejecting bogus offer.");
00147                 packet->options_valid = 0;
00148             }
00149             return;
00150         }
00151         /*
00152          * If we haven't seen this option before, just make
00153          * space for it and copy it there.
00154          */
00155         if (!packet->options[code].data) {
00156             if (!(t = calloc(1, len + 1)))
00157                 error("Can't allocate storage for option %s.",
00158                     dhcp_options[code].name);
00159             /*
00160              * Copy and NUL-terminate the option (in case
00161              * it's an ASCII string.
00162              */
00163             memcpy(t, &s[2], len);
00164             t[len] = 0;
00165             packet->options[code].len = len;
00166             packet->options[code].data = t;
00167         } else {
00168             /*
00169              * If it's a repeat, concatenate it to whatever
00170              * we last saw.   This is really only required
00171              * for clients, but what the heck...
00172              */
00173             t = calloc(1, len + packet->options[code].len + 1);
00174             if (!t) {
00175                 error("Can't expand storage for option %s.",
00176                     dhcp_options[code].name);
00177                                 return;
00178                         }
00179             memcpy(t, packet->options[code].data,
00180                 packet->options[code].len);
00181             memcpy(t + packet->options[code].len,
00182                 &s[2], len);
00183             packet->options[code].len += len;
00184             t[packet->options[code].len] = 0;
00185             free(packet->options[code].data);
00186             packet->options[code].data = t;
00187         }
00188         s += len + 2;
00189     }
00190     packet->options_valid = 1;
00191 }
00192 
00193 /*
00194  * cons options into a big buffer, and then split them out into the
00195  * three separate buffers if needed.  This allows us to cons up a set of
00196  * vendor options using the same routine.
00197  */
00198 int
00199 cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
00200     int mms, struct tree_cache **options,
00201     int overload, /* Overload flags that may be set. */
00202     int terminate, int bootpp, u_int8_t *prl, int prl_len)
00203 {
00204     unsigned char priority_list[300], buffer[4096];
00205     int priority_len, main_buffer_size, mainbufix, bufix;
00206     int option_size, length;
00207 
00208     /*
00209      * If the client has provided a maximum DHCP message size, use
00210      * that; otherwise, if it's BOOTP, only 64 bytes; otherwise use
00211      * up to the minimum IP MTU size (576 bytes).
00212      *
00213      * XXX if a BOOTP client specifies a max message size, we will
00214      * honor it.
00215      */
00216     if (!mms &&
00217         inpacket &&
00218         inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data &&
00219         (inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].len >=
00220         sizeof(u_int16_t)))
00221         mms = getUShort(
00222             inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data);
00223 
00224     if (mms)
00225         main_buffer_size = mms - DHCP_FIXED_LEN;
00226     else if (bootpp)
00227         main_buffer_size = 64;
00228     else
00229         main_buffer_size = 576 - DHCP_FIXED_LEN;
00230 
00231     if (main_buffer_size > sizeof(buffer))
00232         main_buffer_size = sizeof(buffer);
00233 
00234     /* Preload the option priority list with mandatory options. */
00235     priority_len = 0;
00236     priority_list[priority_len++] = DHO_DHCP_MESSAGE_TYPE;
00237     priority_list[priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
00238     priority_list[priority_len++] = DHO_DHCP_LEASE_TIME;
00239     priority_list[priority_len++] = DHO_DHCP_MESSAGE;
00240 
00241     /*
00242      * If the client has provided a list of options that it wishes
00243      * returned, use it to prioritize.  Otherwise, prioritize based
00244      * on the default priority list.
00245      */
00246     if (inpacket &&
00247         inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
00248         int prlen =
00249             inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].len;
00250         if (prlen + priority_len > sizeof(priority_list))
00251             prlen = sizeof(priority_list) - priority_len;
00252 
00253         memcpy(&priority_list[priority_len],
00254             inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data,
00255             prlen);
00256         priority_len += prlen;
00257         prl = priority_list;
00258     } else if (prl) {
00259         if (prl_len + priority_len > sizeof(priority_list))
00260             prl_len = sizeof(priority_list) - priority_len;
00261 
00262         memcpy(&priority_list[priority_len], prl, prl_len);
00263         priority_len += prl_len;
00264         prl = priority_list;
00265     } else {
00266         memcpy(&priority_list[priority_len],
00267             dhcp_option_default_priority_list,
00268             sizeof_dhcp_option_default_priority_list);
00269         priority_len += sizeof_dhcp_option_default_priority_list;
00270     }
00271 
00272     /* Copy the options into the big buffer... */
00273     option_size = store_options(
00274         buffer,
00275         (main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0) +
00276         ((overload & 2) ? DHCP_SNAME_LEN : 0)),
00277         options, priority_list, priority_len, main_buffer_size,
00278         (main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)),
00279         terminate);
00280 
00281     /* Put the cookie up front... */
00282     memcpy(outpacket->options, DHCP_OPTIONS_COOKIE, 4);
00283     mainbufix = 4;
00284 
00285     /*
00286      * If we're going to have to overload, store the overload option
00287      * at the beginning.  If we can, though, just store the whole
00288      * thing in the packet's option buffer and leave it at that.
00289      */
00290     if (option_size <= main_buffer_size - mainbufix) {
00291         memcpy(&outpacket->options[mainbufix],
00292             buffer, option_size);
00293         mainbufix += option_size;
00294         if (mainbufix < main_buffer_size)
00295             outpacket->options[mainbufix++] = DHO_END;
00296         length = DHCP_FIXED_NON_UDP + mainbufix;
00297     } else {
00298         outpacket->options[mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
00299         outpacket->options[mainbufix++] = 1;
00300         if (option_size >
00301             main_buffer_size - mainbufix + DHCP_FILE_LEN)
00302             outpacket->options[mainbufix++] = 3;
00303         else
00304             outpacket->options[mainbufix++] = 1;
00305 
00306         memcpy(&outpacket->options[mainbufix],
00307             buffer, main_buffer_size - mainbufix);
00308         bufix = main_buffer_size - mainbufix;
00309         length = DHCP_FIXED_NON_UDP + mainbufix;
00310         if (overload & 1) {
00311             if (option_size - bufix <= DHCP_FILE_LEN) {
00312                 memcpy(outpacket->file,
00313                     &buffer[bufix], option_size - bufix);
00314                 mainbufix = option_size - bufix;
00315                 if (mainbufix < DHCP_FILE_LEN)
00316                     outpacket->file[mainbufix++] = (char)DHO_END;
00317                 while (mainbufix < DHCP_FILE_LEN)
00318                     outpacket->file[mainbufix++] = (char)DHO_PAD;
00319             } else {
00320                 memcpy(outpacket->file,
00321                     &buffer[bufix], DHCP_FILE_LEN);
00322                 bufix += DHCP_FILE_LEN;
00323             }
00324         }
00325         if ((overload & 2) && option_size < bufix) {
00326             memcpy(outpacket->sname,
00327                 &buffer[bufix], option_size - bufix);
00328 
00329             mainbufix = option_size - bufix;
00330             if (mainbufix < DHCP_SNAME_LEN)
00331                 outpacket->file[mainbufix++] = (char)DHO_END;
00332             while (mainbufix < DHCP_SNAME_LEN)
00333                 outpacket->file[mainbufix++] = (char)DHO_PAD;
00334         }
00335     }
00336     return (length);
00337 }
00338 
00339 /*
00340  * Store all the requested options into the requested buffer.
00341  */
00342 int
00343 store_options(unsigned char *buffer, int buflen, struct tree_cache **options,
00344     unsigned char *priority_list, int priority_len, int first_cutoff,
00345     int second_cutoff, int terminate)
00346 {
00347     int bufix = 0, option_stored[256], i, ix, tto;
00348 
00349     /* Zero out the stored-lengths array. */
00350     memset(option_stored, 0, sizeof(option_stored));
00351 
00352     /*
00353      * Copy out the options in the order that they appear in the
00354      * priority list...
00355      */
00356     for (i = 0; i < priority_len; i++) {
00357         /* Code for next option to try to store. */
00358         int code = priority_list[i];
00359         int optstart;
00360 
00361         /*
00362          * Number of bytes left to store (some may already have
00363          * been stored by a previous pass).
00364          */
00365         int length;
00366 
00367         /* If no data is available for this option, skip it. */
00368         if (!options[code]) {
00369             continue;
00370         }
00371 
00372         /*
00373          * The client could ask for things that are mandatory,
00374          * in which case we should avoid storing them twice...
00375          */
00376         if (option_stored[code])
00377             continue;
00378         option_stored[code] = 1;
00379 
00380         /* We should now have a constant length for the option. */
00381         length = options[code]->len;
00382 
00383         /* Do we add a NUL? */
00384         if (terminate && dhcp_options[code].format[0] == 't') {
00385             length++;
00386             tto = 1;
00387         } else
00388             tto = 0;
00389 
00390         /* Try to store the option. */
00391 
00392         /*
00393          * If the option's length is more than 255, we must
00394          * store it in multiple hunks.   Store 255-byte hunks
00395          * first.  However, in any case, if the option data will
00396          * cross a buffer boundary, split it across that
00397          * boundary.
00398          */
00399         ix = 0;
00400 
00401         optstart = bufix;
00402         while (length) {
00403             unsigned char incr = length > 255 ? 255 : length;
00404 
00405             /*
00406              * If this hunk of the buffer will cross a
00407              * boundary, only go up to the boundary in this
00408              * pass.
00409              */
00410             if (bufix < first_cutoff &&
00411                 bufix + incr > first_cutoff)
00412                 incr = first_cutoff - bufix;
00413             else if (bufix < second_cutoff &&
00414                 bufix + incr > second_cutoff)
00415                 incr = second_cutoff - bufix;
00416 
00417             /*
00418              * If this option is going to overflow the
00419              * buffer, skip it.
00420              */
00421             if (bufix + 2 + incr > buflen) {
00422                 bufix = optstart;
00423                 break;
00424             }
00425 
00426             /* Everything looks good - copy it in! */
00427             buffer[bufix] = code;
00428             buffer[bufix + 1] = incr;
00429             if (tto && incr == length) {
00430                 memcpy(buffer + bufix + 2,
00431                     options[code]->value + ix, incr - 1);
00432                 buffer[bufix + 2 + incr - 1] = 0;
00433             } else
00434                 memcpy(buffer + bufix + 2,
00435                     options[code]->value + ix, incr);
00436             length -= incr;
00437             ix += incr;
00438             bufix += 2 + incr;
00439         }
00440     }
00441     return (bufix);
00442 }
00443 
00444 /*
00445  * Format the specified option so that a human can easily read it.
00446  */
00447 char *
00448 pretty_print_option(unsigned int code, unsigned char *data, int len,
00449     int emit_commas, int emit_quotes)
00450 {
00451     static char optbuf[32768]; /* XXX */
00452     int hunksize = 0, numhunk = -1, numelem = 0;
00453     char fmtbuf[32], *op = optbuf;
00454     int i, j, k, opleft = sizeof(optbuf);
00455     unsigned char *dp = data;
00456     struct in_addr foo;
00457     char comma;
00458 
00459     /* Code should be between 0 and 255. */
00460     if (code > 255)
00461         error("pretty_print_option: bad code %d", code);
00462 
00463     if (emit_commas)
00464         comma = ',';
00465     else
00466         comma = ' ';
00467 
00468     /* Figure out the size of the data. */
00469     for (i = 0; dhcp_options[code].format[i]; i++) {
00470         if (!numhunk) {
00471             warning("%s: Excess information in format string: %s",
00472                 dhcp_options[code].name,
00473                 &(dhcp_options[code].format[i]));
00474             break;
00475         }
00476         numelem++;
00477         fmtbuf[i] = dhcp_options[code].format[i];
00478         switch (dhcp_options[code].format[i]) {
00479         case 'A':
00480             --numelem;
00481             fmtbuf[i] = 0;
00482             numhunk = 0;
00483             break;
00484         case 'X':
00485             for (k = 0; k < len; k++)
00486                 if (!isascii(data[k]) ||
00487                     !isprint(data[k]))
00488                     break;
00489             if (k == len) {
00490                 fmtbuf[i] = 't';
00491                 numhunk = -2;
00492             } else {
00493                 fmtbuf[i] = 'x';
00494                 hunksize++;
00495                 comma = ':';
00496                 numhunk = 0;
00497             }
00498             fmtbuf[i + 1] = 0;
00499             break;
00500         case 't':
00501             fmtbuf[i] = 't';
00502             fmtbuf[i + 1] = 0;
00503             numhunk = -2;
00504             break;
00505         case 'I':
00506         case 'l':
00507         case 'L':
00508             hunksize += 4;
00509             break;
00510         case 's':
00511         case 'S':
00512             hunksize += 2;
00513             break;
00514         case 'b':
00515         case 'B':
00516         case 'f':
00517             hunksize++;
00518             break;
00519         case 'e':
00520             break;
00521         default:
00522             warning("%s: garbage in format string: %s",
00523                 dhcp_options[code].name,
00524                 &(dhcp_options[code].format[i]));
00525             break;
00526         }
00527     }
00528 
00529     /* Check for too few bytes... */
00530     if (hunksize > len) {
00531         warning("%s: expecting at least %d bytes; got %d",
00532             dhcp_options[code].name, hunksize, len);
00533         return ("<error>");
00534     }
00535     /* Check for too many bytes... */
00536     if (numhunk == -1 && hunksize < len)
00537         warning("%s: %d extra bytes",
00538             dhcp_options[code].name, len - hunksize);
00539 
00540     /* If this is an array, compute its size. */
00541     if (!numhunk)
00542         numhunk = len / hunksize;
00543     /* See if we got an exact number of hunks. */
00544     if (numhunk > 0 && numhunk * hunksize < len)
00545         warning("%s: %d extra bytes at end of array",
00546             dhcp_options[code].name, len - numhunk * hunksize);
00547 
00548     /* A one-hunk array prints the same as a single hunk. */
00549     if (numhunk < 0)
00550         numhunk = 1;
00551 
00552     /* Cycle through the array (or hunk) printing the data. */
00553     for (i = 0; i < numhunk; i++) {
00554         for (j = 0; j < numelem; j++) {
00555             int opcount;
00556             switch (fmtbuf[j]) {
00557             case 't':
00558                 if (emit_quotes) {
00559                     *op++ = '"';
00560                     opleft--;
00561                 }
00562                 for (; dp < data + len; dp++) {
00563                     if (!isascii(*dp) ||
00564                         !isprint(*dp)) {
00565                         if (dp + 1 != data + len ||
00566                             *dp != 0) {
00567                             _snprintf(op, opleft,
00568                                 "\\%03o", *dp);
00569                             op += 4;
00570                             opleft -= 4;
00571                         }
00572                     } else if (*dp == '"' ||
00573                         *dp == '\'' ||
00574                         *dp == '$' ||
00575                         *dp == '`' ||
00576                         *dp == '\\') {
00577                         *op++ = '\\';
00578                         *op++ = *dp;
00579                         opleft -= 2;
00580                     } else {
00581                         *op++ = *dp;
00582                         opleft--;
00583                     }
00584                 }
00585                 if (emit_quotes) {
00586                     *op++ = '"';
00587                     opleft--;
00588                 }
00589 
00590                 *op = 0;
00591                 break;
00592             case 'I':
00593                 foo.s_addr = htonl(getULong(dp));
00594                 strncpy(op, inet_ntoa(foo), opleft - 1);
00595                 op[opleft - 1] = ANSI_NULL;
00596                 opcount = strlen(op);
00597                 if (opcount >= opleft)
00598                     goto toobig;
00599                 opleft -= opcount;
00600                 dp += 4;
00601                 break;
00602             case 'l':
00603                 opcount = _snprintf(op, opleft, "%ld",
00604                     (long)getLong(dp));
00605                 if (opcount >= opleft || opcount == -1)
00606                     goto toobig;
00607                 opleft -= opcount;
00608                 dp += 4;
00609                 break;
00610             case 'L':
00611                 opcount = _snprintf(op, opleft, "%ld",
00612                     (unsigned long)getULong(dp));
00613                 if (opcount >= opleft || opcount == -1)
00614                     goto toobig;
00615                 opleft -= opcount;
00616                 dp += 4;
00617                 break;
00618             case 's':
00619                 opcount = _snprintf(op, opleft, "%d",
00620                     getShort(dp));
00621                 if (opcount >= opleft || opcount == -1)
00622                     goto toobig;
00623                 opleft -= opcount;
00624                 dp += 2;
00625                 break;
00626             case 'S':
00627                 opcount = _snprintf(op, opleft, "%d",
00628                     getUShort(dp));
00629                 if (opcount >= opleft || opcount == -1)
00630                     goto toobig;
00631                 opleft -= opcount;
00632                 dp += 2;
00633                 break;
00634             case 'b':
00635                 opcount = _snprintf(op, opleft, "%d",
00636                     *(char *)dp++);
00637                 if (opcount >= opleft || opcount == -1)
00638                     goto toobig;
00639                 opleft -= opcount;
00640                 break;
00641             case 'B':
00642                 opcount = _snprintf(op, opleft, "%d", *dp++);
00643                 if (opcount >= opleft || opcount == -1)
00644                     goto toobig;
00645                 opleft -= opcount;
00646                 break;
00647             case 'x':
00648                 opcount = _snprintf(op, opleft, "%x", *dp++);
00649                 if (opcount >= opleft || opcount == -1)
00650                     goto toobig;
00651                 opleft -= opcount;
00652                 break;
00653             case 'f':
00654                 opcount = (size_t) strncpy(op, *dp++ ? "true" : "false", opleft - 1);
00655                 op[opleft - 1] = ANSI_NULL;
00656                 if (opcount >= opleft)
00657                     goto toobig;
00658                 opleft -= opcount;
00659                 break;
00660             default:
00661                 warning("Unexpected format code %c", fmtbuf[j]);
00662             }
00663             op += strlen(op);
00664             opleft -= strlen(op);
00665             if (opleft < 1)
00666                 goto toobig;
00667             if (j + 1 < numelem && comma != ':') {
00668                 *op++ = ' ';
00669                 opleft--;
00670             }
00671         }
00672         if (i + 1 < numhunk) {
00673             *op++ = comma;
00674             opleft--;
00675         }
00676         if (opleft < 1)
00677             goto toobig;
00678 
00679     }
00680     return (optbuf);
00681  toobig:
00682     warning("dhcp option too large");
00683     return ("<error>");
00684 }
00685 
00686 void
00687 do_packet(struct interface_info *interface, struct dhcp_packet *packet,
00688     int len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
00689 {
00690     struct packet tp;
00691     int i;
00692 
00693     if (packet->hlen > sizeof(packet->chaddr)) {
00694         note("Discarding packet with invalid hlen.");
00695         return;
00696     }
00697 
00698     memset(&tp, 0, sizeof(tp));
00699     tp.raw = packet;
00700     tp.packet_length = len;
00701     tp.client_port = from_port;
00702     tp.client_addr = from;
00703     tp.interface = interface;
00704     tp.haddr = hfrom;
00705 
00706     parse_options(&tp);
00707     if (tp.options_valid &&
00708         tp.options[DHO_DHCP_MESSAGE_TYPE].data)
00709         tp.packet_type = tp.options[DHO_DHCP_MESSAGE_TYPE].data[0];
00710     if (tp.packet_type)
00711         dhcp(&tp);
00712     else
00713         bootp(&tp);
00714 
00715     /* Free the data associated with the options. */
00716     for (i = 0; i < 256; i++)
00717         if (tp.options[i].len && tp.options[i].data)
00718             free(tp.options[i].data);
00719 }

Generated on Thu May 24 2012 04:19:21 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.