dhcp6_srv.cc 8.04 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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.

15
16
17
18
19
20
21
22
#include <dhcp/dhcp6.h>
#include <dhcp/pkt6.h>
#include <dhcp6/iface_mgr.h>
#include <dhcp6/dhcp6_srv.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
#include <asiolink/io_address.h>
#include <exceptions/exceptions.h>
23
24
25

using namespace std;
using namespace isc;
26
27
using namespace isc::dhcp;
using namespace isc::asiolink;
28

Tomek Mrugalski's avatar
Tomek Mrugalski committed
29
30
31
Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {

//void Dhcpv6Srv::Dhcpv6Srv_impl(uint16_t port) {
32
    cout << "Initialization" << endl;
33

Tomek Mrugalski's avatar
Tomek Mrugalski committed
34
35
    // First call to instance() will create IfaceMgr (it's a singleton).
    // It may throw something if things go wrong.
36
    IfaceMgr::instance();
37

Tomek Mrugalski's avatar
Tomek Mrugalski committed
38
39
    // Now try to open IPv6 sockets on detected interfaces.
    IfaceMgr::instance().openSockets(port);
40

41
42
43
    /// @todo: instantiate LeaseMgr here once it is imlpemented.

    setServerID();
44
45

    shutdown = false;
46
47
}

48
49
Dhcpv6Srv::~Dhcpv6Srv() {
    cout << "DHCPv6 Srv shutdown." << endl;
50
51

    IfaceMgr::instance().closeSockets();
52
53
}

54
55
bool
Dhcpv6Srv::run() {
56
    while (!shutdown) {
57
58
        boost::shared_ptr<Pkt6> query; // client's message
        boost::shared_ptr<Pkt6> rsp;   // server's response
59

60
        query = IfaceMgr::instance().receive6();
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
        if (query) {
            if (!query->unpack()) {
                cout << "Failed to parse incoming packet" << endl;
                continue;
            }
            switch (query->getType()) {
            case DHCPV6_SOLICIT:
                rsp = processSolicit(query);
                break;
            case DHCPV6_REQUEST:
                rsp = processRequest(query);
                break;
            case DHCPV6_RENEW:
                rsp = processRenew(query);
                break;
            case DHCPV6_REBIND:
                rsp = processRebind(query);
                break;
            case DHCPV6_CONFIRM:
                rsp = processConfirm(query);
                break;
            case DHCPV6_RELEASE:
                rsp = processRelease(query);
                break;
            case DHCPV6_DECLINE:
                rsp = processDecline(query);
                break;
89
90
91
            case DHCPV6_INFORMATION_REQUEST:
                rsp = processInfRequest(query);
                break;
92
93
94
95
96
97
98
            default:
                cout << "Unknown pkt type received:"
                     << query->getType() << endl;
            }

            cout << "Received " << query->data_len_ << " bytes packet type="
                 << query->getType() << endl;
99
            cout << query->toText();
100
            if (rsp) {
101
102
103
104
105
                rsp->remote_addr_ = query->remote_addr_;
                rsp->local_addr_ = query->local_addr_;
                rsp->remote_port_ = DHCP6_CLIENT_PORT;
                rsp->local_port_ = DHCP6_SERVER_PORT;
                rsp->ifindex_ = query->ifindex_;
106
                rsp->iface_ = query->iface_;
107
108
109
110
111
112
                cout << "Replying with:" << rsp->getType() << endl;
                cout << rsp->toText();
                cout << "----" << endl;
                if (rsp->pack()) {
                    cout << "#### pack successful." << endl;
                }
113
114
                IfaceMgr::instance().send(rsp);
            }
115
116
        }

117
118
        // TODO add support for config session (see src/bin/auth/main.cc)
        //      so this daemon can be controlled from bob
119
120
    }

121
    return (true);
122
}
123

124
void
125
126
127
128
Dhcpv6Srv::setServerID() {
    /// TODO implement this for real once interface detection is done.
    /// Use hardcoded server-id for now

129
    boost::shared_array<uint8_t> srvid(new uint8_t[14]);
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    srvid[0] = 0;
    srvid[1] = 1; // DUID type 1 = DUID-LLT (see section 9.2 of RFC3315)
    srvid[2] = 0;
    srvid[3] = 6; // HW type = ethernet (I think. I'm typing this from my head
                  // in hotel, without Internet connection)
    for (int i=4; i<14; i++) {
        srvid[i]=i-4;
    }
    serverid_ = boost::shared_ptr<Option>(new Option(Option::V6,
                                                     D6O_SERVERID,
                                                     srvid,
                                                     0, 14));
}

144
boost::shared_ptr<Pkt6>
145
Dhcpv6Srv::processSolicit(boost::shared_ptr<Pkt6> solicit) {
146
147
148
149
150

    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_ADVERTISE,
                                           solicit->getTransid(),
                                           Pkt6::UDP));

151
152
    /// TODO Rewrite this once LeaseManager is implemented.

153
    // answer client's IA (this is mostly a dummy,
154
155
156
157
    // so let's answer only first IA and hope there is only one)
    boost::shared_ptr<Option> ia_opt = solicit->getOption(D6O_IA_NA);
    if (ia_opt) {
        // found IA
158
159
        Option* tmp = ia_opt.get();
        Option6IA* ia_req = dynamic_cast<Option6IA*>(tmp);
160
        if (ia_req) {
161
            boost::shared_ptr<Option6IA>
162
                ia_rsp(new Option6IA(D6O_IA_NA, ia_req->getIAID()));
163
164
            ia_rsp->setT1(1500);
            ia_rsp->setT2(2600);
165
166
167
168
            boost::shared_ptr<Option6IAAddr>
                addr(new Option6IAAddr(D6O_IAADDR,
                                       IOAddress("2001:db8:1234:5678::abcd"),
                                       5000, 7000));
169
170
171
172
173
174
175
            ia_rsp->addOption(addr);
            reply->addOption(ia_rsp);
        }
    }

    // add client-id
    boost::shared_ptr<Option> clientid = solicit->getOption(D6O_CLIENTID);
176
177
178
    if (clientid) {
        reply->addOption(clientid);
    }
179
180

    // add server-id
181
    reply->addOption(getServerID());
182
183
184
185
    return reply;
}

boost::shared_ptr<Pkt6>
186
Dhcpv6Srv::processRequest(boost::shared_ptr<Pkt6> request) {
187
188
189
    /// TODO: Implement processRequest() for real
    boost::shared_ptr<Pkt6> reply = processSolicit(request);
    reply->setType(DHCPV6_REPLY);
190
191
192
193
    return reply;
}

boost::shared_ptr<Pkt6>
194
Dhcpv6Srv::processRenew(boost::shared_ptr<Pkt6> renew) {
195
196
197
198
199
200
201
    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
                                           renew->getTransid(),
                                           Pkt6::UDP));
    return reply;
}

boost::shared_ptr<Pkt6>
202
Dhcpv6Srv::processRebind(boost::shared_ptr<Pkt6> rebind) {
203
204
205
206
207
208
209
    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
                                           rebind->getTransid(),
                                           Pkt6::UDP));
    return reply;
}

boost::shared_ptr<Pkt6>
210
Dhcpv6Srv::processConfirm(boost::shared_ptr<Pkt6> confirm) {
211
212
213
214
215
216
217
    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
                                           confirm->getTransid(),
                                           Pkt6::UDP));
    return reply;
}

boost::shared_ptr<Pkt6>
218
Dhcpv6Srv::processRelease(boost::shared_ptr<Pkt6> release) {
219
220
221
222
223
224
225
    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
                                           release->getTransid(),
                                           Pkt6::UDP));
    return reply;
}

boost::shared_ptr<Pkt6>
226
Dhcpv6Srv::processDecline(boost::shared_ptr<Pkt6> decline) {
227
228
229
230
231
    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
                                           decline->getTransid(),
                                           Pkt6::UDP));
    return reply;
}
232

233
boost::shared_ptr<Pkt6>
234
Dhcpv6Srv::processInfRequest(boost::shared_ptr<Pkt6> infRequest) {
235
236
237
238
239
    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
                                           infRequest->getTransid(),
                                           Pkt6::UDP));
    return reply;
}