gdhcp: Avoid reading invalid data in dhcp_get_option
[platform/upstream/connman.git] / gdhcp / server.c
index 83132a7..52ea2a5 100755 (executable)
@@ -66,7 +66,6 @@ struct _GDHCPServer {
        GHashTable *option_hash; /* Options send to client */
        GDHCPSaveLeaseFunc save_lease_func;
        GDHCPLeaseAddedCb lease_added_cb;
-       GDHCPSaveACKLeaseFunc save_ack_lease_func;
        GDHCPDebugFunc debug_func;
        gpointer debug_data;
 };
@@ -215,9 +214,6 @@ static struct dhcp_lease *add_lease(GDHCPServer *dhcp_server, uint32_t expire,
        g_hash_table_insert(dhcp_server->nip_lease_hash,
                                GINT_TO_POINTER((int) lease->lease_nip), lease);
 
-       if (dhcp_server->lease_added_cb)
-               dhcp_server->lease_added_cb(lease->lease_mac, yiaddr);
-
        return lease;
 }
 
@@ -400,10 +396,9 @@ GDHCPServer *g_dhcp_server_new(GDHCPType type,
        dhcp_server->ref_count = 1;
        dhcp_server->ifindex = ifindex;
        dhcp_server->listener_sockfd = -1;
-       dhcp_server->listener_watch = -1;
+       dhcp_server->listener_watch = 0;
        dhcp_server->listener_channel = NULL;
        dhcp_server->save_lease_func = NULL;
-       dhcp_server->save_ack_lease_func = NULL;
        dhcp_server->debug_func = NULL;
        dhcp_server->debug_data = NULL;
 
@@ -418,7 +413,7 @@ error:
 }
 
 
-static uint8_t check_packet_type(struct dhcp_packet *packet)
+static uint8_t check_packet_type(struct dhcp_packet *packet, uint16_t packet_len)
 {
        uint8_t *type;
 
@@ -428,7 +423,7 @@ static uint8_t check_packet_type(struct dhcp_packet *packet)
        if (packet->op != BOOTREQUEST)
                return 0;
 
-       type = dhcp_get_option(packet, DHCP_MESSAGE_TYPE);
+       type = dhcp_get_option(packet, packet_len, DHCP_MESSAGE_TYPE);
 
        if (!type)
                return 0;
@@ -618,6 +613,9 @@ static void send_ACK(GDHCPServer *dhcp_server,
        send_packet_to_client(dhcp_server, &packet);
 
        add_lease(dhcp_server, 0, packet.chaddr, packet.yiaddr);
+
+       if (dhcp_server->lease_added_cb)
+               dhcp_server->lease_added_cb(packet.chaddr, packet.yiaddr);
 }
 
 static void send_NAK(GDHCPServer *dhcp_server,
@@ -652,12 +650,10 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
        struct dhcp_packet packet;
        struct dhcp_lease *lease;
        uint32_t requested_nip = 0;
-       uint8_t type, *server_id_option, *request_ip_option, *host_name;
+       uint8_t type, *server_id_option, *request_ip_option;
+       uint16_t packet_len;
        int re;
 
-       GDHCPOptionType option_type;
-       char *option_value;
-
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
                dhcp_server->listener_watch = 0;
                return FALSE;
@@ -666,12 +662,13 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
        re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd);
        if (re < 0)
                return TRUE;
+       packet_len = (uint16_t)(unsigned int)re;
 
-       type = check_packet_type(&packet);
+       type = check_packet_type(&packet, packet_len);
        if (type == 0)
                return TRUE;
 
-       server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID);
+       server_id_option = dhcp_get_option(&packet, packet_len, DHCP_SERVER_ID);
        if (server_id_option) {
                uint32_t server_nid =
                        get_unaligned((const uint32_t *) server_id_option);
@@ -680,7 +677,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                        return TRUE;
        }
 
-       request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP);
+       request_ip_option = dhcp_get_option(&packet, packet_len, DHCP_REQUESTED_IP);
        if (request_ip_option)
                requested_nip = get_be32(request_ip_option);
 
@@ -696,28 +693,15 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                debug(dhcp_server, "Received REQUEST NIP %d",
                                                        requested_nip);
                if (requested_nip == 0) {
-                       requested_nip = packet.ciaddr;
+                       requested_nip = ntohl(packet.ciaddr);
                        if (requested_nip == 0)
                                break;
                }
 
                if (lease && requested_nip == lease->lease_nip) {
                        debug(dhcp_server, "Sending ACK");
-
-                       host_name = dhcp_get_option(&packet, DHCP_HOST_NAME);
-                       option_type = dhcp_get_code_type(DHCP_HOST_NAME);
-                       option_value = malloc_option_value_string(host_name,
-                                                               option_type);
                        send_ACK(dhcp_server, &packet,
                                lease->lease_nip);
-
-                       if (dhcp_server->save_ack_lease_func)
-                               dhcp_server->save_ack_lease_func(
-                                                       option_value,
-                                                       lease->lease_mac,
-                                                       lease->lease_nip);
-                       g_free(option_value);
-
                        break;
                }
 
@@ -846,15 +830,6 @@ void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server,
        dhcp_server->lease_added_cb = cb;
 }
 
-void g_dhcp_server_set_save_ack_lease(GDHCPServer *dhcp_server,
-                               GDHCPSaveACKLeaseFunc func, gpointer user_data)
-{
-       if (dhcp_server == NULL)
-               return;
-
-       dhcp_server->save_ack_lease_func = func;
-}
-
 GDHCPServer *g_dhcp_server_ref(GDHCPServer *dhcp_server)
 {
        if (!dhcp_server)