option6_ia.cc 4.41 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <stdint.h>
#include <arpa/inet.h>
#include <sstream>
#include "exceptions/exceptions.h"

20
21
22
23
#include "dhcp/libdhcp.h"
#include "dhcp/option6_ia.h"
#include "dhcp/dhcp6.h"
#include "util/io_utilities.h"
24
25
26
27

using namespace std;
using namespace isc;
using namespace isc::dhcp;
28
using namespace isc::util;
29

30
31
Option6IA::Option6IA(unsigned short type, unsigned int iaid)
    :Option(Option::V6, type), iaid_(iaid) {
32
33
}

34
Option6IA::Option6IA(unsigned short type,
35
36
37
38
                     const boost::shared_array<uint8_t>& buf,
                     unsigned int buf_len,
                     unsigned int offset,
                     unsigned int option_len)
39
    :Option(Option::V6, type) {
40
41
42
43
    unpack(buf, buf_len, offset, option_len);
}

unsigned int
44
Option6IA::pack(boost::shared_array<uint8_t>& buf,
45
46
                unsigned int buf_len,
                unsigned int offset) {
47
    if (offset + len() > buf_len) {
48
        isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
49
50
                  << ", buffer=" << buf_len << ": too small buffer.");
    }
51

52
53
54
55
56
    if (len() < 16 ) {
        isc_throw(OutOfRange, "Attempt to build malformed IA option: len="
                  << len() << " is too small (at least 16 is required).");
    }

57
58
59
60
61
62
63
    writeUint16(type_, &buf[offset]);
    offset += sizeof(uint16_t);

    writeUint16(len() - OPTION6_HDR_LEN, &buf[offset]);
    offset += sizeof(uint16_t);

    /// TODO start using writeUint32 once such function is implemented
64
65
    uint8_t* ptr = &buf[offset];

66
    *(uint32_t*)ptr = htonl(iaid_);
67
    ptr += sizeof(uint32_t);
68
69

    *(uint32_t*)ptr = htonl(t1_);
70
    ptr += sizeof(uint32_t);
71
72

    *(uint32_t*)ptr = htonl(t2_);
73
    ptr += sizeof(uint32_t);
74

75
    offset = LibDHCP::packOptions6(buf, buf_len, offset+12, options_);
76
77
78
    return offset;
}

79
unsigned int
80
Option6IA::unpack(const boost::shared_array<uint8_t>& buf,
81
                  unsigned int buf_len,
82
                  unsigned int offset,
83
                  unsigned int parse_len) {
84
    if ( parse_len < OPTION6_IA_LEN || offset + OPTION6_IA_LEN > buf_len) {
85
86
        isc_throw(OutOfRange, "Option " << type_ << " truncated");
    }
87
88
89
90

    /// TODO this will cause SIGBUS on sparc if we happen to read misaligned
    /// memory access. We need to fix this (and similar code) as part of
    /// the ticket #1313
91
    iaid_ = ntohl(*(uint32_t*)&buf[offset]);
92
    offset += sizeof(uint32_t);
93
    t1_ = ntohl(*(uint32_t*)&buf[offset]);
94
    offset += sizeof(uint32_t);
95
    t2_ = ntohl(*(uint32_t*)&buf[offset]);
96
    offset += sizeof(uint32_t);
97
    offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
98
                                     parse_len - OPTION6_IA_LEN, options_);
99
100
101
102

    return (offset);
}

103
std::string Option6IA::toText(int indent /* = 0*/) {
104
    stringstream tmp;
105
106
107

    for (int i=0; i<indent; i++)
        tmp << " ";
108
    tmp << "type=" << type_;
109

110
111
    switch (type_) {
    case D6O_IA_NA:
112
        tmp << "(IA_NA)";
113
114
        break;
    case D6O_IA_PD:
115
        tmp << "(IA_PD)";
116
        break;
117
118
    default:
        tmp << "(unknown)";
119
    }
120
    tmp << " iaid=" << iaid_ << ", t1=" << t1_ << ", t2=" << t2_
121
        << " " << options_.size() << " sub-options:" << endl;
122

123
124
    for (Option6Collection::const_iterator opt=options_.begin();
         opt!=options_.end();
125
         ++opt) {
126
        tmp << (*opt).second->toText(indent+2);
127
128
129
130
131
    }
    return tmp.str();
}

unsigned short Option6IA::len() {
132

133
134
    unsigned short length = OPTION6_HDR_LEN /*header (4)*/ +
        OPTION6_IA_LEN  /* option content (12) */;
135
136

    // length of all suboptions
137
138
    for (Option::Option6Collection::iterator it = options_.begin();
         it != options_.end();
139
140
141
142
143
         ++it) {
        length += (*it).second->len();
    }
    return (length);
}