Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenoptions.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
1.7.6.1
|