diff options
Diffstat (limited to 'tinyNET/src/dhcp')
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp.c | 338 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp.h | 121 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp_message.c | 355 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp_message.h | 226 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp_option.c | 326 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp_option.h | 291 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp_option_sip.c | 131 | ||||
-rw-r--r-- | tinyNET/src/dhcp/tnet_dhcp_option_sip.h | 62 |
8 files changed, 1850 insertions, 0 deletions
diff --git a/tinyNET/src/dhcp/tnet_dhcp.c b/tinyNET/src/dhcp/tnet_dhcp.c new file mode 100644 index 0000000..8e7dbe6 --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp.c @@ -0,0 +1,338 @@ +/* +* Copyright (C) 2009-2010 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango.org> +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file tnet_dhcp.c + * @brief DHCP/BOOTP (RFC 2131 - Dynamic Host Configuration Protocol) utilities function for P-CSCF discovery(RFC 3319 and 3361). + * Also implement: RFC 3315, 3118, 3319, 3825 (Geoconf), 4676 (Civic Addresses Configuration Information) ... + * + * @author Mamadou Diop <diopmamadou(at)doubango.org> + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tnet_dhcp.h" + +#include "../tnet_endianness.h" + +#include "tsk_string.h" +#include "tsk_thread.h" +#include "tsk_memory.h" +#include "tsk_time.h" +#include "tsk_debug.h" + +#include <string.h> + +// Useful link: http://support.microsoft.com/?scid=kb%3Ben-us%3B169289&x=21&y=14 +// Another one: http://www.iana.org/assignments/bootp-dhcp-parameters/ +// Another one: http://www.slideshare.net/raini/DHCP-Presentation-v102 +// RFC 3319 Dynamic Host Configuration Protocol (DHCPv6) Options for Session Initiation Protocol (SIP) Servers +// RFC 3361 Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for Session Initiation Protocol (SIP) Servers + +/**@defgroup tnet_dhcp_group DHCPv4/BOOTP (RFC 2131) implementation. +*/ + +/**@ingroup tnet_dhcp_group +* Creates new DHCPv4 context. +*/ +tnet_dhcp_ctx_t* tnet_dhcp_ctx_create() +{ + return tsk_object_new(tnet_dhcp_ctx_def_t); +} + +/**@ingroup tnet_dhcp_group +* Creates new DHCPv4 parameters. +*/ +tnet_dhcp_params_t* tnet_dhcp_params_create() +{ + return tsk_object_new(tnet_dhcp_params_def_t); +} + +/* FIXME: USE retransmission mech (*2*2...) +*/ +/**@ingroup tnet_dhcp_group +*/ +tnet_dhcp_reply_t* tnet_dhcp_send_request(tnet_dhcp_ctx_t* ctx, tnet_dhcp_request_t* request) +{ + tsk_buffer_t *output; + tnet_dhcp_reply_t* reply = tsk_null; + int ret; + struct timeval tv; + fd_set set; + uint64_t timeout = 0; + tsk_list_item_t *item; + const tnet_interface_t *iface; + + tnet_socket_t *localsocket4 = tsk_null; + struct sockaddr_storage server; + + if(!ctx || !request){ + goto bail; + } + + localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, ctx->port_client, tnet_socket_type_udp_ipv4); + if(!TNET_SOCKET_IS_VALID(localsocket4)){ + TSK_DEBUG_ERROR("Failed to create/bind DHCP client socket."); + goto bail; + } + + /* Always wait for 200ms before retransmission */ + tv.tv_sec = 0; + tv.tv_usec = (200 * 1000); + + if(tnet_sockaddr_init("255.255.255.255", ctx->server_port, tnet_socket_type_udp_ipv4, &server)){ + TNET_PRINT_LAST_ERROR("Failed to initialize the DHCP server address"); + goto bail; + } + + /* ENABLE BROADCASTING */ + { +#if defined(SOLARIS) + char yes = '1'; +#else + int yes = 1; +#endif + if(setsockopt(localsocket4->fd, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(int))){ + TNET_PRINT_LAST_ERROR("Failed to enable broadcast option"); + goto bail; + } + } + + /* Set timeout */ + timeout = tsk_time_epoch() + ctx->timeout; + + do + { + /* RFC 2131 - 3.6 Use of DHCP in clients with multiple interfaces + A client with multiple network interfaces must use DHCP through each + interface independently to obtain configuration information + parameters for those separate interfaces. + */ + + tsk_list_foreach(item, ctx->interfaces){ + iface = item->data; + + /* Set FD */ + FD_ZERO(&set); + FD_SET(localsocket4->fd, &set); + + /* ciaddr */ + if(request->type == dhcp_type_inform){ + struct sockaddr_storage ss; + if(!tnet_get_sockaddr(localsocket4->fd, &ss)){ + uint32_t addr = tnet_htonl_2(&((struct sockaddr_in*)&ss)->sin_addr); + memcpy(&request->ciaddr, &addr, 4); + } + } + + /* chaddr */ + memset(request->chaddr, 0, sizeof(request->chaddr)); + request->hlen = iface->mac_address_length > sizeof(request->chaddr) ? sizeof(request->chaddr) : iface->mac_address_length; + memcpy(request->chaddr, iface->mac_address, request->hlen); + + /* Serialize and send to the server. */ + if(!(output = tnet_dhcp_message_serialize(ctx, request))){ + TSK_DEBUG_ERROR("Failed to serialize the DHCP message."); + goto next_iface; + } + /* Send the request to the DHCP server */ + if((ret =tnet_sockfd_sendto(localsocket4->fd, (const struct sockaddr*)&server, output->data, output->size))<0){ + TNET_PRINT_LAST_ERROR("Failed to send DHCP request"); + + tsk_thread_sleep(150); // wait 150ms before trying the next iface. + goto next_iface; + } + /* wait for response */ + if((ret = select(localsocket4->fd+1, &set, NULL, NULL, &tv))<0){ /* Error */ + TNET_PRINT_LAST_ERROR("select have failed."); + tsk_thread_sleep(150); // wait 150ms before trying the next iface. + goto next_iface; + } + else if(ret == 0) + { /* timeout ==> do nothing */ + } + else + { /* there is data to read */ + tsk_size_t len = 0; + void* data = tsk_null; + + /* Check how how many bytes are pending */ + if((ret = tnet_ioctlt(localsocket4->fd, FIONREAD, &len))<0){ + goto next_iface; + } + + /* Receive pending data */ + data = tsk_calloc(len, sizeof(uint8_t)); + if((ret = tnet_sockfd_recv(localsocket4->fd, data, len, 0))<0){ + TSK_FREE(data); + + TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams."); + goto next_iface; + } + + /* Parse the incoming response. */ + reply = tnet_dhcp_message_deserialize(ctx, data, (tsk_size_t)ret); + TSK_FREE(data); + + if(reply) + { /* response successfuly parsed */ + if(request->xid != reply->xid) + { /* Not same transaction id ==> continue*/ + TSK_OBJECT_SAFE_FREE(reply); + } + } + } + + next_iface: + TSK_OBJECT_SAFE_FREE(output); + if(reply){ + goto bail; + } + } + //break;//FIXME + } + while(timeout > tsk_time_epoch()); + +bail: + TSK_OBJECT_SAFE_FREE(localsocket4); + + return reply; +} + +/**@ingroup tnet_dhcp_group +*/ +tnet_dhcp_reply_t* tnet_dhcp_query(tnet_dhcp_ctx_t* ctx, tnet_dhcp_message_type_t type, tnet_dhcp_params_t* params) +{ + tnet_dhcp_reply_t* reply = tsk_null; + tnet_dhcp_request_t* request = tnet_dhcp_request_create(); + + if(!ctx || !params || !request){ + goto bail; + } + + request->type = type; + tnet_dhcp_message_add_codes(request, params->codes, params->codes_count); + + reply = tnet_dhcp_send_request(ctx, request); + +bail: + TSK_OBJECT_SAFE_FREE(request); + + return reply; +} + +/**@ingroup tnet_dhcp_group +*/ +int tnet_dhcp_params_add_code(tnet_dhcp_params_t* params, tnet_dhcp_option_code_t code) +{ + if(params){ + if(params->codes_count < TNET_DHCP_MAX_CODES){ + unsigned i; + for(i=0; i<params->codes_count; i++){ + if(params->codes[i] == code){ + return -3; + } + } + params->codes[params->codes_count++] = code; + } + else return -2; + } + return -1; +} + + + +//================================================================================================= +// [[DHCP CONTEXT]] object definition +// +static tsk_object_t* tnet_dhcp_ctx_ctor(tsk_object_t * self, va_list * app) +{ + tnet_dhcp_ctx_t *ctx = self; + if(ctx){ + tnet_host_t host; + + ctx->vendor_id = tsk_strdup(TNET_DHCP_VENDOR_ID_DEFAULT); + if(!tnet_gethostname(&host)){ + ctx->hostname = tsk_strndup(host, tsk_strlen(host)); + } + ctx->timeout = TNET_DHCP_TIMEOUT_DEFAULT; + ctx->max_msg_size = TNET_DHCP_MAX_MSG_SIZE; + ctx->port_client = TNET_DHCP_CLIENT_PORT; + ctx->server_port = TNET_DHCP_SERVER_PORT; + ctx->interfaces = tnet_get_interfaces(); + + if(!ctx->interfaces || TSK_LIST_IS_EMPTY(ctx->interfaces)){ + TSK_DEBUG_ERROR("Failed to retrieve network interfaces."); + } + + tsk_safeobj_init(ctx); + } + return self; +} + +static tsk_object_t* tnet_dhcp_ctx_dtor(tsk_object_t * self) +{ + tnet_dhcp_ctx_t *ctx = self; + if(ctx){ + tsk_safeobj_deinit(ctx); + + TSK_FREE(ctx->vendor_id); + TSK_FREE(ctx->hostname); + + TSK_OBJECT_SAFE_FREE(ctx->interfaces); + } + return self; +} + +static const tsk_object_def_t tnet_dhcp_ctx_def_s = +{ + sizeof(tnet_dhcp_ctx_t), + tnet_dhcp_ctx_ctor, + tnet_dhcp_ctx_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_dhcp_ctx_def_t = &tnet_dhcp_ctx_def_s; + +//================================================================================================= +// [[DHCP PARAMS]] object definition +// +static tsk_object_t* tnet_dhcp_params_ctor(tsk_object_t * self, va_list * app) +{ + tnet_dhcp_params_t *params = self; + if(params){ + } + return self; +} + +static tsk_object_t* tnet_dhcp_params_dtor(tsk_object_t * self) +{ + tnet_dhcp_params_t *params = self; + if(params){ + } + return self; +} + +static const tsk_object_def_t tnet_dhcp_params_def_s = +{ + sizeof(tnet_dhcp_params_t), + tnet_dhcp_params_ctor, + tnet_dhcp_params_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_dhcp_params_def_t = &tnet_dhcp_params_def_s; diff --git a/tinyNET/src/dhcp/tnet_dhcp.h b/tinyNET/src/dhcp/tnet_dhcp.h new file mode 100644 index 0000000..6b306c5 --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp.h @@ -0,0 +1,121 @@ +/* +* Copyright (C) 2009-2010 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango.org> +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file tnet_dhcp.h + * @brief DHCP (RFC 2131 - Dynamic Host Configuration Protocol) utilities function for P-CSCF discovery(RFC 3319 and 3361) + * Also implement: RFC 3315, 3118, 3319, 3825 (Geoconf), 4676 (Civic Addresses Configuration Information)... + * + * @author Mamadou Diop <diopmamadou(at)doubango.org> + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ + +#ifndef TNET_DHCP_H +#define TNET_DHCP_H + +#include "tinynet_config.h" + +#include "tnet_dhcp_message.h" + +#include "tnet_utils.h" + +#include "tsk_object.h" +#include "tsk_safeobj.h" + +TNET_BEGIN_DECLS + +/**@ingroup tnet_dhcp_group +* Default timeout (in milliseconds) value for DHCP requests. +*/ +#define TNET_DHCP_TIMEOUT_DEFAULT 2000 + +/**@ingroup tnet_dhcp_group +* Local port(client) to bind to for incoming DHCP messages as per RFC 2131 subclause 4.1. */ +#define TNET_DHCP_CLIENT_PORT 68 +/**@ingroup tnet_dhcp_group +* Destination port(Server) for outgoing DHCP messages as per RFC 2131 subclause 4.1. */ +#define TNET_DHCP_SERVER_PORT 67 + +/**@ingroup tnet_dhcp_group +* @def TNET_DHCP_VENDOR_ID_DEFAULT +*/ +/**@ingroup tnet_dhcp_group +* @def TNET_DHCP_MAX_CODES +*/ +/**@ingroup tnet_dhcp_group +* @def TNET_DHCP_MAX_MSG_SIZE +*/ +#define TNET_DHCP_VENDOR_ID_DEFAULT "doubango/v0.0.0" +#define TNET_DHCP_MAX_CODES 20 +#define TNET_DHCP_MAX_MSG_SIZE 1500 + +/**@ingroup tnet_dhcp_group +* Parameter Request List (55) +*/ +typedef struct tnet_dhcp_params_s +{ + TSK_DECLARE_OBJECT; + + tnet_dhcp_option_code_t codes[TNET_DHCP_MAX_CODES]; + unsigned codes_count; +} +tnet_dhcp_params_t; + +/**@ingroup tnet_dhcp_group +*/ +typedef struct tnet_dhcp_ctx_s +{ + TSK_DECLARE_OBJECT; + + char* vendor_id; + char* hostname; + uint16_t max_msg_size; /**< Option code 57. */ + + uint64_t timeout; + + tnet_port_t port_client; /**< Local port to bind to for incloming DHCP messages. Default: 68 */ + tnet_port_t server_port; /**< Destination port for outgoing DHCP messages. Default: 64 */ + tnet_interfaces_L_t *interfaces; + + TSK_DECLARE_SAFEOBJ; +} +tnet_dhcp_ctx_t; + + +TINYNET_API tnet_dhcp_reply_t* tnet_dhcp_query(tnet_dhcp_ctx_t* ctx, tnet_dhcp_message_type_t type, tnet_dhcp_params_t* params); +#define tnet_dhcp_query_discover(ctx, params) tnet_dhcp_query(ctx, dhcp_type_discover, params) +#define tnet_dhcp_query_request(ctx, params) tnet_dhcp_query(ctx, dhcp_type_request, params) +#define tnet_dhcp_query_decline(ctx, params) tnet_dhcp_query(ctx, dhcp_type_decline, params) +#define tnet_dhcp_query_release(ctx, params) tnet_dhcp_query(ctx, dhcp_type_release, params) +#define tnet_dhcp_query_inform(ctx, params) tnet_dhcp_query(ctx, dhcp_type_inform, params) + +TINYNET_API int tnet_dhcp_params_add_code(tnet_dhcp_params_t* params, tnet_dhcp_option_code_t code); + + +TINYNET_API tnet_dhcp_ctx_t* tnet_dhcp_ctx_create(); +TINYNET_API tnet_dhcp_params_t* tnet_dhcp_params_create(); + +TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_ctx_def_t; +TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_params_def_t; + +TNET_END_DECLS + +#endif /* TNET_DHCP_H */ diff --git a/tinyNET/src/dhcp/tnet_dhcp_message.c b/tinyNET/src/dhcp/tnet_dhcp_message.c new file mode 100644 index 0000000..e4eff3b --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp_message.c @@ -0,0 +1,355 @@ +/* +* Copyright (C) 2009-2010 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango.org> +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file tnet_dhcp_message.c + * @brief DHCP Message as per RFC 2131 subclause 2. + * + * @author Mamadou Diop <diopmamadou(at)doubango.org> + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tnet_dhcp_message.h" +#include "tnet_dhcp.h" + +#include "../tnet_utils.h" +#include "../tnet_endianness.h" + +#include "tsk_time.h" +#include "tsk_memory.h" +#include "tsk_string.h" +#include "tsk_debug.h" + +#include <string.h> + +tnet_dhcp_message_t* tnet_dhcp_message_create(tnet_dhcp_message_op_t opcode) +{ + return tsk_object_new(tnet_dhcp_message_def_t, opcode); +} + +tnet_dhcp_request_t* tnet_dhcp_request_create() +{ + return tnet_dhcp_message_create(dhcp_op_bootrequest); +} + +tnet_dhcp_message_t* tnet_dhcp_reply_create() +{ + return tnet_dhcp_message_create(dhcp_op_bootreply); +} + +tsk_buffer_t* tnet_dhcp_message_serialize(const tnet_dhcp_ctx_t *ctx, const tnet_dhcp_message_t *message) +{ + tsk_buffer_t* output = 0; + uint8_t _1byte; + uint16_t _2bytes; + uint32_t _4bytes; + + /* Check message validity */ + if(!message){ + goto bail; + } + + output = tsk_buffer_create_null(); + + /*== OP HTYPE HLEN HOPS */ + _4bytes = (((uint32_t)(message->op)) << 24) | + (((uint32_t)(message->htype)) << 16) | + (((uint16_t)(message->hlen)) << 8) | message->hops; + _4bytes = tnet_ntohl(_4bytes); + tsk_buffer_append(output, &(_4bytes), 4); + + /*== XID */ + _4bytes = tnet_ntohl(message->xid); + tsk_buffer_append(output, &(_4bytes), 4); + /*== SECS */ + _2bytes = tnet_ntohs(message->secs); + tsk_buffer_append(output, &(_2bytes), 2); + /*== FLAGS */ + _2bytes = tnet_ntohs(message->flags); + tsk_buffer_append(output, &(_2bytes), 2); + /*== CIADDR */ + _4bytes = tnet_ntohl(message->ciaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== YIADDR */ + _4bytes = tnet_ntohl(message->yiaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== SIADDR */ + _4bytes = tnet_ntohl(message->siaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== GIADDR */ + _4bytes = tnet_ntohl(message->giaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== CHADDR */ + tsk_buffer_append(output, message->chaddr, sizeof(message->chaddr)); + /*== sname (unused) */ + tsk_buffer_append(output, message->sname, sizeof(message->sname)); + /*== file (unused) */ + tsk_buffer_append(output, message->file, sizeof(message->file)); + /*== Magic Cookie */ + _4bytes = tnet_ntohl(TNET_DHCP_MAGIC_COOKIE); + tsk_buffer_append(output, &(_4bytes), 4); + + /*== Message Type (option 53) + */ + tnet_dhcp_option_serializeex(dhcp_code_DHCP_Msg_Type, 1, &message->type, output); + + /*== Client Identifier (option 61) ==> RFC 2132 - 9.14. Client-identifier + Code Len Type Client-Identifier + +-----+-----+-----+-----+-----+--- + | 61 | n | t1 | i1 | i2 | ... + +-----+-----+-----+-----+-----+--- + */ + if(message->hlen){ + uint8_t client_id[17]; // 16 /*sizeof(chaddr)*/+ 1/*htype*/ + /*if(client_id)*/{ + client_id[0] = message->htype; + memcpy(&client_id[1], message->chaddr, message->hlen); + tnet_dhcp_option_serializeex(dhcp_code_Client_Id, (message->hlen+1), client_id, output); + } + } + /*== Host name(10) ==> RFC 2132 - 3.14. Host Name Option + Code Len Host Name + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 12 | n | h1 | h2 | h3 | h4 | h5 | h6 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + */ + if(TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->hostname){ + tnet_dhcp_option_serializeex(dhcp_code_Hostname, tsk_strlen(ctx->hostname), ctx->hostname, output); + } + /*== Vendor classId(60) ==> RFC 2132 - 9.13. Vendor class identifier + Code Len Vendor class Identifier + +-----+-----+-----+-----+--- + | 60 | n | i1 | i2 | ... + +-----+-----+-----+-----+--- + */ + if(TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->vendor_id){ + tnet_dhcp_option_serializeex(dhcp_code_Class_Id, tsk_strlen(ctx->vendor_id), ctx->vendor_id, output); + } + + /*== RFC 2132 - 9.10. Maximum DHCP Message Size (57) + Code Len Length + +-----+-----+-----+-----+ + | 57 | 2 | l1 | l2 | + +-----+-----+-----+-----+ + */ + if(TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->max_msg_size){ + _2bytes = tnet_ntohs(ctx->max_msg_size); + tnet_dhcp_option_serializeex(dhcp_code_DHCP_Max_Msg_Size, 2, &_2bytes, output); + } + + /*== DHCP Options + */ + { + tsk_list_item_t *item; + tnet_dhcp_option_t* option; + tsk_list_foreach(item, message->options) + { + option = (tnet_dhcp_option_t*)item->data; + if(tnet_dhcp_option_serialize(option, output)){ + TSK_DEBUG_WARN("Failed to serialize DHCP OPTION (%u)", option->code); + } + } + } + + /* RFC 2131 - 4.1 Constructing and sending DHCP messages + The last option must always be the 'end' option. + */ + _1byte = dhcp_code_End; + tsk_buffer_append(output, &(_1byte), 1); + +bail: + return output; +} + +tnet_dhcp_message_t* tnet_dhcp_message_deserialize(const struct tnet_dhcp_ctx_s *ctx, const uint8_t *data, tsk_size_t size) +{ + tnet_dhcp_message_t *message = 0; + uint8_t *dataPtr, *dataEnd, *dataStart; + + if(!data || !size) + { + goto bail; + } + + if(size < TNET_DHCP_MESSAGE_MIN_SIZE){ + TSK_DEBUG_ERROR("DHCP message too short."); + goto bail; + } + + if(!(message = tnet_dhcp_reply_create())){ /* If REQUEST OP will be overridedden */ + TSK_DEBUG_ERROR("Failed to create new DHCP message."); + goto bail; + } + + dataPtr = (uint8_t*)data; + dataStart = dataPtr; + dataEnd = (dataStart + size); + + /*== op (1)*/ + message->op = *(dataPtr++); + /*== htype (1) */ + message->htype = *(dataPtr++); + /*== hlen (1) */ + message->hlen = *(dataPtr++); + /*== htype (1) */ + message->hops = *(dataPtr++); + /*== xid (4) */ + message->xid= tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== secs (2) */ + message->secs = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /*== flags (2) */ + message->flags = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /*== ciaddr (4) */ + message->ciaddr= tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== yiaddr (4) */ + message->yiaddr= tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== siaddr (4) */ + message->siaddr= tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== giaddr (4) */ + message->giaddr= tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== chaddr (16[max]) */ + memcpy(message->chaddr, dataPtr, message->hlen>16 ? 16 : message->hlen); + dataPtr += 16; + /*== sname (64) */ + memcpy(message->sname, dataPtr, 64); + dataPtr += 64; + /*== file (128) */ + memcpy(message->file, dataPtr, 128); + dataPtr += 128; + /*== Magic Cookie (4) */ + if(tnet_htonl_2(dataPtr) != TNET_DHCP_MAGIC_COOKIE){ + TSK_DEBUG_ERROR("Invalid DHCP magic cookie."); + // Do not exit ==> continue parsing. + } + dataPtr += 4; + + /*== options (variable) */ + while(dataPtr<dataEnd && *dataPtr!=dhcp_code_End) + { + tnet_dhcp_option_t* option = tnet_dhcp_option_deserialize(dataPtr, (dataEnd-dataPtr)); + if(option && option->value){ + + if(option->code == dhcp_code_DHCP_Msg_Type){ + message->type = (tnet_dhcp_message_type_t)*TSK_BUFFER_TO_U8(option->value); + } + + dataPtr += option->value->size + 2/*Code Len*/; + tsk_list_push_back_data(message->options, (void**)&option); + } + else break; + } + +bail: + return message; +} + + +const tnet_dhcp_option_t* tnet_dhcp_message_find_option(const tnet_dhcp_message_t *message, tnet_dhcp_option_code_t code) +{ + tsk_list_item_t *item; + + if(!message){ + goto bail; + } + + tsk_list_foreach(item, message->options) + { + if(((tnet_dhcp_option_t*)item->data)->code == code){ + return ((tnet_dhcp_option_t*)item->data); + } + } + +bail: + return 0; +} + +int tnet_dhcp_message_add_codes(tnet_dhcp_message_t *self, tnet_dhcp_option_code_t codes[], unsigned codes_count) +{ + int ret = -1; + + if(!self){ + goto bail; + } + if(codes_count){ + unsigned i; + + tnet_dhcp_option_paramslist_t* option = (tnet_dhcp_option_paramslist_t*)tnet_dhcp_message_find_option(self, dhcp_code_Parameter_List); + if(!option){ + tnet_dhcp_option_paramslist_t *option_paramslist = tnet_dhcp_option_paramslist_create(); + option = option_paramslist; + tsk_list_push_back_data(self->options, (void**)&option_paramslist); + } + + for(i=0; i<codes_count; i++){ + if((ret = tnet_dhcp_option_paramslist_add_code(option, codes[i]))){ + break; + } + } + } + +bail: + return ret; +} + + +//================================================================================================= +// [[DHCP MESSAGE]] object definition +// +static tsk_object_t* tnet_dhcp_message_ctor(tsk_object_t * self, va_list * app) +{ + tnet_dhcp_message_t *message = self; + if(message){ + static uint32_t __dhcpmessage_unique_xid = 0;//(uint32_t)tsk_time_epoch(); + + message->op = va_arg(*app, tnet_dhcp_message_op_t); + message->htype = tnet_htype_Ethernet_10Mb; + message->hlen = 0x06; + + message->xid = ++(__dhcpmessage_unique_xid); + message->options = tsk_list_create(); + } + return self; +} + +static tsk_object_t* tnet_dhcp_message_dtor(tsk_object_t * self) +{ + tnet_dhcp_message_t *message = self; + if(message){ + TSK_OBJECT_SAFE_FREE(message->options); + } + return self; +} + +static const tsk_object_def_t tnet_dhcp_message_def_s = +{ + sizeof(tnet_dhcp_message_t), + tnet_dhcp_message_ctor, + tnet_dhcp_message_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_dhcp_message_def_t = &tnet_dhcp_message_def_s; + diff --git a/tinyNET/src/dhcp/tnet_dhcp_message.h b/tinyNET/src/dhcp/tnet_dhcp_message.h new file mode 100644 index 0000000..4101e9b --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp_message.h @@ -0,0 +1,226 @@ +/* +* Copyright (C) 2009-2010 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango.org> +* +* This file is part of Open Source Doubango Framework. +* +* DOUBANGO is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* DOUBANGO is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with DOUBANGO. +* +*/ +/**@file tnet_dhcp_message.h + * @brief DHCP Message as per RFC 2131 subclause 2. + * + * @author Mamadou Diop <diopmamadou(at)doubango.org> + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ + +#ifndef TNET_DHCP_MESSAGE_H +#define TNET_DHCP_MESSAGE_H + +#include "tinynet_config.h" + +#include "tnet_dhcp_option.h" +#include "tnet_hardwares.h" + +#include "tsk_buffer.h" + +TNET_BEGIN_DECLS + +struct tnet_dhcp_ctx_s; + +#define TNET_DHCP_MESSAGE_IS_REQUEST(self) ((self) && ((self)->op==dhcp_op_bootrequest)) +#define TNET_DHCP_MESSAGE_IS_REPLY(self) ((self) && ((self)->op==dhcp_op_bootreply)) + +#define TNET_DHCP_MAGIC_COOKIE 0x63825363 /**< DHCP magic cookie (99, 130, 83 and 99 in decimal).*/ + +#define TNET_DHCP_MESSAGE_MIN_SIZE 223 /* Is it rigth? */ + +/** List of all supported DHCP message (see RFC 2131). +*/ +typedef enum tnet_dhcp_message_type_e +{ + /**< DHCPDISCOVER - Client broadcast to locate available servers. + */ + dhcp_type_discover = 1, + + /**< DHCPOFFER - Server to client in response to DHCPDISCOVER with + offer of configuration parameters. + */ + dhcp_type_offer = 2, + + /**< DHCPREQUEST - Client message to servers either (a) requesting + offered parameters from one server and implicitly + declining offers from all others, (b) confirming + correctness of previously allocated address after, + e.g., system reboot, or (c) extending the lease on a + particular network address. + */ + dhcp_type_request = 3, + + /**< DHCPDECLINE - Client to server indicating network address is already + in use. + */ + dhcp_type_decline = 4, + + /**< DHCPACK - Server to client with configuration parameters, + including committed network address. + */ + dhcp_type_ack = 5, + + /**< DHCPNAK - Server to client indicating client's notion of network + address is incorrect (e.g., client has moved to new + subnet) or client's lease as expired + */ + dhcp_type_nack = 6, + + /**< DHCPRELEASE - Client to server relinquishing network address and + cancelling remaining lease. + */ + dhcp_type_release = 7, + + /**< DHCPINFORM - Client to server, asking only for local configuration + parameters; client already has externally configured + network address. + */ + dhcp_type_inform = 8, +} +tnet_dhcp_message_type_t; + +/** DHCP message OP code / message type. +*/ +typedef enum tnet_dhcp_message_op_e +{ + dhcp_op_bootrequest = 1, + dhcp_op_bootreply = 2 +} +tnet_dhcp_message_op_t; + +/** BOOTP/DHCP message as per RFC 2131 subclause 2. +*/ +typedef struct tnet_dhcp_message_s +{ + TSK_DECLARE_OBJECT; + + /**< DHCP message type. Mandatory. + */ + tnet_dhcp_message_type_t type; + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | op (1) | htype (1) | hlen (1) | hops (1) | + +---------------+---------------+---------------+---------------+ + | xid (4) | + +-------------------------------+-------------------------------+ + | secs (2) | flags (2) | + +-------------------------------+-------------------------------+ + | ciaddr (4) | + +---------------------------------------------------------------+ + | yiaddr (4) | + +---------------------------------------------------------------+ + | siaddr (4) | + +---------------------------------------------------------------+ + | giaddr (4) | + +---------------------------------------------------------------+ + | | + | chaddr (16) | + | | + | | + +---------------------------------------------------------------+ + | | + | sname (64) | + +---------------------------------------------------------------+ + | | + | file (128) | + +---------------------------------------------------------------+ + | | + | options (variable) | + +---------------------------------------------------------------+ + */ + + /**< Message op code / message type (1-byte). + 1 = BOOTREQUEST, 2 = BOOTREPLY + */ + tnet_dhcp_message_op_t op; + /**< Hardware address type, see ARP section in "Assigned Numbers" RFC; e.g., '1' = 10mb ethernet. + For more information see RFC 1340. + */ + tnet_hardware_type_t htype; + /**< Hardware address length (e.g. '6' for 10mb ethernet). tsk_strlen(chaddr). + */ + uint8_t hlen; + /**< Client sets to zero, optionally used by relay agents when booting via a relay agent. + */ + uint8_t hops; + /**< Transaction ID, a random number chosen by the client, used by the client + and server to associate messages and responses between a client and a server. + */ + uint32_t xid; + /**< Filled in by client, seconds elapsed since client began address acquisition or renewal process. + */ + uint16_t secs; + /**< Flags (see figure 2) + */ + uint16_t flags; + /**< Client IP address; only filled in if client is in BOUND, RENEW or REBINDING + state and can respond to ARP requests. + */ + uint32_t ciaddr; + /**< 'your' (client) IP address. + */ + uint32_t yiaddr; + /**< IP address of next server to use in bootstrap; + returned in DHCPOFFER, DHCPACK by server. + */ + uint32_t siaddr; + /**< Relay agent IP address, used in booting via a relay agent. + */ + uint32_t giaddr; + /**< Client hardware address. + */ + uint8_t chaddr[16]; + /**< Optional server host name, null terminated string. + */ + uint8_t sname[64]; + /**<Boot file name, null terminated string; "generic" name or null in DHCPDISCOVER, + fully qualifieddirectory-path name in DHCPOFFER. + */ + uint8_t file[128]; + /**Optional parameters field. See the options documents for a list of defined options. + For more information please refer to RFC 2132, 1497 and 1533. + */ + tnet_dhcp_options_L_t *options; +} +tnet_dhcp_message_t; + +typedef tsk_list_t tnet_dhcp_messages_L_t; +typedef tnet_dhcp_message_t tnet_dhcp_request_t; /**< BOOTREQUEST message. */ +typedef tnet_dhcp_message_t tnet_dhcp_reply_t; /**< BOOTREPLY message. */ + +tsk_buffer_t* tnet_dhcp_message_serialize(const struct tnet_dhcp_ctx_s *ctx, const tnet_dhcp_message_t *self); +tnet_dhcp_message_t* tnet_dhcp_message_deserialize(const struct tnet_dhcp_ctx_s *ctx, const uint8_t *data, tsk_size_t size); +const tnet_dhcp_option_t* tnet_dhcp_message_find_option(const tnet_dhcp_message_t *self, tnet_dhcp_option_code_t code); +int tnet_dhcp_message_add_codes(tnet_dhcp_message_t *self, tnet_dhcp_option_code_t codes[], unsigned codes_count); + +TINYNET_API tnet_dhcp_message_t* tnet_dhcp_message_create(tnet_dhcp_message_op_t opcode); +TINYNET_API tnet_dhcp_request_t* tnet_dhcp_request_create(); +TINYNET_API tnet_dhcp_message_t* tnet_dhcp_reply_create(); + +TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_message_def_t; + +TNET_END_DECLS + +#endif /* TNET_DHCP_MESSAGE_H */ diff --git a/tinyNET/src/dhcp/tnet_dhcp_option.c b/tinyNET/src/dhcp/tnet_dhcp_option.c new file mode 100644 index 0000000..39a28e9 --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp_option.c @@ -0,0 +1,326 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+/**@file tnet_dhcp_option.c
+ * @brief DHCP Options and BOOTP Vendor Extensions as per RFC 2132.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dhcp_option.h"
+
+#include "tnet_dhcp_option_sip.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+tnet_dhcp_option_t* tnet_dhcp_option_create(tnet_dhcp_option_code_t code)
+{
+ return tsk_object_new(tnet_dhcp_option_def_t, code);
+}
+
+tnet_dhcp_option_paramslist_t* tnet_dhcp_option_paramslist_create()
+{
+ return tsk_object_new(tnet_dhcp_option_paramslist_def_t);
+}
+
+tnet_dhcp_option_dns_t* tnet_dhcp_option_dns_create(const void* payload, tsk_size_t payload_size)
+{
+ return tsk_object_new(tnet_dhcp_option_dns_def_t, payload, payload_size);
+}
+
+/** Initializes DHCPv4 option.
+ *
+ * @param [in,out] self The option to initialize.
+ * @param code The code of the option to initialize.
+ *
+ * @return Zero if succeed and non-zero error code otherwise.
+**/
+int tnet_dhcp_option_init(tnet_dhcp_option_t *self, tnet_dhcp_option_code_t code)
+{
+ if(self)
+ {
+ if(!self->initialized)
+ {
+ self->code = code;
+ //option->value = tsk_buffer_create_null();
+
+ self->initialized = tsk_true;
+ return 0;
+ }
+ return -2;
+ }
+ return -1;
+}
+
+int tnet_dhcp_option_deinit(tnet_dhcp_option_t *self)
+{
+ if(self)
+ {
+ if(self->initialized)
+ {
+ TSK_OBJECT_SAFE_FREE(self->value);
+
+ self->initialized = tsk_false;
+ return 0;
+ }
+ return -2;
+ }
+ return -1;
+}
+
+tnet_dhcp_option_t* tnet_dhcp_option_deserialize(const void* data, tsk_size_t size)
+{
+ tnet_dhcp_option_t *option = 0;
+ uint8_t* dataPtr = ((uint8_t*)data);
+ //uint8_t* dataEnd = (dataPtr+size);
+
+ tnet_dhcp_option_code_t code;
+ uint8_t len;
+
+ /* Check validity */
+ if(!dataPtr || size<2/*Code Len*/){
+ goto bail;
+ }
+
+ code = (tnet_dhcp_option_code_t)*dataPtr++;
+ len = *dataPtr++;
+
+ switch(code)
+ {
+ case dhcp_code_SIP_Servers_DHCP_Option:
+ {
+ option = (tnet_dhcp_option_t *)tnet_dhcp_option_sip_create(dataPtr, len);
+ break;
+ }
+
+ case dhcp_code_Domain_Server:
+ {
+ option = (tnet_dhcp_option_t *)tnet_dhcp_option_dns_create(dataPtr, len);
+ break;
+ }
+
+ default:
+ {
+ option = tnet_dhcp_option_create(code);
+ }
+ }
+
+ /* In all case */
+ if(option && !option->value && len){
+ option->value = tsk_buffer_create((((uint8_t*)data) + 2/*Code Len*/), len);
+ }
+
+bail:
+ return option;
+}
+
+int tnet_dhcp_option_serialize(const tnet_dhcp_option_t* self, tsk_buffer_t *output)
+{
+ if(!self || !output){
+ return -1;
+ }
+
+ /* Code */
+ tsk_buffer_append(output, &(self->code), 1);
+
+ if(self->value){
+ /* Length */
+ tsk_buffer_append(output, &(self->value->size), 1);
+
+ /* Value */
+ tsk_buffer_append(output, self->value->data, self->value->size);
+ }
+ else{
+ /* Length */
+ static uint8_t zero = 0x00;
+ tsk_buffer_append(output, &zero, 1);
+ }
+
+ return 0;
+}
+
+int tnet_dhcp_option_serializeex(tnet_dhcp_option_code_t code, uint8_t length, const void* value, tsk_buffer_t *output)
+{
+ if(value && length && output){
+ tsk_buffer_append(output, &(code), 1);
+ tsk_buffer_append(output, &(length), 1);
+ tsk_buffer_append(output, value, length);
+
+ return 0;
+ }
+ return -1;
+}
+
+//
+// [[DHCP OPTION]] object definition
+//
+static tsk_object_t* tnet_dhcp_option_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dhcp_option_t *option = self;
+ if(option){
+ tnet_dhcp_option_init(option, va_arg(*app, tnet_dhcp_option_code_t));
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dhcp_option_dtor(tsk_object_t * self)
+{
+ tnet_dhcp_option_t *option = self;
+ if(option){
+ tnet_dhcp_option_deinit(option);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dhcp_option_def_s =
+{
+ sizeof(tnet_dhcp_option_t),
+ tnet_dhcp_option_ctor,
+ tnet_dhcp_option_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dhcp_option_def_t = &tnet_dhcp_option_def_s;
+
+
+
+/*=======================================================================================
+* RFC 2132 - 9.8. Parameter Request List
+*=======================================================================================*/
+int tnet_dhcp_option_paramslist_add_code(tnet_dhcp_option_paramslist_t* self, tnet_dhcp_option_code_t code)
+{
+ if(self){
+ if(!TNET_DHCP_OPTION(self)->value){
+ TNET_DHCP_OPTION(self)->value = tsk_buffer_create_null();
+ }
+ return tsk_buffer_append(TNET_DHCP_OPTION(self)->value, &code, 1);
+ }
+ return -1;
+}
+
+//
+// [[DHCP OPTION - RFC 2132 9.8. Parameter Request List]] object definition
+//
+static tsk_object_t* tnet_dhcp_option_paramslist_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dhcp_option_paramslist_t *option = self;
+ if(option){
+ /* init base */
+ tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Parameter_List);
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dhcp_option_paramslist_dtor(tsk_object_t * self)
+{
+ tnet_dhcp_option_paramslist_t *option = self;
+ if(option){
+ /* deinit base */
+ tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option));
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dhcp_option_paramslist_def_s =
+{
+ sizeof(tnet_dhcp_option_paramslist_t),
+ tnet_dhcp_option_paramslist_ctor,
+ tnet_dhcp_option_paramslist_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dhcp_option_paramslist_def_t = &tnet_dhcp_option_paramslist_def_s;
+
+
+/*=======================================================================================
+* RFC 2132 - 3.8. Domain Name Server Option
+*=======================================================================================*/
+//
+// [[DHCP OPTION - RFC 2132 3.8. Domain Name Server Option]] object definition
+//
+static tsk_object_t* tnet_dhcp_option_dns_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dhcp_option_dns_t *option = self;
+ if(option){
+ const void* payload = va_arg(*app, const void*);
+ tsk_size_t payload_size = va_arg(*app, tsk_size_t);
+
+ const uint8_t* payloadPtr = (const uint8_t*)payload;
+ const uint8_t* payloadEnd = (payloadPtr + payload_size);
+
+ /* init base */
+ tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Domain_Server);
+
+ option->servers = tsk_list_create();
+
+ if(payload_size<4 || payload_size%4){
+ TSK_DEBUG_ERROR("DHCP - The minimum length for this option is 4 octets, and the length MUST always be a multiple of 4.");
+ }
+ else{
+ tsk_size_t i;
+ char* ip4 = 0;
+ uint32_t address;
+ tsk_string_t* addrstring;
+
+ for(i=0; i<payload_size && (payloadPtr< payloadEnd); i+=4){
+ /*
+ Code Len Address 1 Address 2
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ...
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ */
+ address = tnet_htonl_2(payloadPtr);
+ tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF);
+
+ addrstring = tsk_string_create(ip4);
+ tsk_list_push_back_data(option->servers, (void*)&addrstring);
+
+ TSK_FREE(ip4);
+ payloadPtr+= 4;
+ }
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dhcp_option_dns_dtor(tsk_object_t * self)
+{
+ tnet_dhcp_option_dns_t *option = self;
+ if(option){
+ /* deinit base */
+ tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option));
+
+ TSK_OBJECT_SAFE_FREE(option->servers);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dhcp_option_dns_def_s =
+{
+ sizeof(tnet_dhcp_option_dns_t),
+ tnet_dhcp_option_dns_ctor,
+ tnet_dhcp_option_dns_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dhcp_option_dns_def_t = &tnet_dhcp_option_dns_def_s;
diff --git a/tinyNET/src/dhcp/tnet_dhcp_option.h b/tinyNET/src/dhcp/tnet_dhcp_option.h new file mode 100644 index 0000000..b9c313e --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp_option.h @@ -0,0 +1,291 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+/**@file tnet_dhcp_option.h
+ * @brief DHCP Options and BOOTP Vendor Extensions as per RFC 2132.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef TNET_DHCP_OPTION_H
+#define TNET_DHCP_OPTION_H
+
+#include "tinynet_config.h"
+
+#include "tsk_buffer.h"
+#include "tsk_string.h"
+
+TNET_BEGIN_DECLS
+
+#define TNET_DHCP_OPTION(self) ((tnet_dhcp_option_t*)(self))
+
+typedef enum tnet_dhcp_option_code_e
+{
+ dhcp_code_Pad= 0 ,/**< Pad 0 None [RFC2132] */
+ dhcp_code_Subnet_Mask= 1 ,/**< Subnet Mask 4 Subnet Mask Value [RFC2132] */
+ dhcp_code_Time_Offset= 2 ,/**< Time Offset 4 Time Offset in Seconds from UTC [RFC2132] (note: deprecated by 100 and 101) */
+ dhcp_code_Router= 3 ,/**< Router N N/4 Router addresses [RFC2132] */
+ dhcp_code_Time_Server= 4 ,/**< Time Server N N/4 Timeserver addresses [RFC2132] */
+ dhcp_code_Name_Server= 5 ,/**< Name Server N N/4 IEN-116 Server addresses [RFC2132] */
+ dhcp_code_Domain_Server= 6 ,/**< Domain Server N N/4 DNS Server addresses [RFC2132] */
+ dhcp_code_Log_Server= 7 ,/**< Log Server N N/4 Logging Server addresses [RFC2132] */
+ dhcp_code_Quotes_Server= 8 ,/**< Quotes Server N N/4 Quotes Server addresses [RFC2132] */
+ dhcp_code_LPR_Server= 9 ,/**< LPR Server N N/4 Printer Server addresses [RFC2132] */
+ dhcp_code_Impress_Server= 10 ,/**< Impress Server N N/4 Impress Server addresses [RFC2132] */
+ dhcp_code_RLP_Server= 11 ,/**< RLP Server N N/4 RLP Server addresses [RFC2132] */
+ dhcp_code_Hostname= 12 ,/**< Hostname N Hostname string [RFC2132] */
+ dhcp_code_Boot_File_Size= 13 ,/**< Boot File Size 2 Size of boot file in 512 byte chunks [RFC2132] */
+ dhcp_code_Merit_Dump_File= 14 ,/**< Merit Dump File N Client to dump and name the file to dump it to [RFC2132] */
+ dhcp_code_Domain_Name= 15 ,/**< Domain Name N The DNS domain name of the client [RFC2132] */
+ dhcp_code_Swap_Server= 16 ,/**< Swap Server N Swap Server address [RFC2132] */
+ dhcp_code_Root_Path= 17 ,/**< Root Path N Path name for root disk [RFC2132] */
+ dhcp_code_Extension_File= 18 ,/**< Extension File N Path name for more BOOTP info [RFC2132] */
+ dhcp_code_Forward_On_Off= 19 ,/**< Forward On/Off 1 Enable/Disable IP Forwarding [RFC2132] */
+ dhcp_code_SrcRte_On_Off = 20 ,/**< SrcRte On/Off 1 Enable/Disable Source Routing [RFC2132] */
+ dhcp_code_Policy_Filter= 21 ,/**< Policy Filter N Routing Policy Filters [RFC2132] */
+ dhcp_code_Max_DG_Assembly= 22 ,/**< Max DG Assembly 2 Max Datagram Reassembly Size [RFC2132] */
+ dhcp_code_Default_IP_TTL= 23 ,/**< Default IP TTL 1 Default IP Time to Live [RFC2132] */
+ dhcp_code_MTU_Timeout= 24 ,/**< MTU Timeout 4 Path MTU Aging Timeout [RFC2132] */
+ dhcp_code_MTU_Plateau= 25 ,/**< MTU Plateau N Path MTU Plateau Table [RFC2132] */
+ dhcp_code_MTU_Interface= 26 ,/**< MTU Interface 2 Interface MTU Size [RFC2132] */
+ dhcp_code_MTU_Subnet= 27 ,/**< MTU Subnet 1 All Subnets are Local [RFC2132] */
+ dhcp_code_Broadcast_Address= 28 ,/**< Broadcast Address 4 Broadcast Address [RFC2132] */
+ dhcp_code_Mask_Discovery= 29 ,/**< Mask Discovery 1 Perform Mask Discovery [RFC2132] */
+ dhcp_code_Mask_Supplier= 30 ,/**< Mask Supplier 1 Provide Mask to Others [RFC2132] */
+ dhcp_code_Router_Discovery= 31 ,/**< Router Discovery 1 Perform Router Discovery [RFC2132] */
+ dhcp_code_Router_Request= 32 ,/**< Router Request 4 Router Solicitation Address [RFC2132] */
+ dhcp_code_Static_Route= 33 ,/**< Static Route N Static Routing Table [RFC2132] */
+ dhcp_code_Trailers= 34 ,/**< Trailers 1 Trailer Encapsulation [RFC2132] */
+ dhcp_code_ARP_Timeout= 35 ,/**< ARP Timeout 4 ARP Cache Timeout [RFC2132] */
+ dhcp_code_Ethernet= 36 ,/**< Ethernet 1 Ethernet Encapsulation [RFC2132] */
+ dhcp_code_Default_TCP_TTL= 37 ,/**< Default TCP TTL 1 Default TCP Time to Live [RFC2132] */
+ dhcp_code_Keepalive_Time= 38 ,/**< Keepalive Time 4 TCP Keepalive Interval [RFC2132] */
+ dhcp_code_Keepalive_Data= 39 ,/**< Keepalive Data 1 TCP Keepalive Garbage [RFC2132] */
+ dhcp_code_NIS_Domain= 40 ,/**< NIS Domain N NIS Domain Name [RFC2132] */
+ dhcp_code_NIS_Servers= 41 ,/**< NIS Servers N NIS Server Addresses [RFC2132] */
+ dhcp_code_NTP_Servers= 42 ,/**< NTP Servers N NTP Server Addresses [RFC2132] */
+ dhcp_code_Vendor_Specific= 43 ,/**< Vendor Specific N Vendor Specific Information [RFC2132] */
+ dhcp_code_NETBIOS_Name_Srv= 44 ,/**< NETBIOS Name Srv N NETBIOS Name Servers [RFC2132] */
+ dhcp_code_NETBIOS_Dist_Srv= 45 ,/**< NETBIOS Dist Srv N NETBIOS Datagram Distribution [RFC2132] */
+ dhcp_code_NETBIOS_Node_Type= 46 ,/**< NETBIOS Node Type 1 NETBIOS Node Type [RFC2132] */
+ dhcp_code_NETBIOS_Scope= 47 ,/**< NETBIOS Scope N NETBIOS Scope [RFC2132] */
+ dhcp_code_X_Window_Font= 48 ,/**< X Window Font N X Window Font Server [RFC2132] */
+ dhcp_code_X_Window_Manager= 49 ,/**< X Window Manager N X Window Display Manager [RFC2132] */
+ dhcp_code_Address_Request= 50 ,/**< Address Request 4 Requested IP Address [RFC2132] */
+ dhcp_code_Address_Time= 51 ,/**< Address Time 4 IP Address Lease Time [RFC2132] */
+ dhcp_code_Overload= 52 ,/**< Overload 1 Overload "sname" or "file" [RFC2132] */
+ dhcp_code_DHCP_Msg_Type= 53 ,/**< DHCP Msg Type 1 DHCP Message Type [RFC2132] */
+ dhcp_code_DHCP_Server_Id= 54 ,/**< DHCP Server Id 4 DHCP Server Identification [RFC2132] */
+ dhcp_code_Parameter_List= 55 ,/**< Parameter List N Parameter Request List [RFC2132] */
+ dhcp_code_DHCP_Error_Message= 56 ,/**< DHCP Message N DHCP Error Message [RFC2132] */
+ dhcp_code_DHCP_Max_Msg_Size= 57 ,/**< DHCP Max Msg Size 2 DHCP Maximum Message Size [RFC2132] */
+ dhcp_code_Renewal_Time= 58 ,/**< Renewal Time 4 DHCP Renewal (T1) Time [RFC2132] */
+ dhcp_code_Rebinding_Time= 59 ,/**< Rebinding Time 4 DHCP Rebinding (T2) Time [RFC2132] */
+ dhcp_code_Class_Id= 60 ,/**< Class Id N Class Identifier [RFC2132] */
+ dhcp_code_Client_Id= 61 ,/**< Client Id N Client Identifier [RFC2132] */
+ dhcp_code_NetWare_IP_Domain= 62 ,/**< NetWare/IP Domain N NetWare/IP Domain Name [RFC2242] */
+ dhcp_code_NetWare_IP_Option= 63 ,/**< NetWare/IP Option N NetWare/IP sub Options [RFC2242] */
+ dhcp_code_NIS_Domain_Name= 64 ,/**< NIS-Domain-Name N NIS+ v3 Client Domain Name [RFC2132] */
+ dhcp_code_NIS_Server_Addr = 65 ,/**< NIS-Server-Addr N NIS+ v3 Server Addresses [RFC2132] */
+ dhcp_code_Server_Name= 66 ,/**< Server-Name N TFTP Server Name [RFC2132] */
+ dhcp_code_Bootfile_Name= 67 ,/**< Bootfile-Name N Boot File Name [RFC2132] */
+ dhcp_code_Home_Agent_Addrs= 68 ,/**< Home-Agent-Addrs N Home Agent Addresses [RFC2132] */
+ dhcp_code_SMTP_Server= 69 ,/**< SMTP-Server N Simple Mail Server Addresses [RFC2132] */
+ dhcp_code_POP3_Server= 70 ,/**< POP3-Server N Post Office Server Addresses [RFC2132] */
+ dhcp_code_NNTP_Server= 71 ,/**< NNTP-Server N Network News Server Addresses [RFC2132] */
+ dhcp_code_WWW_Server= 72 ,/**< WWW-Server N WWW Server Addresses [RFC2132] */
+ dhcp_code_Finger_Server= 73 ,/**< Finger-Server N Finger Server Addresses [RFC2132] */
+ dhcp_code_IRC_Server= 74 ,/**< IRC-Server N Chat Server Addresses [RFC2132] */
+ dhcp_code_StreetTalk_Server= 75 ,/**< StreetTalk-Server N StreetTalk Server Addresses [RFC2132] */
+ dhcp_code_STDA_Server= 76 ,/**< STDA-Server N ST Directory Assist. Addresses [RFC2132] */
+ dhcp_code_User_Class= 77 ,/**< User-Class N User Class Information [RFC3004] */
+ dhcp_code_Directory_Agent = 78 ,/**< Directory Agent N directory agent information [RFC2610] */
+ dhcp_code_Service_Scope = 79 ,/**< Service Scope N service location agent scope [RFC2610] */
+ dhcp_code_Rapid_Commit= 80 ,/**< Rapid Commit 0 Rapid Commit [RFC4039] */
+ dhcp_code_Client_FQDN = 81 ,/**< Client FQDN N Fully Qualified Domain Name [RFC4702] */
+ dhcp_code_Relay_Agent_Information= 82 ,/**< Relay Agent Information N Relay Agent Information [RFC3046] */
+ dhcp_code_iSNS= 83 ,/**< iSNS N Internet Storage Name Service [RFC4174] */
+ //84 REMOVED/Unassigned [RFC3679] */
+ dhcp_code_NDS_Servers= 85 ,/**< NDS Servers N Novell Directory Services [RFC2241] */
+ dhcp_code_NDS_Tree_Name= 86 ,/**< NDS Tree Name N Novell Directory Services [RFC2241] */
+ dhcp_code_NDS_Context= 87 ,/**< NDS Context N Novell Directory Services [RFC2241] */
+ dhcp_code_BCMCS_Controller_Domain_Name_list= 88 ,/**< BCMCS Controller Domain Name list [RFC4280] */
+ dhcp_code_BCMCS_Controller_IPv4_address_option= 89 ,/**< BCMCS Controller IPv4 address option [RFC4280] */
+ dhcp_code_Authentication= 90 ,/**< Authentication N Authentication [RFC3118] */
+ dhcp_code_client_last_transaction_time= 91 ,/**< client-last-transaction-time option [RFC4388] */
+ dhcp_code_associated_ip= 92 ,/**< associated-ip option [RFC4388] */
+ dhcp_code_Client_System = 93 ,/**< Client System N Client System Architecture [RFC4578] */
+ dhcp_code_Client_NDI = 94 ,/**< Client NDI N Client Network Device Interface [RFC4578] */
+ dhcp_code_LDAP= 95 ,/**< LDAP N Lightweight Directory Access Protocol [RFC3679] */
+ dhcp_code_REMOVED_Unassigned= 96 ,/**< REMOVED/Unassigned [RFC3679] */
+ dhcp_code_UUID_GUID= 97 ,/**< UUID/GUID N UUID/GUID-based Client Identifier [RFC4578] */
+ dhcp_code_User_Auth= 98 ,/**< User-Auth N Open Group's User Authentication [RFC2485] */
+ dhcp_code_GEOCONF_CIVIC= 99 ,/**< GEOCONF_CIVIC [RFC4776] */
+ dhcp_code_PCode= 100 ,/**< PCode N IEEE 1003.1 TZ String [RFC4833] */
+ dhcp_code_TCode= 101 ,/**< TCode N Reference to the TZ Database [RFC4833] */
+ //102-107 REMOVED/Unassigned [RFC3679]
+ //108 REMOVED/Unassigned [RFC3679]
+ //109 Unassigned [RFC3679]
+ //110 REMOVED/Unassigned [RFC3679]
+ //111 Unassigned [RFC3679]
+ dhcp_code_Netinfo_Address= 112 ,/**< Netinfo Address N NetInfo Parent Server Address [RFC3679] */
+ dhcp_code_Netinfo_Tag= 113 ,/**< Netinfo Tag N NetInfo Parent Server Tag [RFC3679] */
+ dhcp_code_= 114 ,/**< URL N URL [RFC3679] */
+ //115 REMOVED/Unassigned [RFC3679]
+ dhcp_code_Auto_Config= 116 ,/**< Auto-Config N DHCP Auto-Configuration [RFC2563] */
+ dhcp_code_Name_Service_Search= 117 ,/**< Name Service Search N Name Service Search [RFC2937] */
+ dhcp_code_Subnet_Selection_Option= 118 ,/**< Subnet Selection Option 4 Subnet Selection Option [RFC3011] */
+ dhcp_code_Domain_Search= 119 ,/**< Domain Search N DNS domain search list [RFC3397] */
+ dhcp_code_SIP_Servers_DHCP_Option= 120 ,/**< SIP Servers DHCP Option N SIP Servers DHCP Option [RFC3361] */
+ dhcp_code_Classless_Static_Route_Option= 121 ,/**< Classless Static Route Option N Classless Static Route Option [RFC3442] */
+ dhcp_code_CCC= 122 ,/**< CCC N CableLabs Client Configuration [RFC3495] */
+ dhcp_code_GeoConf_Option= 123 ,/**< GeoConf Option 16 GeoConf Option [RFC3825] */
+ dhcp_code_V_I_Vendor_Class= 124 ,/**< V-I Vendor Class Vendor-Identifying Vendor Class [RFC3925] */
+ dhcp_code_V_I_Vendor_Specific_Information= 125 ,/**< V-I Vendor-Specific Information Vendor-Identifying Vendor-Specific Information [RFC3925] */
+ //dhcp_code_= 126 ,/**< Removed/Unassigned [RFC3679] */
+ //dhcp_code_= 127 ,/**< Removed/Unassigned [RFC3679] */
+ //dhcp_code_PXE - undefined= 128 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_Etherboot_signature= 128 ,/**< Etherboot signature. 6 bytes: E4:45:74:68:00:00 */
+ dhcp_code_DOCSIS= 128 ,/**< DOCSIS "full security" server IP address */
+ dhcp_code_TFTP_Server_IP= 128 ,/**< TFTP Server IP address (for IP Phone software load) */
+ //dhcp_code_= 129 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_Kernel_options= 129 ,/**< Kernel options. Variable length string */
+ dhcp_code_Call_Server_IP= 129 ,/**< Call Server IP address */
+ //dhcp_code_= 130 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_Ethernet_interface= 130 ,/**< Ethernet interface. Variable length string. */
+ dhcp_code_Discrimination= 130 ,/**< Discrimination string (to identify vendor) */
+ //dhcp_code_= 131 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_Remote_statistics_server_IP= 131 ,/**< Remote statistics server IP address */
+ //dhcp_code_= 132 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_IEEE_802_1Q_VLAN_ID= 132 ,/**< IEEE 802.1Q VLAN ID */
+ //dhcp_code_= 133 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_IEEE_802_1D_p= 133 ,/**< IEEE 802.1D/p Layer 2 Priority */
+ //dhcp_code_= 134 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_DSCP= 134 ,/**< Diffserv Code Point (DSCP) for VoIP signalling and media streams */
+ //dhcp_code_= 135 ,/**< PXE - undefined (vendor specific) [RFC4578] */
+ dhcp_code_HTTP_Proxy= 135 ,/**< HTTP Proxy for phone-specific applications */
+ dhcp_code_OPTION_PANA_AGENT= 136 ,/**< OPTION_PANA_AGENT [RFC5192] */
+ dhcp_code_OPTION_V4_LOST= 137 ,/**< OPTION_V4_LOST [RFC5223] */
+ dhcp_code_OPTION_CAPWAP_AC_V4= 138 ,/**< OPTION_CAPWAP_AC_V4 N CAPWAP Access Controller addresses [RFC5417] */
+ dhcp_code_OPTION_IPv4_Address_MoS= 139 ,/**< OPTION-IPv4_Address-MoS N a series of suboptions [RFC5678] */
+ dhcp_code_OPTION_IPv4_FQDN_MoS= 140 ,/**< OPTION-IPv4_FQDN-MoS N a series of suboptions [RFC5678] */
+ //141-149 Unassigned [RFC3942] */
+ dhcp_code_TFTP_server_address= 150 ,/**< TFTP server address (Tentatively Assigned - 2005-06-23) */
+ dhcp_code_Etherboot= 150 ,/**< Etherboot */
+ dhcp_code_GRUB_configuration_path_name= 150 ,/**< GRUB configuration path name */
+ //151-174 Unassigned [RFC3942]
+ //dhcp_code_Etherboot= 175 ,/**< Etherboot (Tentatively Assigned - 2005-06-23) */
+ dhcp_code_IP_Telephone= 176 ,/**< IP Telephone (Tentatively Assigned - 2005-06-23) */
+ //dhcp_code_Etherboot= 177 ,/**< Etherboot (Tentatively Assigned - 2005-06-23) */
+ dhcp_code_PacketCable_and_CableHome= 177 ,/**< PacketCable and CableHome (replaced by 122) */
+ //178-207 Unassigned [RFC3942]
+ dhcp_code_PXELINUX_Magic= 208 ,/**< PXELINUX Magic 4 magic string = F1:00:74:7E [RFC5071] Deprecated */
+ dhcp_code_Configuration_File= 209 ,/**< Configuration File N Configuration file [RFC5071] */
+ dhcp_code_Path_Prefix= 210 ,/**< Path Prefix N Path Prefix Option [RFC5071] */
+ dhcp_code_Reboot_Time = 211 ,/**< Reboot Time 4 Reboot Time [RFC5071] */
+ // 212-219 Unassigned
+ dhcp_code_Subnet_Allocation= 220 ,/**< Subnet Allocation Option (Tentatively Assigned - 2005-06-23) */
+ dhcp_code_Virtual_Subnet= 221 ,/**< Virtual Subnet Selection Option (Tentatively Assigned - 2005-06-23) */
+ // 222-223 Unassigned [RFC3942]
+ //224-254 Reserved (Private Use)
+ dhcp_code_null=224 ,
+ dhcp_code_End= 255 ,/**< End 0 None [RFC2132] */
+}
+tnet_dhcp_option_code_t;
+
+/** DHCP/BOOTP option as per RFC 2132.
+* Format ==> subclause 2.
+*/
+typedef struct tnet_dhcp_option_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tsk_bool_t initialized;
+
+ tnet_dhcp_option_code_t code; /**< 1-byte option-code. */
+ tsk_buffer_t *value;
+}
+tnet_dhcp_option_t;
+
+typedef tsk_list_t tnet_dhcp_options_L_t;
+
+#define TNET_DECLARE_DHCP_OPTION tnet_dhcp_option_t dhcp_option
+
+int tnet_dhcp_option_init(tnet_dhcp_option_t *self, tnet_dhcp_option_code_t code);
+int tnet_dhcp_option_deinit(tnet_dhcp_option_t *self);
+
+tnet_dhcp_option_t* tnet_dhcp_option_deserialize(const void* data, tsk_size_t size);
+int tnet_dhcp_option_serialize(const tnet_dhcp_option_t* self, tsk_buffer_t *output);
+int tnet_dhcp_option_serializeex(tnet_dhcp_option_code_t code, uint8_t length, const void* value, tsk_buffer_t *output);
+
+/*=======================================================================================
+* RFC 2132 - 9.8. Parameter Request List
+*=======================================================================================*/
+
+/** Parameter Request List Option */
+typedef struct tnet_dhcp_option_paramslist_s
+{
+ TNET_DECLARE_DHCP_OPTION;
+
+ /* RFC 2132 - 9.8. Parameter Request List
+ Code Len Option Codes
+ +-----+-----+-----+-----+---
+ | 55 | n | c1 | c2 | ...
+ +-----+-----+-----+-----+---
+ */
+}
+tnet_dhcp_option_paramslist_t;
+int tnet_dhcp_option_paramslist_add_code(tnet_dhcp_option_paramslist_t* self, tnet_dhcp_option_code_t code);
+
+/*=======================================================================================
+* RFC 2132 - 3.8. Domain Name Server Option
+*=======================================================================================*/
+
+/** Domain Name Server Option */
+typedef struct tnet_dhcp_option_dns_s
+{
+ TNET_DECLARE_DHCP_OPTION;
+
+ /* RFC 2132 - 3.8. Domain Name Server Option
+ Code Len Address 1 Address 2
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ...
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ */
+ tsk_strings_L_t *servers;
+}
+tnet_dhcp_option_dns_t;
+
+TINYNET_API tnet_dhcp_option_t* tnet_dhcp_option_create(tnet_dhcp_option_code_t code);
+TINYNET_API tnet_dhcp_option_paramslist_t* tnet_dhcp_option_paramslist_create();
+TINYNET_API tnet_dhcp_option_dns_t* tnet_dhcp_option_dns_create(const void* payload, tsk_size_t payload_size);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_option_def_t;
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_ns_def_t;
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_option_paramslist_def_t;
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_option_dns_def_t;
+
+
+TNET_END_DECLS
+
+#endif /* TNET_DHCP_OPTION_H */
diff --git a/tinyNET/src/dhcp/tnet_dhcp_option_sip.c b/tinyNET/src/dhcp/tnet_dhcp_option_sip.c new file mode 100644 index 0000000..69d564e --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp_option_sip.c @@ -0,0 +1,131 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+/**@file tnet_dhcp_option_sip.c
+ * @brief Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for
+ * Session Initiation Protocol (SIP) Servers as per RFC 3361.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dhcp_option_sip.h"
+
+#include "dns/tnet_dns_rr.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_memory.h"
+#include "tsk_string.h"
+
+tnet_dhcp_option_sip_t* tnet_dhcp_option_sip_create(const void* payload, tsk_size_t payload_size)
+{
+ return tsk_object_new(tnet_dhcp_option_sip_def_t, payload, payload_size);
+}
+
+//
+// [[DHCP SIP4]] object definition
+//
+static tsk_object_t* tnet_dhcp_option_sip_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dhcp_option_sip_t *option = self;
+ if(option){
+ const void* payload = va_arg(*app, const void*);
+ tsk_size_t payload_size = va_arg(*app, tsk_size_t);
+
+ const uint8_t* payloadPtr = (const uint8_t*)payload;
+ const uint8_t* payloadEnd = (payloadPtr + payload_size);
+
+ /* init base */
+ tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_SIP_Servers_DHCP_Option);
+
+ option->servers = tsk_list_create();
+
+ /* Set values as per RFC 3361. */
+ if(*payloadPtr == 0){ /* enc=0 */
+ /*
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ |120|27 | 0 | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'c'|'o'|'m'| 0 |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+ | 7
+ |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'n'|'e'|'t'| 0 | +---+---+---
+ +---+---+---+---+---+---+---+---+---+---+
+ */
+ tsk_size_t offset = 1;
+ char* server = 0;
+ payloadPtr++;
+ while((payloadPtr < payloadEnd) && !tnet_dns_rr_qname_deserialize(payload, &server, &offset)){
+ tsk_string_t* string = tsk_string_create(server);
+ tsk_list_push_back_data(option->servers, (void*)&string);
+ TSK_FREE(server);
+ payloadPtr += offset;
+ }
+ }
+ else{
+ /*
+ Code Len enc Address 1 Address 2
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ | 120 | n | 1 | a1 | a2 | a3 | a4 | a1 | ...
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ */
+ uint32_t address;
+ tsk_string_t* addrstring;
+ char* ip4 = 0;
+
+ while(payloadPtr < payloadEnd){
+ ++payloadPtr;
+ address = tnet_htonl_2(payloadPtr);
+
+ tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF);
+
+ addrstring = tsk_string_create(ip4);
+ tsk_list_push_back_data(option->servers, (void*)&addrstring);
+
+ TSK_FREE(ip4);
+
+ payloadPtr+= 4;
+ }
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dhcp_option_sip_dtor(tsk_object_t * self)
+{
+ tnet_dhcp_option_sip_t *option = self;
+ if(option){
+ /* deinit base */
+ tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option));
+
+ TSK_OBJECT_SAFE_FREE(option->servers);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dhcp_option_sip_def_s =
+{
+ sizeof(tnet_dhcp_option_sip_t),
+ tnet_dhcp_option_sip_ctor,
+ tnet_dhcp_option_sip_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dhcp_option_sip_def_t = &tnet_dhcp_option_sip_def_s;
diff --git a/tinyNET/src/dhcp/tnet_dhcp_option_sip.h b/tinyNET/src/dhcp/tnet_dhcp_option_sip.h new file mode 100644 index 0000000..8db7049 --- /dev/null +++ b/tinyNET/src/dhcp/tnet_dhcp_option_sip.h @@ -0,0 +1,62 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+/**@file tnet_dhcp_option_sip.h
+ * @brief Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for
+ * Session Initiation Protocol (SIP) Servers as per RFC 3361.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef tnet_dhcp_option_sip_H
+#define tnet_dhcp_option_sip_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dhcp_option.h"
+
+#include "tsk_string.h"
+
+TNET_BEGIN_DECLS
+
+typedef struct tnet_dhcp_option_sip_s
+{
+ TNET_DECLARE_DHCP_OPTION;
+
+ /* RFC 3361 subclause 3.1
+ Code Len enc DNS name of SIP server
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ | 120 | n | 0 | s1 | s2 | s3 | s4 | s5 | ...
+ +-----+-----+-----+-----+-----+-----+-----+-----+--
+ */
+ tsk_strings_L_t *servers;
+}
+tnet_dhcp_option_sip_t;
+
+TINYNET_API tnet_dhcp_option_sip_t* tnet_dhcp_option_sip_create(const void* payload, tsk_size_t payload_size);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dhcp_option_sip_def_t;
+
+TNET_END_DECLS
+
+#endif /* #define tnet_dhcp_option_sip_H */
|