00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <sys/types.h>
00025 #include <unistd.h>
00026
00027 #include <sys/socket.h>
00028 #include <arpa/inet.h>
00029 #include <time.h>
00030 #include <search.h>
00031 extern void tdestroy (void *root, void (*free_node)(void *nodep));
00032 #include <stdio.h>
00033
00034 #include <isc_dhcp/dhcpd.h>
00035
00036 #include <dhcp4_lease.h>
00037
00038 static int option_code_comparator( const void *p1, const void *p2 )
00039 {
00040 const DHCPv4_option *o1 = p1, *o2 = p2;
00041 uint16_t o1code = (o1->unicode << 8) | (o1->code),
00042 o2code = (o2->unicode << 8) | (o2->code);
00043 return
00044 ( ( o1code == o2code )
00045 ? 0
00046 :( ( o1code > o2code )
00047 ? 1
00048 : -1
00049 )
00050 );
00051 }
00052
00053 static int option_name_comparator( const void *p1, const void *p2 )
00054 {
00055 const DHCPv4_option *o1 = p1, *o2 = p2;
00056 return strcmp(o1->name, o2->name);
00057 }
00058
00059 DHCPv4_option *dhcpv4_get_option_by_code( DHCPv4_lease *l, uint8_t universe, uint8_t code)
00060 {
00061 DHCPv4_option sop, **opp;
00062 sop.unicode = universe;
00063 sop.code = code;
00064 if( (opp = tfind( &sop, &(l->options), option_code_comparator)) != 0L )
00065 return *opp;
00066 return 0L;
00067 }
00068
00069 DHCPv4_option *dhcpv4_get_option_by_name( DHCPv4_lease *l, char *n)
00070 {
00071 DHCPv4_option sop, **opp;
00072 sop.name = n;
00073 if( (opp = tfind( &sop, &(l->options_by_name), option_name_comparator)) != 0L )
00074 return *opp;
00075 return 0L;
00076 }
00077
00078 static
00079 void dhcp4_client_option_add
00080 ( struct option_cache *oc,
00081 struct packet *packet,
00082 struct lease *isc_lease,
00083 struct client_state *client,
00084 struct option_state *in_options,
00085 struct option_state *cfg_options,
00086 struct binding_scope **scope,
00087 struct universe *u,
00088 void *lease_ptr
00089 );
00090
00091 DHCPv4_lease *dhcpv4_lease( struct client_state *client )
00092 {
00093 DHCPv4_lease *lease;
00094 struct client_lease *l = client->new ? client->new : client->active;
00095 int i;
00096
00097 if ( ( l == 0L ) || (l->address.len != 4) )
00098 return 0L;
00099
00100 lease = calloc( 1, sizeof(DHCPv4_lease) );
00101
00102 lease->address.s_addr =
00103 htonl
00104 ( (l->address.iabuf[0] << 24)
00105 |(l->address.iabuf[1] << 16)
00106 |(l->address.iabuf[2] << 8)
00107 | l->address.iabuf[3]
00108 );
00109
00110 lease->requested_address.s_addr =
00111 htonl
00112 ( (client->requested_address.iabuf[0] << 24)
00113 |(client->requested_address.iabuf[1] << 16)
00114 |(client->requested_address.iabuf[2] << 8)
00115 | client->requested_address.iabuf[3]
00116 );
00117
00118 lease->is_static = l->is_static;
00119 lease->is_bootp = l->is_bootp;
00120 lease->requested = client->first_sending;
00121 lease->expiry = l->expiry;
00122 lease->renewal = l->renewal;
00123 lease->rebind = l->rebind;
00124
00125 if ( client->interface )
00126 {
00127 lease->if_index = client->interface->index;
00128 if ( client->interface->name )
00129 lease->if_name = strdup(client->interface->name);
00130 }else
00131 lease->if_index = -1;
00132
00133 lease->server_address = client->packet.siaddr;
00134
00135 if ( l->filename )
00136 lease->filename = strdup(l->filename);
00137
00138 if ( l->server_name )
00139 lease->server_name = strdup(l->server_name);
00140 for (i = 0; i < l -> options -> universe_count; i++)
00141 {
00142
00143 option_space_foreach
00144 ( (struct packet *)0, (struct lease *)0,
00145 client, (struct option_state *)0,
00146 l -> options, &global_scope,
00147 universes [i],
00148 lease, dhcp4_client_option_add
00149 );
00150 }
00151 return lease;
00152 }
00153
00154 static
00155 void option_free( void *opp )
00156 {
00157 DHCPv4_option *opt = opp;
00158 free(opt->name);
00159 free(opt->format);
00160 free(opt->universe);
00161 free(opt);
00162 }
00163
00164 void dhcpv4_lease_free( DHCPv4_lease *lease)
00165 {
00166 if(lease->if_name)
00167 {
00168 free(lease->if_name);
00169 lease->if_name = 0;
00170 }
00171 if(lease->filename)
00172 {
00173 free(lease->filename);
00174 lease->filename = 0;
00175 }
00176 if(lease->server_name)
00177 {
00178 free(lease->server_name);
00179 lease->server_name=0;
00180 }
00181 if( lease->options )
00182 {
00183 tdestroy(lease->options, option_free);
00184 lease->options = 0;
00185 }
00186 free(lease);
00187 }
00188
00189 static void option_twalker( const void *p, const VISIT which, const int depth )
00190 {
00191 DHCPv4_option *option, *const*opp=p;
00192 DHCPv4_lease *lease;
00193
00194 if( (opp == 0L) || ((option = *opp) == 0L)
00195 ||( (which != postorder) && (which != leaf) )
00196 ) return;
00197
00198 lease = option -> lease;
00199
00200 lease -> handler (option, lease -> handler_arg );
00201 }
00202
00203 void dhcpv4_process_options ( DHCPv4_lease *lease, DHCPv4_option_handler handler, void *handler_arg)
00204 {
00205 if ( lease && lease->options )
00206 {
00207 lease->handler = handler;
00208 lease->handler_arg = handler_arg;
00209 twalk(lease->options, option_twalker);
00210 }
00211 }
00212
00213 #define DHC_PAD( type, total_length ) ( ( sizeof(type) - (total_length & (sizeof(type)-1) ) ) & (sizeof(type)-1) )
00214
00215 void dhcp4_client_option_add
00216 ( struct option_cache *oc,
00217 struct packet *packet,
00218 struct lease *isc_lease,
00219 struct client_state *client,
00220 struct option_state *in_options,
00221 struct option_state *cfg_options,
00222 struct binding_scope **scope,
00223 struct universe *u,
00224 void *lease_ptr
00225 )
00226 {
00227 DHCPv4_lease *lease = lease_ptr;
00228 DHCPv4_option *option;
00229 struct data_string data;
00230 const uint8_t *dp, *de;
00231 uint8_t *p, *value, *endv,
00232 is_array = 0, element_pad = 0, **vl;
00233 int fi=0, i=0, length = 0, n_values = 0, total_length = 0, dbg_length=0;
00234 uint32_t intv;
00235 uint16_t sv, n_members=0, n_elements =0, member_size=0;
00236 const uint8_t *dbg_d_last;
00237 uint8_t *dbg_v_last, **dbg_vl_last;
00238 void *dbg_t;
00239
00240
00241
00242 memset (&data, 0, sizeof data);
00243 if ( evaluate_option_cache
00244 ( &data, packet, isc_lease, client,
00245 in_options, cfg_options, scope, oc, MDL
00246 )
00247 )
00248 {
00249 if (data.len)
00250 {
00251
00252
00253
00254
00255 dp = &(data.data[0]);
00256 de = &(data.data[data.len]);
00257 dbg_length = length;
00258 dbg_d_last = dp;
00259 for (fi=0;
00260 (oc -> option -> format [fi])
00261 &&( (dp < de)
00262 ||( (dp == de)
00263 &&( (oc -> option -> format [fi] == 'A')
00264 ||(oc -> option -> format [fi] == 'a')
00265 )
00266 )
00267 );
00268 fi++
00269 )
00270 {
00271
00272
00273
00274
00275 dbg_d_last = dp;
00276 dbg_length = length;
00277 switch ( oc-> option -> format [fi] )
00278 {
00279 case DHC_T_IP_ADDRESS:
00280 case DHC_T_UINT32:
00281 case DHC_T_INT32:
00282 length += sizeof(uint32_t) + DHC_PAD( uint32_t, length );
00283 dp += 4;
00284 n_members++;
00285 break;
00286
00287 case DHC_T_UINT16:
00288 case DHC_T_INT16:
00289 length += sizeof(int16_t) + DHC_PAD( int16_t, length );
00290 dp += 2;
00291 n_members++;
00292 break;
00293
00294 case DHC_T_ENUMERATION:
00295 for(i=0; oc->option->format[fi] && (oc->option->format[fi] != '.'); fi++, i++ );
00296
00297
00298
00299 case DHC_T_CHAR:
00300 case DHC_T_UCHAR:
00301 case DHC_T_BOOL:
00302 case DHC_T_IMPLICIT_BOOL:
00303 length += sizeof(uint8_t) + DHC_PAD(uint8_t, length );
00304 dp += 1;
00305 n_members++;
00306 break;
00307
00308 case DHC_T_ENCAPSULATION:
00309 case DHC_T_ENCAPSULATION_NO_DIRECTIVE:
00310
00311 for(i=0; oc -> option -> format[fi] && (oc -> option -> format[fi] != '.'); fi++, i++);
00312
00313
00314
00315
00316 case DHC_T_HEX_STRING:
00317 length += ( (unsigned long)de - (unsigned long)dp );
00318 dp = de ;
00319 n_members++;
00320
00321
00322
00323 break;
00324
00325 case DHC_T_DOMAIN_NAME:
00326 case DHC_T_TEXT:
00327 case DHC_T_OPTION_SPACE:
00328 length += ( data.len - length );
00329 if( data.data[data.len - 1] != '\0' )
00330 {
00331 length += 1;
00332
00333 }
00334 dp = de ;
00335 n_members++;
00336 break;
00337
00338
00339
00340
00341
00342
00343
00344 case DHC_T_ARRAY:
00345 case DHC_T_LIST:
00346 is_array = 1;
00347 member_size = length;
00348
00349
00350
00351
00352
00353
00354 n_elements = ( (unsigned long)data.len / (unsigned long )(dp - &(data.data[0])));
00355 if( n_elements && n_members )
00356 {
00357 switch( oc -> option -> format [ 0 ] )
00358 {
00359 case DHC_T_IP_ADDRESS:
00360 case DHC_T_UINT32:
00361 case DHC_T_INT32:
00362 length += (element_pad = DHC_PAD(uint32_t, length));
00363 break;
00364
00365 case DHC_T_UINT16:
00366 case DHC_T_INT16:
00367 length += (element_pad = DHC_PAD(uint8_t, length));
00368 break;
00369
00370 case DHC_T_CHAR:
00371 case DHC_T_UCHAR:
00372 case DHC_T_BOOL:
00373 case DHC_T_IMPLICIT_BOOL:
00374 case DHC_T_ENUMERATION:
00375
00376 length += (element_pad = DHC_PAD(uint8_t, length));
00377 default:
00378 break;
00379 }
00380 }
00381 length = n_elements * length;
00382 length -= element_pad;
00383 dp = de;
00384 if( oc->option->format[fi+1] != '\0' )
00385 {
00386
00387
00388 goto dhcp4_client_option_add_fail ;
00389 }
00390 break;
00391
00392 case DHC_T_OPTIONAL:
00393 case DHC_T_NONE:
00394 default:
00395 break;
00396 }
00397 }
00398
00399
00400
00401 if( length == 0 )
00402 return;
00403
00404 n_values = n_members * (n_elements ? n_elements : 1);
00405
00406 total_length =
00407 sizeof( DHCPv4_option )
00408 + length
00409 + ( ( n_values > 1 )
00410 ? ( ( n_values * sizeof(uint8_t*) )
00411 +( DHC_PAD ( void*, length ) )
00412 )
00413 : 0
00414 );
00415
00416
00417
00418
00419
00420 option = malloc( total_length );
00421
00422 if( option == 0L )
00423 return ;
00424 memset(option, '\0', total_length);
00425 option->lease = lease;
00426 option->name = strdup(oc->option->name);
00427 option->format = strdup(oc->option->format);
00428 option->code = oc->option->code;
00429 option->unicode = u->index;
00430 option->universe = strdup(u->name);
00431 option->length = length;
00432 option->form =
00433 is_array
00434 ? DHCO_ARRAY
00435 :( ( n_members > 1 )
00436 ? DHCO_STRUCT
00437 : DHCO_SCALAR
00438 );
00439 if ( option->form == DHCO_STRUCT )
00440 {
00441 option->size = length ;
00442 option->n_members = n_members;
00443 option->n_elements = 0;
00444 }else
00445 if ( option->form == DHCO_ARRAY )
00446 {
00447 option->size = member_size;
00448 option->n_elements = n_elements;
00449 option->n_members = n_members;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 vl = (void*)
00461 ( (option->form != DHCO_SCALAR)
00462 ?( (unsigned long)&(option->value[length])
00463 + (unsigned long)(DHC_PAD(void*,length))
00464 )
00465 : 0L
00466 );
00467
00468
00469
00470
00471
00472
00473
00474 value = &(option->value[0]);
00475 endv = &(option -> value[ length ]);
00476 dp = &(data.data[0]);
00477 de = &(data.data[data.len]);
00478 length = 0;
00479 dbg_length = length;
00480 dbg_d_last = dp;
00481 dbg_v_last = value;
00482 dbg_vl_last = vl;
00483
00484 for ( fi=0;
00485 (option -> format [fi])
00486 && (dp < de)
00487 && (value < endv);
00488 fi++
00489 )
00490 {
00491 if ( vl )
00492 *vl = value;
00493
00494
00495
00496
00497
00498
00499
00500
00501 dbg_d_last = dp;
00502 dbg_v_last = value;
00503 dbg_vl_last = vl;
00504 dbg_length = length;
00505
00506 switch ( oc -> option -> format [fi] )
00507 {
00508 case DHC_T_IP_ADDRESS:
00509 value += DHC_PAD(uint32_t, length);
00510 length += DHC_PAD(uint32_t, length);
00511 memcpy(value, dp, sizeof(uint32_t));
00512 value += sizeof(uint32_t);
00513 length += sizeof(uint32_t);
00514 dp += 4;
00515 break;
00516
00517 case DHC_T_INT32:
00518 case DHC_T_UINT32:
00519 value += DHC_PAD(uint32_t, length);
00520 length += DHC_PAD(uint32_t, length);
00521 memcpy( &intv, dp, sizeof(uint32_t));
00522 *((uint32_t*)value) = ntohl( intv );
00523 value += sizeof(uint32_t);
00524 length += sizeof(uint32_t);
00525 dp += 4;
00526 break;
00527
00528 case DHC_T_UINT16:
00529 case DHC_T_INT16:
00530 value += DHC_PAD(uint16_t, length);
00531 length += DHC_PAD(uint16_t, length);
00532 memcpy( &sv, dp, sizeof(uint16_t));
00533 *((uint16_t*)value)=ntohs( sv );
00534 value += sizeof(uint16_t);
00535 length += sizeof(uint16_t);
00536 dp += 2;
00537 break;
00538
00539 case DHC_T_ENUMERATION:
00540 for(i=0; oc->option->format[fi] && (oc->option->format[fi] != '.'); fi++, i++ );
00541
00542
00543
00544 case DHC_T_CHAR:
00545 case DHC_T_UCHAR:
00546 case DHC_T_BOOL:
00547 case DHC_T_IMPLICIT_BOOL:
00548 value += DHC_PAD(uint8_t, length );
00549 length += DHC_PAD(uint8_t, length );
00550 *value = *dp;
00551 value += sizeof(uint8_t);
00552 length += sizeof(uint8_t);
00553 dp += 1;
00554 break;
00555
00556 case DHC_T_ENCAPSULATION:
00557 case DHC_T_ENCAPSULATION_NO_DIRECTIVE:
00558
00559 for(i=0; oc -> option -> format[fi] && (oc -> option -> format[fi] != '.'); fi++, i++);
00560
00561
00562
00563 case DHC_T_HEX_STRING:
00564 memcpy( value, dp, ((unsigned long)de) - ((unsigned long)dp) );
00565 value += ((unsigned long)de) - ((unsigned long)dp);
00566 length += ((unsigned long)de) - ((unsigned long)dp);
00567 dp = de;
00568 break;
00569
00570 case DHC_T_DOMAIN_NAME:
00571 case DHC_T_TEXT:
00572 case DHC_T_OPTION_SPACE:
00573 p = value;
00574 memcpy( value, dp, ((unsigned long)de) - ((unsigned long)dp) );
00575 value += ((unsigned long)de) - ((unsigned long)dp);
00576 if( *(de-1) != '\0' )
00577 {
00578 *(value++) = '\0';
00579 length += 1;
00580 }
00581 length += (((unsigned long)value) - ((unsigned long)p));
00582 dp = de;
00583 break;
00584
00585 case DHC_T_ARRAY:
00586 case DHC_T_LIST:
00587 fi = -1;
00588 continue;
00589
00590 case DHC_T_OPTIONAL:
00591 case DHC_T_NONE:
00592
00593 break;
00594 }
00595 if ( vl )
00596 vl++;
00597 }
00598
00599
00600
00601 if ( (dp != de) || (value != endv) )
00602 {
00603
00604
00605
00606
00607 goto dhcp4_client_option_add_fail;
00608 }
00609
00610 dbg_t = tsearch( option, &(lease->options), option_code_comparator );
00611 dbg_t = tsearch( option, &(lease->options_by_name), option_name_comparator );
00612
00613
00614 return;
00615
00616 dhcp4_client_option_add_fail:
00617
00618 return;
00619 }
00620 }
00621 }
00622
00623 struct dhcpv4_pack_s
00624 {
00625 DHCPv4_lease *lease;
00626 uint8_t *buf;
00627 uint8_t *bufp;
00628 uint32_t buflen;
00629 };
00630
00631 void dhcpv4_pack_lease_option(DHCPv4_option *opt, void *psp )
00632 {
00633 struct dhcpv4_pack_s *ps = psp;
00634 uint32_t n_values =
00635 ( (opt->n_elements ? opt->n_elements : 1)
00636 * opt->n_members
00637 ),
00638 name_len = strlen(opt->name),
00639 uni_len = strlen(opt->universe),
00640 fmt_len = strlen(opt->format);
00641
00642
00643 if( ps->buf )
00644 *((uint32_t*)(ps->bufp))=name_len;
00645 ps->bufp +=sizeof(uint32_t);
00646 if( ps->buf )
00647 memcpy(ps->bufp,opt->name,name_len);
00648 ps->bufp+=name_len + DHC_PAD(uint32_t,name_len);
00649
00650 if( ps->buf )
00651 *((uint32_t*)(ps->bufp))=uni_len;
00652 ps->bufp+=sizeof(uint32_t);
00653 if( ps->buf )
00654 memcpy(ps->bufp,opt->universe,uni_len);
00655 ps->bufp+=uni_len + DHC_PAD(uint32_t,uni_len);
00656
00657 if( ps->buf )
00658 *((uint32_t*)(ps->bufp))=fmt_len;
00659 ps->bufp+=sizeof(uint32_t);
00660 if( ps->buf )
00661 memcpy(ps->bufp,opt->format,fmt_len);
00662 ps->bufp+=fmt_len + DHC_PAD(uint32_t,fmt_len);
00663
00664 uint8_t sizeof_opt = ((unsigned long)&(opt->value[0]))-((unsigned long)opt);
00665 if( ps->buf )
00666 memcpy(ps->bufp, opt, sizeof_opt);
00667 ps->bufp += sizeof_opt;
00668 if( ps->buf )
00669 memcpy(ps->bufp, &(opt->value[0]), opt->length);
00670 ps->bufp += opt->length
00671 + DHC_PAD(uint32_t, opt->length)
00672 + ( ((n_values > 1) ? n_values : 0) * sizeof(void*));
00673
00674
00675 }
00676
00677 int dhcpv4_pack_lease( DHCPv4_lease *lease, uint8_t *buf, uint32_t len )
00678 {
00679 if(lease == 0L)
00680 return 0;
00681
00682 int filename_len = lease->filename ? strlen(lease->filename) : 0,
00683 servername_len = lease->server_name ? strlen(lease->server_name) : 0,
00684 ifname_len = lease->if_name ? strlen(lease->if_name) : 0;
00685
00686 struct dhcpv4_pack_s ps =
00687 { .lease = lease,
00688 .buf = buf,
00689 .bufp = buf,
00690 .buflen= len
00691 };
00692
00693 if(ps.buf)
00694 {
00695 *((uint32_t*)(ps.bufp)) = len;
00696 ps.bufp += sizeof(uint32_t);
00697 }else
00698 ps.bufp += sizeof(uint32_t);
00699
00700 if( ps.buf )
00701 memcpy(ps.bufp, lease, sizeof(DHCPv4_lease));
00702
00703 ps.bufp += sizeof(DHCPv4_lease) + DHC_PAD(uint32_t, sizeof(DHCPv4_lease));
00704
00705 if( filename_len )
00706 {
00707 if( ps.buf )
00708 *((uint32_t*)ps.bufp) = filename_len;
00709 ps.bufp+=sizeof(uint32_t);
00710 if( ps.buf )
00711 memcpy(ps.bufp, lease->filename, filename_len);
00712 ps.bufp += filename_len;
00713 ps.bufp += DHC_PAD(uint32_t, filename_len);
00714 }else
00715 {
00716 if( ps.buf )
00717 *((uint32_t*)ps.bufp) = 0;
00718 ps.bufp+=sizeof(uint32_t);
00719 }
00720
00721 if( servername_len )
00722 {
00723 if( ps.buf )
00724 *((uint32_t*)ps.bufp) = servername_len;
00725 ps.bufp+=sizeof(uint32_t);
00726 if( ps.buf )
00727 memcpy(ps.bufp, lease->server_name, servername_len);
00728 ps.bufp += servername_len;
00729 ps.bufp += DHC_PAD(uint32_t, servername_len);
00730 }else
00731 {
00732 if( ps.buf )
00733 *((uint32_t*)ps.bufp) = 0;
00734 ps.bufp+=sizeof(uint32_t);
00735 }
00736
00737 if( ifname_len )
00738 {
00739 if( ps.buf )
00740 *((uint32_t*)ps.bufp) = ifname_len;
00741 ps.bufp+=sizeof(uint32_t);
00742 if( ps.buf )
00743 memcpy(ps.bufp, lease->if_name, ifname_len);
00744 ps.bufp += ifname_len;
00745 ps.bufp += DHC_PAD(uint32_t, ifname_len);
00746 }else
00747 {
00748 if( ps.buf )
00749 *((uint32_t*)ps.bufp) = 0;
00750 ps.bufp+=sizeof(uint32_t);
00751 }
00752
00753 dhcpv4_process_options( lease, dhcpv4_pack_lease_option, &ps );
00754
00755 return (ps.bufp - ps.buf);
00756 }
00757
00758 DHCPv4_lease *dhcpv4_unpack_lease( uint8_t *buf )
00759 {
00760 if( buf == 0 )
00761 return 0;
00762
00763 uint32_t packlen = *((uint32_t*)buf);
00764 uint8_t *bufp = buf + sizeof(uint32_t) ;
00765 DHCPv4_lease *rlease = 0;
00766 DHCPv4_option *opt=0, *ropt=0;
00767 uint32_t n_values=0, slen=0;
00768
00769 if( packlen < (sizeof(DHCPv4_lease) + (2 * sizeof(uint32_t))) )
00770 return 0L;
00771
00772 rlease = calloc(1, sizeof(DHCPv4_lease));
00773
00774 memcpy(rlease, bufp, sizeof(DHCPv4_lease));
00775 rlease->options = 0;
00776 rlease->options_by_name = 0;
00777 rlease->handler = 0;
00778 rlease->handler_arg = 0;
00779 rlease->if_name = 0;
00780 rlease->server_name = 0;
00781 rlease->filename = 0;
00782
00783 bufp += sizeof(DHCPv4_lease) + DHC_PAD(uint32_t, sizeof(DHCPv4_lease));
00784
00785 if ((slen = *((uint32_t*)bufp)) > 0)
00786 {
00787 rlease->filename = calloc(1, slen + 1 );
00788 bufp += sizeof(uint32_t);
00789 memcpy(rlease->filename, bufp, slen);
00790 bufp += slen + DHC_PAD(uint32_t, slen);
00791 }else
00792 bufp += sizeof(uint32_t);
00793
00794 if((slen = *((uint32_t*)bufp)) > 0)
00795 {
00796 rlease->server_name = calloc(1, slen + 1 );
00797 bufp += sizeof(uint32_t);
00798 memcpy(rlease->server_name, bufp, slen);
00799 bufp += slen + DHC_PAD(uint32_t, slen);
00800 }else
00801 bufp += sizeof(uint32_t);
00802
00803 if((slen = *((uint32_t*)bufp)) > 0)
00804 {
00805 rlease->if_name = calloc(1, slen + 1 );
00806 bufp += sizeof(uint32_t);
00807 memcpy(rlease->if_name, bufp, slen);
00808 bufp += slen + DHC_PAD(uint32_t, slen);
00809 }else
00810 bufp += sizeof(uint32_t);
00811
00812 while( bufp < (buf + packlen) )
00813 {
00814 char *name, *universe, *format;
00815 void **lv, *lv0, **rlv;
00816 int nv=0;
00817
00818
00819
00820 slen = *((uint32_t*)bufp);
00821 name = calloc(1, slen + 1);
00822 bufp += sizeof(uint32_t);
00823 memcpy(name, bufp, slen);
00824
00825 bufp += slen + DHC_PAD(uint32_t, slen);
00826
00827 slen = *((uint32_t*)bufp);
00828 universe = calloc(1, slen + 1);
00829 bufp += sizeof(uint32_t);
00830 memcpy(universe, bufp, slen);
00831 bufp += slen + DHC_PAD(uint32_t, slen);
00832
00833 slen = *((uint32_t*)bufp);
00834 format = calloc(1, slen + 1);
00835 bufp += sizeof(uint32_t);
00836 memcpy(format, bufp, slen);
00837 bufp += slen + DHC_PAD(uint32_t, slen);
00838
00839 opt = (DHCPv4_option*)bufp;
00840
00841 uint8_t sizeof_opt = ((unsigned long)&(opt->value[0]))-((unsigned long)opt);
00842
00843 n_values =
00844 ( (opt->n_elements ? opt->n_elements : 1)
00845 * opt->n_members
00846 );
00847
00848
00849
00850 ropt =
00851 calloc
00852 (1, sizeof_opt
00853 + opt->length
00854 + DHC_PAD(uint32_t, opt->length)
00855 + ( ((n_values > 1) ? n_values : 0) * sizeof(void*))
00856 );
00857 memcpy(ropt, opt,
00858 sizeof_opt
00859 + opt->length
00860 + DHC_PAD(uint32_t, opt->length)
00861 + ( ((n_values > 1) ? n_values : 0) * sizeof(void*))
00862 );
00863 ropt->name = name;
00864 ropt->universe = universe;
00865 ropt->format = format;
00866
00867 if( n_values > 1 )
00868 {
00869 lv = (void*)
00870 ( &(opt->value[0])
00871 + opt->length
00872 + DHC_PAD(uint32_t, opt->length)
00873 );
00874
00875 rlv = (void*)
00876 ( &(ropt->value[0])
00877 + opt->length
00878 + DHC_PAD(uint32_t, opt->length)
00879 );
00880
00881 lv0 = *lv;
00882 nv = n_values;
00883 while(nv--)
00884 *(rlv++)=&(ropt->value[0]) + ((*(lv++))-lv0);
00885 }
00886 bufp += sizeof_opt
00887 + opt->length
00888 + DHC_PAD(uint32_t, opt->length)
00889 + ( ((n_values > 1) ? n_values : 0) * sizeof(void*))
00890 ;
00891
00892 ropt->lease = rlease;
00893 tsearch(ropt,&(rlease->options),option_code_comparator);
00894 tsearch(ropt,&(rlease->options_by_name),option_name_comparator);
00895 }
00896 return rlease;
00897 }