Browse Source

[1224] DHCPv4: Indents fixed, using vector<uint8_t> in several places now.

Tomek Mrugalski 13 years ago
parent
commit
f7c85718e5
4 changed files with 172 additions and 157 deletions
  1. 116 109
      src/lib/dhcp/dhcp4.h
  2. 12 8
      src/lib/dhcp/pkt4.cc
  3. 1 1
      src/lib/dhcp/pkt4.h
  4. 43 39
      src/lib/dhcp/tests/pkt4_unittest.cc

+ 116 - 109
src/lib/dhcp/dhcp4.h

@@ -40,121 +40,129 @@ namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
 /* BOOTP (rfc951) message types */
 /* BOOTP (rfc951) message types */
-    enum BOOTPTypes {
-        BOOTREQUEST = 1,
-        BOOTREPLY = 2 };
+enum BOOTPTypes {
+    BOOTREQUEST = 1,
+    BOOTREPLY = 2
+};
 
 
 /* Possible values for flags field... */
 /* Possible values for flags field... */
-    static const uint16_t BOOTP_BROADCAST = 32768L;
+static const uint16_t BOOTP_BROADCAST = 32768L;
 
 
 /* Possible values for hardware type (htype) field... */
 /* Possible values for hardware type (htype) field... */
-    enum HType {
-        HTYPE_ETHER = 1,   /* Ethernet 10Mbps */
-        HTYPE_IEEE802 = 6, /* IEEE 802.2 Token Ring */
-        HTYPE_FDDI = 8     /* FDDI */
-        /// TODO Add infiniband here
-    };
-
-/* Magic cookie validating dhcp options field (and bootp vendor
-   extensions field). */
-#define DHCP_OPTIONS_COOKIE     "\143\202\123\143"
+enum HType {
+    HTYPE_ETHER = 1,   /* Ethernet 10Mbps */
+    HTYPE_IEEE802 = 6, /* IEEE 802.2 Token Ring */
+    HTYPE_FDDI = 8     /* FDDI */
+    /// TODO Add infiniband here
+};
 
 
 /* DHCP Option codes: */
 /* DHCP Option codes: */
-    enum DHCPOptionType {
-        DHO_PAD                          = 0,
-        DHO_SUBNET_MASK                  = 1,
-        DHO_TIME_OFFSET                  = 2,
-        DHO_ROUTERS                      = 3,
-        DHO_TIME_SERVERS                 = 4,
-        DHO_NAME_SERVERS                 = 5,
-        DHO_DOMAIN_NAME_SERVERS          = 6,
-        DHO_LOG_SERVERS                  = 7,
-        DHO_COOKIE_SERVERS               = 8,
-        DHO_LPR_SERVERS                  = 9,
-        DHO_IMPRESS_SERVERS              = 10,
-        DHO_RESOURCE_LOCATION_SERVERS    = 11,
-        DHO_HOST_NAME                    = 12,
-        DHO_BOOT_SIZE                    = 13,
-        DHO_MERIT_DUMP                   = 14,
-        DHO_DOMAIN_NAME                  = 15,
-        DHO_SWAP_SERVER                  = 16,
-        DHO_ROOT_PATH                    = 17,
-        DHO_EXTENSIONS_PATH              = 18,
-        DHO_IP_FORWARDING                = 19,
-        DHO_NON_LOCAL_SOURCE_ROUTING     = 20,
-        DHO_POLICY_FILTER                = 21,
-        DHO_MAX_DGRAM_REASSEMBLY         = 22,
-        DHO_DEFAULT_IP_TTL               = 23,
-        DHO_PATH_MTU_AGING_TIMEOUT       = 24,
-        DHO_PATH_MTU_PLATEAU_TABLE       = 25,
-        DHO_INTERFACE_MTU                = 26,
-        DHO_ALL_SUBNETS_LOCAL            = 27,
-        DHO_BROADCAST_ADDRESS            = 28,
-        DHO_PERFORM_MASK_DISCOVERY       = 29,
-        DHO_MASK_SUPPLIER                = 30,
-        DHO_ROUTER_DISCOVERY             = 31,
-        DHO_ROUTER_SOLICITATION_ADDRESS  = 32,
-        DHO_STATIC_ROUTES                = 33,
-        DHO_TRAILER_ENCAPSULATION        = 34,
-        DHO_ARP_CACHE_TIMEOUT            = 35,
-        DHO_IEEE802_3_ENCAPSULATION      = 36,
-        DHO_DEFAULT_TCP_TTL              = 37,
-        DHO_TCP_KEEPALIVE_INTERVAL       = 38,
-        DHO_TCP_KEEPALIVE_GARBAGE        = 39,
-        DHO_NIS_DOMAIN                   = 40,
-        DHO_NIS_SERVERS                  = 41,
-        DHO_NTP_SERVERS                  = 42,
-        DHO_VENDOR_ENCAPSULATED_OPTIONS  = 43,
-        DHO_NETBIOS_NAME_SERVERS         = 44,
-        DHO_NETBIOS_DD_SERVER            = 45,
-        DHO_NETBIOS_NODE_TYPE            = 46,
-        DHO_NETBIOS_SCOPE                = 47,
-        DHO_FONT_SERVERS                 = 48,
-        DHO_X_DISPLAY_MANAGER            = 49,
-        DHO_DHCP_REQUESTED_ADDRESS       = 50,
-        DHO_DHCP_LEASE_TIME              = 51,
-        DHO_DHCP_OPTION_OVERLOAD         = 52,
-        DHO_DHCP_MESSAGE_TYPE            = 53,
-        DHO_DHCP_SERVER_IDENTIFIER       = 54,
-        DHO_DHCP_PARAMETER_REQUEST_LIST  = 55,
-        DHO_DHCP_MESSAGE                 = 56,
-        DHO_DHCP_MAX_MESSAGE_SIZE        = 57,
-        DHO_DHCP_RENEWAL_TIME            = 58,
-        DHO_DHCP_REBINDING_TIME          = 59,
-        DHO_VENDOR_CLASS_IDENTIFIER      = 60,
-        DHO_DHCP_CLIENT_IDENTIFIER       = 61,
-        DHO_NWIP_DOMAIN_NAME             = 62,
-        DHO_NWIP_SUBOPTIONS              = 63,
-        DHO_USER_CLASS                   = 77,
-        DHO_FQDN                         = 81,
-        DHO_DHCP_AGENT_OPTIONS           = 82,
-        DHO_AUTHENTICATE                 = 90,  /* RFC3118, was 210 */
-        DHO_CLIENT_LAST_TRANSACTION_TIME = 91,
-        DHO_ASSOCIATED_IP                = 92,
-        DHO_SUBNET_SELECTION             = 118, /* RFC3011! */
-        DHO_DOMAIN_SEARCH                = 119, /* RFC3397 */
-        DHO_VIVCO_SUBOPTIONS             = 124,
-        DHO_VIVSO_SUBOPTIONS             = 125,
-
-        DHO_END                          = 255
-    };
+enum DHCPOptionType {
+    DHO_PAD                          = 0,
+    DHO_SUBNET_MASK                  = 1,
+    DHO_TIME_OFFSET                  = 2,
+    DHO_ROUTERS                      = 3,
+    DHO_TIME_SERVERS                 = 4,
+    DHO_NAME_SERVERS                 = 5,
+    DHO_DOMAIN_NAME_SERVERS          = 6,
+    DHO_LOG_SERVERS                  = 7,
+    DHO_COOKIE_SERVERS               = 8,
+    DHO_LPR_SERVERS                  = 9,
+    DHO_IMPRESS_SERVERS              = 10,
+    DHO_RESOURCE_LOCATION_SERVERS    = 11,
+    DHO_HOST_NAME                    = 12,
+    DHO_BOOT_SIZE                    = 13,
+    DHO_MERIT_DUMP                   = 14,
+    DHO_DOMAIN_NAME                  = 15,
+    DHO_SWAP_SERVER                  = 16,
+    DHO_ROOT_PATH                    = 17,
+    DHO_EXTENSIONS_PATH              = 18,
+    DHO_IP_FORWARDING                = 19,
+    DHO_NON_LOCAL_SOURCE_ROUTING     = 20,
+    DHO_POLICY_FILTER                = 21,
+    DHO_MAX_DGRAM_REASSEMBLY         = 22,
+    DHO_DEFAULT_IP_TTL               = 23,
+    DHO_PATH_MTU_AGING_TIMEOUT       = 24,
+    DHO_PATH_MTU_PLATEAU_TABLE       = 25,
+    DHO_INTERFACE_MTU                = 26,
+    DHO_ALL_SUBNETS_LOCAL            = 27,
+    DHO_BROADCAST_ADDRESS            = 28,
+    DHO_PERFORM_MASK_DISCOVERY       = 29,
+    DHO_MASK_SUPPLIER                = 30,
+    DHO_ROUTER_DISCOVERY             = 31,
+    DHO_ROUTER_SOLICITATION_ADDRESS  = 32,
+    DHO_STATIC_ROUTES                = 33,
+    DHO_TRAILER_ENCAPSULATION        = 34,
+    DHO_ARP_CACHE_TIMEOUT            = 35,
+    DHO_IEEE802_3_ENCAPSULATION      = 36,
+    DHO_DEFAULT_TCP_TTL              = 37,
+    DHO_TCP_KEEPALIVE_INTERVAL       = 38,
+    DHO_TCP_KEEPALIVE_GARBAGE        = 39,
+    DHO_NIS_DOMAIN                   = 40,
+    DHO_NIS_SERVERS                  = 41,
+    DHO_NTP_SERVERS                  = 42,
+    DHO_VENDOR_ENCAPSULATED_OPTIONS  = 43,
+    DHO_NETBIOS_NAME_SERVERS         = 44,
+    DHO_NETBIOS_DD_SERVER            = 45,
+    DHO_NETBIOS_NODE_TYPE            = 46,
+    DHO_NETBIOS_SCOPE                = 47,
+    DHO_FONT_SERVERS                 = 48,
+    DHO_X_DISPLAY_MANAGER            = 49,
+    DHO_DHCP_REQUESTED_ADDRESS       = 50,
+    DHO_DHCP_LEASE_TIME              = 51,
+    DHO_DHCP_OPTION_OVERLOAD         = 52,
+    DHO_DHCP_MESSAGE_TYPE            = 53,
+    DHO_DHCP_SERVER_IDENTIFIER       = 54,
+    DHO_DHCP_PARAMETER_REQUEST_LIST  = 55,
+    DHO_DHCP_MESSAGE                 = 56,
+    DHO_DHCP_MAX_MESSAGE_SIZE        = 57,
+    DHO_DHCP_RENEWAL_TIME            = 58,
+    DHO_DHCP_REBINDING_TIME          = 59,
+    DHO_VENDOR_CLASS_IDENTIFIER      = 60,
+    DHO_DHCP_CLIENT_IDENTIFIER       = 61,
+    DHO_NWIP_DOMAIN_NAME             = 62,
+    DHO_NWIP_SUBOPTIONS              = 63,
+    DHO_USER_CLASS                   = 77,
+    DHO_FQDN                         = 81,
+    DHO_DHCP_AGENT_OPTIONS           = 82,
+    DHO_AUTHENTICATE                 = 90,  /* RFC3118, was 210 */
+    DHO_CLIENT_LAST_TRANSACTION_TIME = 91,
+    DHO_ASSOCIATED_IP                = 92,
+    DHO_SUBNET_SELECTION             = 118, /* RFC3011! */
+    DHO_DOMAIN_SEARCH                = 119, /* RFC3397 */
+    DHO_VIVCO_SUBOPTIONS             = 124,
+    DHO_VIVSO_SUBOPTIONS             = 125,
+
+    DHO_END                          = 255
+};
 
 
 /* DHCP message types. */
 /* DHCP message types. */
-    enum DHCPMessageType {
-        DHCPDISCOVER        =  1,
-        DHCPOFFER           =  2,
-        DHCPREQUEST         =  3,
-        DHCPDECLINE         =  4,
-        DHCPACK             =  5,
-        DHCPNAK             =  6,
-        DHCPRELEASE         =  7,
-        DHCPINFORM          =  8,
-        DHCPLEASEQUERY      =  10,
-        DHCPLEASEUNASSIGNED =  11,
-        DHCPLEASEUNKNOWN    =  12,
-        DHCPLEASEACTIVE     =  13
-    };
-
+enum DHCPMessageType {
+    DHCPDISCOVER        =  1,
+    DHCPOFFER           =  2,
+    DHCPREQUEST         =  3,
+    DHCPDECLINE         =  4,
+    DHCPACK             =  5,
+    DHCPNAK             =  6,
+    DHCPRELEASE         =  7,
+    DHCPINFORM          =  8,
+    DHCPLEASEQUERY      =  10,
+    DHCPLEASEUNASSIGNED =  11,
+    DHCPLEASEUNKNOWN    =  12,
+    DHCPLEASEACTIVE     =  13
+};
+
+static const uint16_t DHCP4_CLIENT_PORT = 68;
+static const uint16_t DHCP4_SERVER_PORT = 67;
+
+/// Magic cookie validating dhcp options field (and bootp vendor
+/// extensions field).
+///static const char* DHCP_OPTIONS_COOKIE = "\143\202\123\143";
+
+// TODO: Following are leftovers from dhcp.h import from ISC DHCP
+// They will be converted to C++-style defines once they will start
+// to be used.
+#if 0
 /* Relay Agent Information option subtypes: */
 /* Relay Agent Information option subtypes: */
 #define RAI_CIRCUIT_ID  1
 #define RAI_CIRCUIT_ID  1
 #define RAI_REMOTE_ID   2
 #define RAI_REMOTE_ID   2
@@ -175,8 +183,7 @@ namespace dhcp {
 /* Enterprise Suboptions: */
 /* Enterprise Suboptions: */
 #define VENDOR_ISC_SUBOPTIONS           2495
 #define VENDOR_ISC_SUBOPTIONS           2495
 
 
-    static const uint16_t DHCP4_CLIENT_PORT = 68;
-    static const uint16_t DHCP4_SERVER_PORT = 67;
+#endif
 
 
 } // end of isc::dhcp namespace
 } // end of isc::dhcp namespace
 } // end of isc namespace
 } // end of isc namespace

+ 12 - 8
src/lib/dhcp/pkt4.cc

@@ -25,12 +25,13 @@ using namespace isc::dhcp;
 using namespace isc::asiolink;
 using namespace isc::asiolink;
 
 
 namespace isc {
 namespace isc {
+namespace dhcp {
 
 
 const IOAddress DEFAULT_ADDRESS("0.0.0.0");
 const IOAddress DEFAULT_ADDRESS("0.0.0.0");
 
 
 Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
 Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
-     :local_addr_(IOAddress("0.0.0.0")),
-      remote_addr_(IOAddress("0.0.0.0")),
+     :local_addr_(DEFAULT_ADDRESS),
+      remote_addr_(DEFAULT_ADDRESS),
       iface_(""),
       iface_(""),
       ifindex_(0),
       ifindex_(0),
       local_port_(DHCP4_SERVER_PORT),
       local_port_(DHCP4_SERVER_PORT),
@@ -57,8 +58,8 @@ Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
 }
 }
 
 
 Pkt4::Pkt4(const uint8_t* data, size_t len)
 Pkt4::Pkt4(const uint8_t* data, size_t len)
-     :local_addr_(IOAddress("0.0.0.0")),
-      remote_addr_(IOAddress("0.0.0.0")),
+     :local_addr_(DEFAULT_ADDRESS),
+      remote_addr_(DEFAULT_ADDRESS),
       iface_(""),
       iface_(""),
       ifindex_(-1),
       ifindex_(-1),
       local_port_(DHCP4_SERVER_PORT),
       local_port_(DHCP4_SERVER_PORT),
@@ -118,21 +119,22 @@ Pkt4::toText() {
 }
 }
 
 
 void
 void
-Pkt4::setHWAddr(uint8_t hType, uint8_t hlen, const uint8_t* macAddr) {
+Pkt4::setHWAddr(uint8_t hType, uint8_t hlen,
+                const std::vector<uint8_t>& macAddr) {
     /// TODO Rewrite this once support for client-identifier option
     /// TODO Rewrite this once support for client-identifier option
     /// is implemented (ticket 1228?)
     /// is implemented (ticket 1228?)
     if (hlen>MAX_CHADDR_LEN) {
     if (hlen>MAX_CHADDR_LEN) {
         isc_throw(OutOfRange, "Hardware address (len=" << hlen
         isc_throw(OutOfRange, "Hardware address (len=" << hlen
                   << " too long. Max " << MAX_CHADDR_LEN << " supported.");
                   << " too long. Max " << MAX_CHADDR_LEN << " supported.");
     }
     }
-    if ( (!macAddr) && (hlen > 0) ) {
+    if ( (macAddr.size() == 0) && (hlen > 0) ) {
         isc_throw(OutOfRange, "Invalid HW Address specified");
         isc_throw(OutOfRange, "Invalid HW Address specified");
     }
     }
 
 
     htype_ = hType;
     htype_ = hType;
     hlen_ = hlen;
     hlen_ = hlen;
     memset(chaddr_, 0, MAX_CHADDR_LEN);
     memset(chaddr_, 0, MAX_CHADDR_LEN);
-    memcpy(chaddr_, macAddr, hlen);
+    memcpy(chaddr_, &macAddr[0], hlen);
 }
 }
 
 
 void
 void
@@ -182,4 +184,6 @@ Pkt4::DHCPTypeToBootpType(uint8_t dhcpType) {
     }
     }
 }
 }
 
 
-};
+} // end of namespace isc::dhcp
+
+} // end of namespace isc

+ 1 - 1
src/lib/dhcp/pkt4.h

@@ -250,7 +250,7 @@ public:
     /// @param hlen hardware length (will be sent in hlen field)
     /// @param hlen hardware length (will be sent in hlen field)
     /// @param macAddr pointer to hardware address
     /// @param macAddr pointer to hardware address
     void setHWAddr(uint8_t hType, uint8_t hlen,
     void setHWAddr(uint8_t hType, uint8_t hlen,
-                   const uint8_t* macAddr);
+                   const std::vector<uint8_t>& macAddr);
 
 
     /// Returns htype field
     /// Returns htype field
     ///
     ///

+ 43 - 39
src/lib/dhcp/tests/pkt4_unittest.cc

@@ -44,10 +44,10 @@ TEST(Pkt4Test, constructor) {
     ASSERT_EQ(236U, DHCPV4_PKT_HDR_LEN);
     ASSERT_EQ(236U, DHCPV4_PKT_HDR_LEN);
     Pkt4* pkt = 0;
     Pkt4* pkt = 0;
 
 
-    // minimal 
+    // minimal
     uint8_t testData[250];
     uint8_t testData[250];
     for (int i = 0; i < 250; i++) {
     for (int i = 0; i < 250; i++) {
-        testData[i]=i; 
+        testData[i]=i;
     }
     }
 
 
     // positive case1. Normal received packet
     // positive case1. Normal received packet
@@ -95,14 +95,14 @@ const static uint32_t dummyTransid = 0x12345678;
 const uint8_t dummyMacAddr[] = {0, 1, 2, 3, 4, 5};
 const uint8_t dummyMacAddr[] = {0, 1, 2, 3, 4, 5};
 
 
 // a dummy MAC address, padded with 0s
 // a dummy MAC address, padded with 0s
-const uint8_t dummyChaddr[16] = {0, 1, 2, 3, 4, 5, 0, 0, 
+const uint8_t dummyChaddr[16] = {0, 1, 2, 3, 4, 5, 0, 0,
                                  0, 0, 0, 0, 0, 0, 0, 0 };
                                  0, 0, 0, 0, 0, 0, 0, 0 };
 
 
 // let's use some creative test content here (128 chars + \0)
 // let's use some creative test content here (128 chars + \0)
 const uint8_t dummyFile[] = "Lorem ipsum dolor sit amet, consectetur "
 const uint8_t dummyFile[] = "Lorem ipsum dolor sit amet, consectetur "
     "adipiscing elit. Proin mollis placerat metus, at "
     "adipiscing elit. Proin mollis placerat metus, at "
     "lacinia orci ornare vitae. Mauris amet.";
     "lacinia orci ornare vitae. Mauris amet.";
-    
+
 // yet another type of test content (64 chars + \0)
 // yet another type of test content (64 chars + \0)
 const uint8_t dummySname[] = "Lorem ipsum dolor sit amet, consectetur "
 const uint8_t dummySname[] = "Lorem ipsum dolor sit amet, consectetur "
     "adipiscing elit posuere.";
     "adipiscing elit posuere.";
@@ -124,8 +124,12 @@ boost::shared_ptr<Pkt4>
 generateTestPacket1() {
 generateTestPacket1() {
 
 
     boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPDISCOVER, dummyTransid));
     boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPDISCOVER, dummyTransid));
+
+    vector<uint8_t> vectorMacAddr(dummyMacAddr, dummyMacAddr
+                                  +sizeof(dummyMacAddr));
+
     // hwType = 6(ETHERNET), hlen = 6(MAC address len)
     // hwType = 6(ETHERNET), hlen = 6(MAC address len)
-    pkt->setHWAddr(6, 6, dummyMacAddr); 
+    pkt->setHWAddr(6, 6, vectorMacAddr);
     pkt->setHops(13); // 13 relays. Wow!
     pkt->setHops(13); // 13 relays. Wow!
     // transaction-id is already set
     // transaction-id is already set
     pkt->setSecs(42);
     pkt->setSecs(42);
@@ -135,7 +139,7 @@ generateTestPacket1() {
     pkt->setSiaddr(IOAddress("192.0.2.255"));
     pkt->setSiaddr(IOAddress("192.0.2.255"));
     pkt->setGiaddr(IOAddress("255.255.255.255"));
     pkt->setGiaddr(IOAddress("255.255.255.255"));
     // chaddr already set with setHWAddr()
     // chaddr already set with setHWAddr()
-    pkt->setSname(dummySname, 64); 
+    pkt->setSname(dummySname, 64);
     pkt->setFile(dummyFile, 128);
     pkt->setFile(dummyFile, 128);
 
 
     return (pkt);
     return (pkt);
@@ -144,43 +148,41 @@ generateTestPacket1() {
 /// Generates test packet
 /// Generates test packet
 ///
 ///
 /// Allocates and generates on-wire buffer that represents
 /// Allocates and generates on-wire buffer that represents
-/// test packet, with all fixed fields set to non-zero values. 
+/// test packet, with all fixed fields set to non-zero values.
 /// Content is not always reasonable.
 /// Content is not always reasonable.
 ///
 ///
 /// See generateTestPacket1() function that returns
 /// See generateTestPacket1() function that returns
 /// exactly the same packet as Pkt4 object.
 /// exactly the same packet as Pkt4 object.
 ///
 ///
 /// @return pointer to allocated Pkt4 object
 /// @return pointer to allocated Pkt4 object
-shared_array<uint8_t>
+// Returns a vector containing a DHCPv4 packet header.
+vector<uint8_t>
 generateTestPacket2() {
 generateTestPacket2() {
 
 
-    shared_array<uint8_t> buf(new uint8_t[Pkt4::DHCPV4_PKT_HDR_LEN]);
-
-    // that is only part of the header. It contains all "short" fields, 
-    // larger fields are constructed separately
+    // That is only part of the header. It contains all "short" fields,
+    // larger fields are constructed separately.
     uint8_t hdr[] = {
     uint8_t hdr[] = {
-        1, 6, 6, 13, // op, htype, hlen, hops,
+        1, 6, 6, 13,            // op, htype, hlen, hops,
         0x12, 0x34, 0x56, 0x78, // transaction-id
         0x12, 0x34, 0x56, 0x78, // transaction-id
-        0, 42, 0xff, 0xff, // 42 secs, 0xffff flags
-        192, 0, 2, 1, // ciaddr
-        1, 2, 3, 4, // yiaddr
-        192, 0, 2, 255, // siaddr
-        255, 255, 255, 255, // giaddr
+        0, 42, 0xff, 0xff,      // 42 secs, 0xffff flags
+        192, 0, 2, 1,           // ciaddr
+        1, 2, 3, 4,             // yiaddr
+        192, 0, 2, 255,         // siaddr
+        255, 255, 255, 255,     // giaddr
     };
     };
 
 
-    BOOST_STATIC_ASSERT(28 == sizeof(hdr));
-
-    size_t offset = 0;
+    // Initialize the vector with the header fields defined above.
+    vector<uint8_t> buf(hdr, hdr + sizeof(hdr));
 
 
-    memcpy(&buf[0] + offset, hdr, sizeof(hdr));
-    offset += sizeof(hdr);
+    // Append the large header fields.
+    copy(dummyMacAddr, dummyMacAddr + Pkt4::MAX_CHADDR_LEN, back_inserter(buf));
+    copy(dummySname, dummySname + Pkt4::MAX_SNAME_LEN, back_inserter(buf));
+    copy(dummyFile, dummyFile + Pkt4::MAX_FILE_LEN, back_inserter(buf));
 
 
-    memcpy(&buf[0] + offset, dummyMacAddr, 6); // chaddr is 16 bytes
-    offset += Pkt4::MAX_CHADDR_LEN;
-    memcpy(&buf[0] + offset, dummySname, 64); // sname is 64 bytes
-    offset += Pkt4::MAX_SNAME_LEN;
-    memcpy(&buf[0] + offset, dummyFile, 128);
-    offset += Pkt4::MAX_FILE_LEN;
+    // Should now have all the header, so check.  The "static_cast" is used
+    // to get round an odd bug whereby the linker appears not to find the
+    // definition of DHCPV4_PKT_HDR_LEN if it appears within an EXPECT_EQ().
+    EXPECT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN), buf.size());
 
 
     return (buf);
     return (buf);
 }
 }
@@ -232,7 +234,7 @@ TEST(Pkt4Test, fixedFieldsPack) {
 TEST(Pkt4Test, fixedFieldsUnpack) {
 TEST(Pkt4Test, fixedFieldsUnpack) {
     shared_array<uint8_t> expectedFormat = generateTestPkt2();
     shared_array<uint8_t> expectedFormat = generateTestPkt2();
 
 
-    shared_ptr<Pkt4> pkt(new Pkt4(&expectedFormat[0], 
+    shared_ptr<Pkt4> pkt(new Pkt4(&expectedFormat[0],
                                   Pkt4::DHCPV4_PKT_HDR_LEN));
                                   Pkt4::DHCPV4_PKT_HDR_LEN));
 
 
     // ok, let's check packet values
     // ok, let's check packet values
@@ -263,9 +265,11 @@ TEST(Pkt4Test, fixedFieldsUnpack) {
 // this test is for hardware addresses (htype, hlen and chaddr fields)
 // this test is for hardware addresses (htype, hlen and chaddr fields)
 TEST(Pkt4Test, hwAddr) {
 TEST(Pkt4Test, hwAddr) {
 
 
-    uint8_t mac[Pkt4::MAX_CHADDR_LEN];
+    vector<uint8_t> mac;
     uint8_t expectedChaddr[Pkt4::MAX_CHADDR_LEN];
     uint8_t expectedChaddr[Pkt4::MAX_CHADDR_LEN];
 
 
+    mac.resize(Pkt4::MAX_CHADDR_LEN);
+
     Pkt4* pkt = 0;
     Pkt4* pkt = 0;
     // let's test each hlen, from 0 till 16
     // let's test each hlen, from 0 till 16
     for (int macLen=0; macLen < Pkt4::MAX_CHADDR_LEN; macLen++) {
     for (int macLen=0; macLen < Pkt4::MAX_CHADDR_LEN; macLen++) {
@@ -277,23 +281,23 @@ TEST(Pkt4Test, hwAddr) {
             mac[i] = 128+i;
             mac[i] = 128+i;
             expectedChaddr[i] = 128+i;
             expectedChaddr[i] = 128+i;
         }
         }
-        
+
         // type and transaction doesn't matter in this test
         // type and transaction doesn't matter in this test
         pkt = new Pkt4(DHCPOFFER, 1234);
         pkt = new Pkt4(DHCPOFFER, 1234);
         pkt->setHWAddr(255-macLen*10, // just weird htype
         pkt->setHWAddr(255-macLen*10, // just weird htype
                        macLen,
                        macLen,
                        mac);
                        mac);
-        EXPECT_EQ(0, memcmp(expectedChaddr, pkt->getChaddr(), 
+        EXPECT_EQ(0, memcmp(expectedChaddr, pkt->getChaddr(),
                             Pkt4::MAX_CHADDR_LEN));
                             Pkt4::MAX_CHADDR_LEN));
 
 
 #if 0
 #if 0
         /// TODO Uncomment when ticket #1227 is implemented)
         /// TODO Uncomment when ticket #1227 is implemented)
-        EXPECT_NO_THROW( 
+        EXPECT_NO_THROW(
             pkt->pack();
             pkt->pack();
         );
         );
 
 
         // CHADDR starts at offset 28 in DHCP packet
         // CHADDR starts at offset 28 in DHCP packet
-        EXPECT_EQ(0, memcmp(pkt->getData()+28, expectedChaddr, 
+        EXPECT_EQ(0, memcmp(pkt->getData()+28, expectedChaddr,
                             Pkt4::MAX_CHADDR_LEN));
                             Pkt4::MAX_CHADDR_LEN));
 #endif
 #endif
 
 
@@ -364,7 +368,7 @@ TEST(Pkt4Test, sname) {
             sname[i] = i;
             sname[i] = i;
             expectedSname[i] = i;
             expectedSname[i] = i;
         }
         }
-        
+
         // type and transaction doesn't matter in this test
         // type and transaction doesn't matter in this test
         pkt = new Pkt4(DHCPOFFER, 1234);
         pkt = new Pkt4(DHCPOFFER, 1234);
         pkt->setSname(sname, snameLen);
         pkt->setSname(sname, snameLen);
@@ -373,7 +377,7 @@ TEST(Pkt4Test, sname) {
 
 
 #if 0
 #if 0
         /// TODO Uncomment when ticket #1227 is implemented)
         /// TODO Uncomment when ticket #1227 is implemented)
-        EXPECT_NO_THROW( 
+        EXPECT_NO_THROW(
             pkt->pack();
             pkt->pack();
         );
         );
 
 
@@ -401,7 +405,7 @@ TEST(Pkt4Test, file) {
             file[i] = i;
             file[i] = i;
             expectedFile[i] = i;
             expectedFile[i] = i;
         }
         }
-        
+
         // type and transaction doesn't matter in this test
         // type and transaction doesn't matter in this test
         pkt = new Pkt4(DHCPOFFER, 1234);
         pkt = new Pkt4(DHCPOFFER, 1234);
         pkt->setFile(file, fileLen);
         pkt->setFile(file, fileLen);
@@ -410,7 +414,7 @@ TEST(Pkt4Test, file) {
 
 
 #if 0
 #if 0
         /// TODO Uncomment when ticket #1227 is implemented)
         /// TODO Uncomment when ticket #1227 is implemented)
-        EXPECT_NO_THROW( 
+        EXPECT_NO_THROW(
             pkt->pack();
             pkt->pack();
         );
         );