main.cc 7.01 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Copyright (C) 2009  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.

// $Id$

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>

#include <cassert>
#include <iostream>

#include <boost/foreach.hpp>

#include <asiolink/asiolink.h>

#include <exceptions/exceptions.h>

#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>

#include <cc/session.h>
#include <cc/data.h>
#include <config/ccsession.h>

#include <xfr/xfrout_client.h>

44
45
46
#include <auth/change_user.h>
#include <auth/common.h>

47
48
49
50
51
52
53
54
55
56
#include <recurse/spec_config.h>
#include <recurse/recursor.h>

using namespace std;
using namespace isc::cc;
using namespace isc::config;
using namespace asiolink;

namespace {

57
static bool verbose_mode = false;
58

Evan Hunt's avatar
Evan Hunt committed
59
// Default port current 5300 for testing purposes
60
61
static const string PROGRAM = "Recurse";
static const char* DNSPORT = "5300";
62

63
IOService io_service;
64
static Recursor *recursor;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

ConstElementPtr
my_config_handler(ConstElementPtr new_config) {
    return (recursor->updateConfig(new_config));
}

ConstElementPtr
my_command_handler(const string& command, ConstElementPtr args) {
    ConstElementPtr answer = createAnswer();

    if (command == "print_message") {
        cout << args << endl;
        /* let's add that message to our answer as well */
        answer = createAnswer(0, args);
    } else if (command == "shutdown") {
80
        io_service.stop();
81
82
83
84
85
86
87
    }
    
    return (answer);
}

void
usage() {
Evan Hunt's avatar
Evan Hunt committed
88
    cerr << "Usage:  b10-recurse -f nameserver [-a address] [-p port] [-u user]"
89
90
91
92
                     "[-4|-6] [-v]" << endl;
    cerr << "\t-f: specify the nameserver to which queries should be forwarded"
         << endl;
    cerr << "\t-a: specify the address to listen on (default: all)" << endl;
Evan Hunt's avatar
Evan Hunt committed
93
94
    cerr << "\t-p: specify the port to listen on (default: " << DNSPORT << ")"
         << endl;
95
    cerr << "\t-4: listen on all IPv4 addresses (incompatible with -a)" << endl;
Evan Hunt's avatar
Evan Hunt committed
96
    cerr << "\t-6: listen on all IPv6 addresses (incompatible with -a)" << endl;
97
98
    cerr << "\t-u: change process UID to the specified user" << endl;
    cerr << "\t-v: verbose output" << endl;
99
100
101
102
103
104
105
106
107
    exit(1);
}
} // end of anonymous namespace

int
main(int argc, char* argv[]) {
    int ch;
    const char* port = DNSPORT;
    const char* address = NULL;
108
    const char* forward = NULL;
109
    const char* uid = NULL;
110
    bool use_ipv4 = true, use_ipv6 = true;
111

112
    while ((ch = getopt(argc, argv, "46a:f:p:u:v")) != -1) {
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
        switch (ch) {
        case '4':
            // Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
            // not "use_ipv4".  We could use something like "ipv4_only", but
            // we found the negatively named variable could confuse the code
            // logic.
            use_ipv6 = false;
            break;
        case '6':
            // The same note as -4 applies.
            use_ipv4 = false;
            break;
        case 'a':
            address = optarg;
            break;
128
129
130
        case 'f':
            forward = optarg;
            break;
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
        case 'p':
            port = optarg;
            break;
        case 'u':
            uid = optarg;
            break;
        case 'v':
            verbose_mode = true;
            break;
        case '?':
        default:
            usage();
        }
    }

    if (argc - optind > 0) {
        usage();
    }

    if (!use_ipv4 && !use_ipv6) {
151
152
        cerr << "[b10-auth] Error: Cannot specify both -4 and -6 "
             << "at the same time" << endl;
153
154
155
156
        usage();
    }

    if ((!use_ipv4 || !use_ipv6) && address != NULL) {
157
158
        cerr << "[b10-auth] Error: Cannot specify -4 or -6 "
             << "at the same time as -a" << endl;
159
160
161
        usage();
    }

162
163
164
165
166
    if (forward == NULL) {
        cerr << "[b10-recurse] No forward name server specified" << endl;
        usage();
    }

167
168
169
170
171
172
173
174
175
176
177
178
179
180
    int ret = 0;

    // XXX: we should eventually pass io_service here.
    Session* cc_session = NULL;
    ModuleCCSession* config_session = NULL;
    try {
        string specfile;
        if (getenv("B10_FROM_BUILD")) {
            specfile = string(getenv("B10_FROM_BUILD")) +
                "/src/bin/recurse/recurse.spec";
        } else {
            specfile = string(RECURSE_SPECFILE_LOCATION);
        }

181
        recursor = new Recursor(*forward);
182
        recursor->setVerbose(verbose_mode);
183
184
        cout << "[b10-recurse] Server created." << endl;

185
        SimpleCallback* checkin = recursor->getCheckinProvider();
186
187
        DNSLookup* lookup = recursor->getDNSLookupProvider();
        DNSAnswer* answer = recursor->getDNSAnswerProvider();
188

189
190
        DNSService* dns_service;

191
192
193
194
195
196
197
        if (address != NULL) {
            // XXX: we can only specify at most one explicit address.
            // This also means the server cannot run in the dual address
            // family mode if explicit addresses need to be specified.
            // We don't bother to fix this problem, however.  The -a option
            // is a short term workaround until we support dynamic listening
            // port allocation.
198
199
            dns_service = new DNSService(io_service, *port, *address,
                                         checkin, lookup, answer);
200
        } else {
201
202
            dns_service = new DNSService(io_service, *port, use_ipv4, use_ipv6,
                                         checkin, lookup, answer);
203
        }
204
        recursor->setDNSService(*dns_service);
205
206
        cout << "[b10-recurse] IOService created." << endl;

207
        cc_session = new Session(io_service.get_io_service());
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
        cout << "[b10-recurse] Configuration session channel created." << endl;

        config_session = new ModuleCCSession(specfile, *cc_session,
                                             my_config_handler,
                                             my_command_handler);
        cout << "[b10-recurse] Configuration channel established." << endl;

        if (uid != NULL) {
            changeUser(uid);
        }

        recursor->setConfigSession(config_session);
        recursor->updateConfig(ElementPtr());

        cout << "[b10-recurse] Server started." << endl;
223
        io_service.run();
224
225
226
227
228
229
230
231
232
233
234
    } catch (const std::exception& ex) {
        cerr << "[b10-recurse] Server failed: " << ex.what() << endl;
        ret = 1;
    }

    delete config_session;
    delete cc_session;
    delete recursor;

    return (ret);
}