| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815 |
- /**
- * @file BDHCPClientCore.c
- * @author Ambroz Bizjak <ambrop7@gmail.com>
- *
- * @section LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <string.h>
- #include <stdlib.h>
- #include <misc/byteorder.h>
- #include <misc/minmax.h>
- #include <misc/balloc.h>
- #include <misc/bsize.h>
- #include <security/BRandom.h>
- #include <base/BLog.h>
- #include <dhcpclient/BDHCPClientCore.h>
- #include <generated/blog_channel_BDHCPClientCore.h>
- #define RESET_TIMEOUT 4000
- #define REQUEST_TIMEOUT 3000
- #define RENEW_REQUEST_TIMEOUT 20000
- #define MAX_REQUESTS 4
- #define RENEW_TIMEOUT(lease) ((btime_t)500 * (lease))
- #define XID_REUSE_MAX 8
- #define LEASE_TIMEOUT(lease) ((btime_t)1000 * (lease) - RENEW_TIMEOUT(lease))
- #define STATE_RESETTING 1
- #define STATE_SENT_DISCOVER 2
- #define STATE_SENT_REQUEST 3
- #define STATE_FINISHED 4
- #define STATE_RENEWING 5
- #define IP_UDP_HEADERS_SIZE 28
- static void report_up (BDHCPClientCore *o)
- {
- o->handler(o->user, BDHCPCLIENTCORE_EVENT_UP);
- return;
- }
- static void report_down (BDHCPClientCore *o)
- {
- o->handler(o->user, BDHCPCLIENTCORE_EVENT_DOWN);
- return;
- }
- static void send_message (
- BDHCPClientCore *o,
- int type,
- uint32_t xid,
- int have_requested_ip_address, uint32_t requested_ip_address,
- int have_dhcp_server_identifier, uint32_t dhcp_server_identifier
- )
- {
- ASSERT(type == DHCP_MESSAGE_TYPE_DISCOVER || type == DHCP_MESSAGE_TYPE_REQUEST)
-
- if (o->sending) {
- BLog(BLOG_ERROR, "already sending");
- return;
- }
-
- // write header
- memset(o->send_buf, 0, sizeof(*o->send_buf));
- o->send_buf->op = hton8(DHCP_OP_BOOTREQUEST);
- o->send_buf->htype = hton8(DHCP_HARDWARE_ADDRESS_TYPE_ETHERNET);
- o->send_buf->hlen = hton8(6);
- o->send_buf->xid = xid;
- o->send_buf->secs = hton16(0);
- memcpy(o->send_buf->chaddr, o->client_mac_addr, sizeof(o->client_mac_addr));
- o->send_buf->magic = hton32(DHCP_MAGIC);
-
- // write options
-
- struct dhcp_option_header *out = (void *)(o->send_buf + 1);
-
- // DHCP message type
- out->type = hton8(DHCP_OPTION_DHCP_MESSAGE_TYPE);
- out->len = hton8(sizeof(struct dhcp_option_dhcp_message_type));
- ((struct dhcp_option_dhcp_message_type *)(out + 1))->type = hton8(type);
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
-
- if (have_requested_ip_address) {
- // requested IP address
- out->type = hton8(DHCP_OPTION_REQUESTED_IP_ADDRESS);
- out->len = hton8(sizeof(struct dhcp_option_addr));
- ((struct dhcp_option_addr *)(out + 1))->addr = requested_ip_address;
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
- }
-
- if (have_dhcp_server_identifier) {
- // DHCP server identifier
- out->type = hton8(DHCP_OPTION_DHCP_SERVER_IDENTIFIER);
- out->len = hton8(sizeof(struct dhcp_option_dhcp_server_identifier));
- ((struct dhcp_option_dhcp_server_identifier *)(out + 1))->id = dhcp_server_identifier;
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
- }
-
- // maximum message size
- out->type = hton8(DHCP_OPTION_MAXIMUM_MESSAGE_SIZE);
- out->len = hton8(sizeof(struct dhcp_option_maximum_message_size));
- ((struct dhcp_option_maximum_message_size *)(out + 1))->size = hton16(IP_UDP_HEADERS_SIZE + PacketRecvInterface_GetMTU(o->recv_if));
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
-
- // parameter request list
- out->type = hton8(DHCP_OPTION_PARAMETER_REQUEST_LIST);
- out->len = hton8(4);
- ((uint8_t *)(out + 1))[0] = DHCP_OPTION_SUBNET_MASK;
- ((uint8_t *)(out + 1))[1] = DHCP_OPTION_ROUTER;
- ((uint8_t *)(out + 1))[2] = DHCP_OPTION_DOMAIN_NAME_SERVER;
- ((uint8_t *)(out + 1))[3] = DHCP_OPTION_IP_ADDRESS_LEASE_TIME;
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
-
- if (o->hostname) {
- // host name
- out->type = hton8(DHCP_OPTION_HOST_NAME);
- out->len = hton8(strlen(o->hostname));
- memcpy(out + 1, o->hostname, strlen(o->hostname));
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
- }
-
- if (o->vendorclassid) {
- // vendor class identifier
- out->type = hton8(DHCP_OPTION_VENDOR_CLASS_IDENTIFIER);
- out->len = hton8(strlen(o->vendorclassid));
- memcpy(out + 1, o->vendorclassid, strlen(o->vendorclassid));
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
- }
-
- if (o->clientid) {
- // client identifier
- out->type = hton8(DHCP_OPTION_CLIENT_IDENTIFIER);
- out->len = hton8(o->clientid_len);
- memcpy(out + 1, o->clientid, o->clientid_len);
- out = (void *)((uint8_t *)(out + 1) + ntoh8(out->len));
- }
-
- // end option
- *((uint8_t *)out) = 0xFF;
- out = (void *)((uint8_t *)out + 1);
-
- // send it
- PacketPassInterface_Sender_Send(o->send_if, (uint8_t *)o->send_buf, (uint8_t *)out - (uint8_t *)o->send_buf);
- o->sending = 1;
- }
- static void send_handler_done (BDHCPClientCore *o)
- {
- ASSERT(o->sending)
- DebugObject_Access(&o->d_obj);
-
- o->sending = 0;
- }
- static void recv_handler_done (BDHCPClientCore *o, int data_len)
- {
- ASSERT(data_len >= 0)
- DebugObject_Access(&o->d_obj);
-
- // receive more packets
- PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)o->recv_buf);
-
- if (o->state == STATE_RESETTING) {
- return;
- }
-
- // check header
-
- if (data_len < sizeof(*o->recv_buf)) {
- return;
- }
-
- if (ntoh8(o->recv_buf->op) != DHCP_OP_BOOTREPLY) {
- return;
- }
-
- if (ntoh8(o->recv_buf->htype) != DHCP_HARDWARE_ADDRESS_TYPE_ETHERNET) {
- return;
- }
-
- if (ntoh8(o->recv_buf->hlen) != 6) {
- return;
- }
-
- if (o->recv_buf->xid != o->xid) {
- return;
- }
-
- if (memcmp(o->recv_buf->chaddr, o->client_mac_addr, sizeof(o->client_mac_addr))) {
- return;
- }
-
- if (ntoh32(o->recv_buf->magic) != DHCP_MAGIC) {
- return;
- }
-
- // parse and check options
-
- uint8_t *pos = (uint8_t *)o->recv_buf + sizeof(*o->recv_buf);
- int len = data_len - sizeof(*o->recv_buf);
-
- int have_end = 0;
-
- int dhcp_message_type = -1;
-
- int have_dhcp_server_identifier = 0;
- uint32_t dhcp_server_identifier;
-
- int have_ip_address_lease_time = 0;
- uint32_t ip_address_lease_time;
-
- int have_subnet_mask = 0;
- uint32_t subnet_mask;
-
- int have_router = 0;
- uint32_t router;
-
- int domain_name_servers_count = 0;
- uint32_t domain_name_servers[BDHCPCLIENTCORE_MAX_DOMAIN_NAME_SERVERS];
-
- while (len > 0) {
- // padding option ?
- if (*pos == 0) {
- pos++;
- len--;
- continue;
- }
-
- if (have_end) {
- return;
- }
-
- // end option ?
- if (*pos == 0xff) {
- pos++;
- len--;
- have_end = 1;
- continue;
- }
-
- // check option header
- if (len < sizeof(struct dhcp_option_header)) {
- return;
- }
- struct dhcp_option_header *opt = (void *)pos;
- pos += sizeof(*opt);
- len -= sizeof(*opt);
- int opt_type = ntoh8(opt->type);
- int opt_len = ntoh8(opt->len);
-
- // check option payload
- if (opt_len > len) {
- return;
- }
- void *optval = pos;
- pos += opt_len;
- len -= opt_len;
-
- switch (opt_type) {
- case DHCP_OPTION_DHCP_MESSAGE_TYPE: {
- if (opt_len != sizeof(struct dhcp_option_dhcp_message_type)) {
- return;
- }
- struct dhcp_option_dhcp_message_type *val = optval;
-
- dhcp_message_type = ntoh8(val->type);
- } break;
-
- case DHCP_OPTION_DHCP_SERVER_IDENTIFIER: {
- if (opt_len != sizeof(struct dhcp_option_dhcp_server_identifier)) {
- return;
- }
- struct dhcp_option_dhcp_server_identifier *val = optval;
-
- dhcp_server_identifier = val->id;
- have_dhcp_server_identifier = 1;
- } break;
-
- case DHCP_OPTION_IP_ADDRESS_LEASE_TIME: {
- if (opt_len != sizeof(struct dhcp_option_time)) {
- return;
- }
- struct dhcp_option_time *val = optval;
-
- ip_address_lease_time = ntoh32(val->time);
- have_ip_address_lease_time = 1;
- } break;
-
- case DHCP_OPTION_SUBNET_MASK: {
- if (opt_len != sizeof(struct dhcp_option_addr)) {
- return;
- }
- struct dhcp_option_addr *val = optval;
-
- subnet_mask = val->addr;
- have_subnet_mask = 1;
- } break;
-
- case DHCP_OPTION_ROUTER: {
- if (opt_len != sizeof(struct dhcp_option_addr)) {
- return;
- }
- struct dhcp_option_addr *val = optval;
-
- router = val->addr;
- have_router = 1;
- } break;
-
- case DHCP_OPTION_DOMAIN_NAME_SERVER: {
- if (opt_len % 4) {
- return;
- }
-
- int num_servers = opt_len / 4;
-
- int i;
- for (i = 0; i < num_servers && i < BDHCPCLIENTCORE_MAX_DOMAIN_NAME_SERVERS; i++) {
- domain_name_servers[i] = ((struct dhcp_option_addr *)optval + i)->addr;
- }
-
- domain_name_servers_count = i;
- } break;
- }
- }
-
- if (!have_end) {
- return;
- }
-
- if (dhcp_message_type == -1) {
- return;
- }
-
- if (dhcp_message_type != DHCP_MESSAGE_TYPE_OFFER && dhcp_message_type != DHCP_MESSAGE_TYPE_ACK && dhcp_message_type != DHCP_MESSAGE_TYPE_NAK) {
- return;
- }
-
- if (!have_dhcp_server_identifier) {
- return;
- }
-
- if (dhcp_message_type == DHCP_MESSAGE_TYPE_NAK) {
- if (o->state != STATE_SENT_REQUEST && o->state != STATE_FINISHED && o->state != STATE_RENEWING) {
- return;
- }
-
- if (dhcp_server_identifier != o->offered.dhcp_server_identifier) {
- return;
- }
-
- if (o->state == STATE_SENT_REQUEST) {
- BLog(BLOG_INFO, "received NAK (in sent request)");
-
- // stop request timer
- BReactor_RemoveTimer(o->reactor, &o->request_timer);
-
- // start reset timer
- BReactor_SetTimer(o->reactor, &o->reset_timer);
-
- // set state
- o->state = STATE_RESETTING;
- }
- else if (o->state == STATE_FINISHED) {
- BLog(BLOG_INFO, "received NAK (in finished)");
-
- // stop renew timer
- BReactor_RemoveTimer(o->reactor, &o->renew_timer);
-
- // start reset timer
- BReactor_SetTimer(o->reactor, &o->reset_timer);
-
- // set state
- o->state = STATE_RESETTING;
-
- // report to user
- report_down(o);
- return;
- }
- else { // STATE_RENEWING
- BLog(BLOG_INFO, "received NAK (in renewing)");
-
- // stop renew request timer
- BReactor_RemoveTimer(o->reactor, &o->renew_request_timer);
-
- // stop lease timer
- BReactor_RemoveTimer(o->reactor, &o->lease_timer);
-
- // start reset timer
- BReactor_SetTimer(o->reactor, &o->reset_timer);
-
- // set state
- o->state = STATE_RESETTING;
-
- // report to user
- report_down(o);
- return;
- }
-
- return;
- }
-
- if (ntoh32(o->recv_buf->yiaddr) == 0) {
- return;
- }
-
- if (!have_ip_address_lease_time) {
- return;
- }
-
- if (!have_subnet_mask) {
- return;
- }
-
- if (o->state == STATE_SENT_DISCOVER && dhcp_message_type == DHCP_MESSAGE_TYPE_OFFER) {
- BLog(BLOG_INFO, "received OFFER");
-
- // remember offer
- o->offered.yiaddr = o->recv_buf->yiaddr;
- o->offered.dhcp_server_identifier = dhcp_server_identifier;
-
- // send request
- send_message(o, DHCP_MESSAGE_TYPE_REQUEST, o->xid, 1, o->offered.yiaddr, 1, o->offered.dhcp_server_identifier);
-
- // stop reset timer
- BReactor_RemoveTimer(o->reactor, &o->reset_timer);
-
- // start request timer
- BReactor_SetTimer(o->reactor, &o->request_timer);
-
- // set state
- o->state = STATE_SENT_REQUEST;
-
- // set request count
- o->request_count = 1;
- }
- else if (o->state == STATE_SENT_REQUEST && dhcp_message_type == DHCP_MESSAGE_TYPE_ACK) {
- if (o->recv_buf->yiaddr != o->offered.yiaddr) {
- return;
- }
-
- if (dhcp_server_identifier != o->offered.dhcp_server_identifier) {
- return;
- }
-
- BLog(BLOG_INFO, "received ACK (in sent request)");
-
- // remember stuff
- o->acked.ip_address_lease_time = ip_address_lease_time;
- o->acked.subnet_mask = subnet_mask;
- o->acked.have_router = have_router;
- if (have_router) {
- o->acked.router = router;
- }
- o->acked.domain_name_servers_count = domain_name_servers_count;
- memcpy(o->acked.domain_name_servers, domain_name_servers, domain_name_servers_count * sizeof(uint32_t));
- o->func_getsendermac(o->user, o->acked.server_mac);
-
- // stop request timer
- BReactor_RemoveTimer(o->reactor, &o->request_timer);
-
- // start renew timer
- BReactor_SetTimerAfter(o->reactor, &o->renew_timer, RENEW_TIMEOUT(o->acked.ip_address_lease_time));
-
- // set state
- o->state = STATE_FINISHED;
-
- // report to user
- report_up(o);
- return;
- }
- else if (o->state == STATE_RENEWING && dhcp_message_type == DHCP_MESSAGE_TYPE_ACK) {
- if (o->recv_buf->yiaddr != o->offered.yiaddr) {
- return;
- }
-
- if (dhcp_server_identifier != o->offered.dhcp_server_identifier) {
- return;
- }
-
- // TODO: check parameters?
-
- BLog(BLOG_INFO, "received ACK (in renewing)");
-
- // remember stuff
- o->acked.ip_address_lease_time = ip_address_lease_time;
-
- // stop renew request timer
- BReactor_RemoveTimer(o->reactor, &o->renew_request_timer);
-
- // stop lease timer
- BReactor_RemoveTimer(o->reactor, &o->lease_timer);
-
- // start renew timer
- BReactor_SetTimerAfter(o->reactor, &o->renew_timer, RENEW_TIMEOUT(o->acked.ip_address_lease_time));
-
- // set state
- o->state = STATE_FINISHED;
- }
- }
- static void start_process (BDHCPClientCore *o, int force_new_xid)
- {
- if (force_new_xid || o->xid_reuse_counter == XID_REUSE_MAX) {
- // generate xid
- BRandom_randomize((uint8_t *)&o->xid, sizeof(o->xid));
-
- // reset counter
- o->xid_reuse_counter = 0;
- }
-
- // increment counter
- o->xid_reuse_counter++;
-
- // send discover
- send_message(o, DHCP_MESSAGE_TYPE_DISCOVER, o->xid, 0, 0, 0, 0);
-
- // set timer
- BReactor_SetTimer(o->reactor, &o->reset_timer);
-
- // set state
- o->state = STATE_SENT_DISCOVER;
- }
- static void reset_timer_handler (BDHCPClientCore *o)
- {
- ASSERT(o->state == STATE_RESETTING || o->state == STATE_SENT_DISCOVER)
- DebugObject_Access(&o->d_obj);
-
- BLog(BLOG_INFO, "reset timer");
-
- start_process(o, (o->state == STATE_RESETTING));
- }
- static void request_timer_handler (BDHCPClientCore *o)
- {
- ASSERT(o->state == STATE_SENT_REQUEST)
- ASSERT(o->request_count >= 1)
- ASSERT(o->request_count <= MAX_REQUESTS)
- DebugObject_Access(&o->d_obj);
-
- // if we have sent enough requests, start again
- if (o->request_count == MAX_REQUESTS) {
- BLog(BLOG_INFO, "request timer, aborting");
-
- start_process(o, 0);
- return;
- }
-
- BLog(BLOG_INFO, "request timer, retrying");
-
- // send request
- send_message(o, DHCP_MESSAGE_TYPE_REQUEST, o->xid, 1, o->offered.yiaddr, 1, o->offered.dhcp_server_identifier);
-
- // start request timer
- BReactor_SetTimer(o->reactor, &o->request_timer);
-
- // increment request count
- o->request_count++;
- }
- static void renew_timer_handler (BDHCPClientCore *o)
- {
- ASSERT(o->state == STATE_FINISHED)
- DebugObject_Access(&o->d_obj);
-
- BLog(BLOG_INFO, "renew timer");
-
- // send request
- send_message(o, DHCP_MESSAGE_TYPE_REQUEST, o->xid, 1, o->offered.yiaddr, 0, 0);
-
- // start renew request timer
- BReactor_SetTimer(o->reactor, &o->renew_request_timer);
-
- // start lease timer
- BReactor_SetTimerAfter(o->reactor, &o->lease_timer, LEASE_TIMEOUT(o->acked.ip_address_lease_time));
-
- // set state
- o->state = STATE_RENEWING;
- }
- static void renew_request_timer_handler (BDHCPClientCore *o)
- {
- ASSERT(o->state == STATE_RENEWING)
- DebugObject_Access(&o->d_obj);
-
- BLog(BLOG_INFO, "renew request timer");
-
- // send request
- send_message(o, DHCP_MESSAGE_TYPE_REQUEST, o->xid, 1, o->offered.yiaddr, 0, 0);
-
- // start renew request timer
- BReactor_SetTimer(o->reactor, &o->renew_request_timer);
- }
- static void lease_timer_handler (BDHCPClientCore *o)
- {
- ASSERT(o->state == STATE_RENEWING)
- DebugObject_Access(&o->d_obj);
-
- BLog(BLOG_INFO, "lease timer");
-
- // stop renew request timer
- BReactor_RemoveTimer(o->reactor, &o->renew_request_timer);
-
- // start again now
- start_process(o, 1);
-
- // report to user
- report_down(o);
- return;
- }
- static bsize_t maybe_len (const char *str)
- {
- return bsize_fromsize(str ? strlen(str) : 0);
- }
- int BDHCPClientCore_Init (BDHCPClientCore *o, PacketPassInterface *send_if, PacketRecvInterface *recv_if, uint8_t *client_mac_addr, struct BDHCPClientCore_opts opts, BReactor *reactor, void *user,
- BDHCPClientCore_func_getsendermac func_getsendermac,
- BDHCPClientCore_handler handler)
- {
- ASSERT(PacketPassInterface_GetMTU(send_if) == PacketRecvInterface_GetMTU(recv_if))
- ASSERT(PacketPassInterface_GetMTU(send_if) >= 576 - IP_UDP_HEADERS_SIZE)
- ASSERT(func_getsendermac)
- ASSERT(handler)
-
- // init arguments
- o->send_if = send_if;
- o->recv_if = recv_if;
- memcpy(o->client_mac_addr, client_mac_addr, sizeof(o->client_mac_addr));
- o->reactor = reactor;
- o->user = user;
- o->func_getsendermac = func_getsendermac;
- o->handler = handler;
-
- o->hostname = NULL;
- o->vendorclassid = NULL;
- o->clientid = NULL;
- o->clientid_len = 0;
-
- // copy options
- if (opts.hostname && !(o->hostname = strdup(opts.hostname))) {
- BLog(BLOG_ERROR, "strdup failed");
- goto fail0;
- }
- if (opts.vendorclassid && !(o->vendorclassid = strdup(opts.vendorclassid))) {
- BLog(BLOG_ERROR, "strdup failed");
- goto fail0;
- }
- if (opts.clientid) {
- if (!(o->clientid = BAlloc(opts.clientid_len))) {
- BLog(BLOG_ERROR, "BAlloc failed");
- goto fail0;
- }
- memcpy(o->clientid, opts.clientid, opts.clientid_len);
- o->clientid_len = opts.clientid_len;
- }
-
- // make sure options aren't too long
- bsize_t opts_size = bsize_add(maybe_len(o->hostname), bsize_add(maybe_len(o->vendorclassid), bsize_fromsize(o->clientid_len)));
- if (opts_size.is_overflow || opts_size.value > 100) {
- BLog(BLOG_ERROR, "options too long together");
- goto fail0;
- }
- if (o->hostname && strlen(o->hostname) > 255) {
- BLog(BLOG_ERROR, "hostname too long");
- goto fail0;
- }
- if (o->vendorclassid && strlen(o->vendorclassid) > 255) {
- BLog(BLOG_ERROR, "vendorclassid too long");
- goto fail0;
- }
- if (o->clientid && o->clientid_len > 255) {
- BLog(BLOG_ERROR, "clientid too long");
- goto fail0;
- }
-
- // allocate buffers
- if (!(o->send_buf = BAlloc(PacketPassInterface_GetMTU(send_if)))) {
- BLog(BLOG_ERROR, "BAlloc send buf failed");
- goto fail0;
- }
- if (!(o->recv_buf = BAlloc(PacketRecvInterface_GetMTU(recv_if)))) {
- BLog(BLOG_ERROR, "BAlloc recv buf failed");
- goto fail1;
- }
-
- // init send interface
- PacketPassInterface_Sender_Init(o->send_if, (PacketPassInterface_handler_done)send_handler_done, o);
-
- // init receive interface
- PacketRecvInterface_Receiver_Init(o->recv_if, (PacketRecvInterface_handler_done)recv_handler_done, o);
-
- // set not sending
- o->sending = 0;
-
- // init timers
- BTimer_Init(&o->reset_timer, RESET_TIMEOUT, (BTimer_handler)reset_timer_handler, o);
- BTimer_Init(&o->request_timer, REQUEST_TIMEOUT, (BTimer_handler)request_timer_handler, o);
- BTimer_Init(&o->renew_timer, 0, (BTimer_handler)renew_timer_handler, o);
- BTimer_Init(&o->renew_request_timer, RENEW_REQUEST_TIMEOUT, (BTimer_handler)renew_request_timer_handler, o);
- BTimer_Init(&o->lease_timer, 0, (BTimer_handler)lease_timer_handler, o);
-
- // start receving
- PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)o->recv_buf);
-
- // start
- start_process(o, 1);
-
- DebugObject_Init(&o->d_obj);
-
- return 1;
-
- fail1:
- BFree(o->send_buf);
- fail0:
- BFree(o->clientid);
- free(o->vendorclassid);
- free(o->hostname);
- return 0;
- }
- void BDHCPClientCore_Free (BDHCPClientCore *o)
- {
- DebugObject_Free(&o->d_obj);
-
- // free timers
- BReactor_RemoveTimer(o->reactor, &o->lease_timer);
- BReactor_RemoveTimer(o->reactor, &o->renew_request_timer);
- BReactor_RemoveTimer(o->reactor, &o->renew_timer);
- BReactor_RemoveTimer(o->reactor, &o->request_timer);
- BReactor_RemoveTimer(o->reactor, &o->reset_timer);
-
- // free buffers
- BFree(o->recv_buf);
- BFree(o->send_buf);
-
- // free options
- BFree(o->clientid);
- free(o->vendorclassid);
- free(o->hostname);
- }
- void BDHCPClientCore_GetClientIP (BDHCPClientCore *o, uint32_t *out_ip)
- {
- ASSERT(o->state == STATE_FINISHED || o->state == STATE_RENEWING)
- DebugObject_Access(&o->d_obj);
-
- *out_ip = o->offered.yiaddr;
- }
- void BDHCPClientCore_GetClientMask (BDHCPClientCore *o, uint32_t *out_mask)
- {
- ASSERT(o->state == STATE_FINISHED || o->state == STATE_RENEWING)
- DebugObject_Access(&o->d_obj);
-
- *out_mask = o->acked.subnet_mask;
- }
- int BDHCPClientCore_GetRouter (BDHCPClientCore *o, uint32_t *out_router)
- {
- ASSERT(o->state == STATE_FINISHED || o->state == STATE_RENEWING)
- DebugObject_Access(&o->d_obj);
-
- if (!o->acked.have_router) {
- return 0;
- }
-
- *out_router = o->acked.router;
- return 1;
- }
- int BDHCPClientCore_GetDNS (BDHCPClientCore *o, uint32_t *out_dns_servers, size_t max_dns_servers)
- {
- ASSERT(o->state == STATE_FINISHED || o->state == STATE_RENEWING)
- DebugObject_Access(&o->d_obj);
-
- int num_return = bmin_int(o->acked.domain_name_servers_count, max_dns_servers);
-
- memcpy(out_dns_servers, o->acked.domain_name_servers, num_return * sizeof(uint32_t));
- return num_return;
- }
- void BDHCPClientCore_GetServerMAC (BDHCPClientCore *o, uint8_t *out_mac)
- {
- DebugObject_Access(&o->d_obj);
- ASSERT(o->state == STATE_FINISHED || o->state == STATE_RENEWING)
-
- memcpy(out_mac, o->acked.server_mac, 6);
- }
|