1c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline/* 2c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * Copyright 2014 The Android Open Source Project 3c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * 4c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * Licensed under the Apache License, Version 2.0 (the "License"); 5c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * you may not use this file except in compliance with the License. 6c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * You may obtain a copy of the License at 7c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * 8c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * http://www.apache.org/licenses/LICENSE-2.0 9c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * 10c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * Unless required by applicable law or agreed to in writing, software 11c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * distributed under the License is distributed on an "AS IS" BASIS, 12c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * See the License for the specific language governing permissions and 14c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * limitations under the License. 15c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * 16c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline * dhcpcd_test.cpp - unit tests for dhcpcd 17c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline */ 18c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 19c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#include <stdint.h> 20c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#include <stdlib.h> 21c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#include <string> 22c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 23c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#include <gtest/gtest.h> 24c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 25c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline// For convenience. 26c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define ARRAYSIZE(x) sizeof((x)) / sizeof((x)[0]) 27c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 28c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline// Regrettably, copy these defines and the dhcp_message structure in from 29c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline// dhcp.h. This header file is not easily included, since subsequent 30c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline// includes use C++ reserved keywords (like "new") as structure member names. 31c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Klineextern "C" { 32c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 33c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define DHO_PAD 0 34c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define DHO_DNSDOMAIN 15 35c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 36c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline/* Max MTU - defines dhcp option length */ 37c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define MTU_MAX 1500 38c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 39c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline/* Sizes for DHCP options */ 40c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define DHCP_CHADDR_LEN 16 41c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define SERVERNAME_LEN 64 42c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define BOOTFILE_LEN 128 43c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define DHCP_UDP_LEN (14 + 20 + 8) 44c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define DHCP_FIXED_LEN (DHCP_UDP_LEN + 226) 45c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define DHCP_OPTION_LEN (MTU_MAX - DHCP_FIXED_LEN) 46c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 47c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline/* Some crappy DHCP servers require the BOOTP minimum length */ 48c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline#define BOOTP_MESSAGE_LENTH_MIN 300 49c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 50c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Klinestruct dhcp_message { 51c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t op; /* message type */ 52c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t hwtype; /* hardware address type */ 53c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t hwlen; /* hardware address length */ 54c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t hwopcount; /* should be zero in client message */ 55c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint32_t xid; /* transaction id */ 56c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint16_t secs; /* elapsed time in sec. from boot */ 57c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint16_t flags; 58c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint32_t ciaddr; /* (previously allocated) client IP */ 59c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint32_t yiaddr; /* 'your' client IP address */ 60c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint32_t siaddr; /* should be zero in client's messages */ 61c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint32_t giaddr; /* should be zero in client's messages */ 62c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t chaddr[DHCP_CHADDR_LEN]; /* client's hardware address */ 63c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t servername[SERVERNAME_LEN]; /* server host name */ 64c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t bootfile[BOOTFILE_LEN]; /* boot file name */ 65c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint32_t cookie; 66c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */ 67c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} _packed; 68c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 69c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Klinechar * get_option_string(const struct dhcp_message *dhcp, uint8_t option); 70c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 71c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 72c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 73c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 74c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Klinestatic const char kOptionString[] = "hostname"; 75c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 76c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Klineclass DhcpcdGetOptionTest : public ::testing::Test { 77c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline protected: 78c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline virtual void SetUp() { 79c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline memset(dhcpmsgs, 0, ARRAYSIZE(dhcpmsgs) * sizeof(struct dhcp_message)); 80c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline // Technically redundant. 81c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline memset(&(dhcpmsgs[0].options), DHO_PAD, sizeof(dhcpmsgs[0].options)); 82c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 83c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = 0; 84c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline length_index = 0; 85c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline value_index = 0; 86c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline } 87c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 88c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline void PopulateTLV() { 89c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline // May very well write off the end of the first struct dhcp_message, 90c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline // by design. 91c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline length_index = type_index + 1; 92c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline value_index = length_index + 1; 93c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline dhcpmsgs[0].options[type_index] = DHO_DNSDOMAIN; 94c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline dhcpmsgs[0].options[length_index] = strlen(kOptionString); 95c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline memcpy(&(dhcpmsgs[0].options[value_index]), 96c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline kOptionString, strlen(kOptionString)); 97c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline } 98c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 99c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline struct dhcp_message dhcpmsgs[2]; 100c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline size_t type_index; 101c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline size_t length_index; 102c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline size_t value_index; 103c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline}; 104c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 105c1c270dba20afa63a5b7769646cf721d0fa7c431Erik KlineTEST_F(DhcpcdGetOptionTest, OptionNotPresent) { 106c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline // An entire option block of padding (all zeros). 107c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_EQ(NULL, ::get_option_string(&(dhcpmsgs[0]), DHO_DNSDOMAIN)); 108c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 109c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 110c1c270dba20afa63a5b7769646cf721d0fa7c431Erik KlineTEST_F(DhcpcdGetOptionTest, TypeIsOffTheEnd) { 111c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = sizeof(dhcpmsgs[0].options); 112c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline PopulateTLV(); 113c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_EQ(NULL, ::get_option_string(&(dhcpmsgs[0]), DHO_DNSDOMAIN)); 114c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 115c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 116c1c270dba20afa63a5b7769646cf721d0fa7c431Erik KlineTEST_F(DhcpcdGetOptionTest, LengthIsOffTheEnd) { 117c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = sizeof(dhcpmsgs[0].options) - 1; 118c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline PopulateTLV(); 119c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_EQ(NULL, ::get_option_string(&(dhcpmsgs[0]), DHO_DNSDOMAIN)); 120c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 121c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 122c1c270dba20afa63a5b7769646cf721d0fa7c431Erik KlineTEST_F(DhcpcdGetOptionTest, ValueIsOffTheEnd) { 123c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = sizeof(dhcpmsgs[0].options) - 2; 124c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline PopulateTLV(); 125c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_EQ(NULL, ::get_option_string(&(dhcpmsgs[0]), DHO_DNSDOMAIN)); 126c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 127c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 128c1c270dba20afa63a5b7769646cf721d0fa7c431Erik KlineTEST_F(DhcpcdGetOptionTest, InsufficientSpaceForValue) { 129c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = sizeof(dhcpmsgs[0].options) - 6; 130c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline PopulateTLV(); 131c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline char* value = ::get_option_string(&(dhcpmsgs[0]), DHO_DNSDOMAIN); 132c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_TRUE(NULL != value); 133c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_EQ("host", ::std::string(value)); 134c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline free(value); 135c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 136c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline 137c1c270dba20afa63a5b7769646cf721d0fa7c431Erik KlineTEST_F(DhcpcdGetOptionTest, InsufficientSpaceForContinuedValue) { 138c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = sizeof(dhcpmsgs[0].options) - 16; 139c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline PopulateTLV(); 140c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline type_index = sizeof(dhcpmsgs[0].options) - 6; 141c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline PopulateTLV(); 142c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline char* value = ::get_option_string(&(dhcpmsgs[0]), DHO_DNSDOMAIN); 143c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_TRUE(NULL != value); 144c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline EXPECT_EQ("hostnamehost", ::std::string(value)); 145c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline free(value); 146c1c270dba20afa63a5b7769646cf721d0fa7c431Erik Kline} 147