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