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