Ticket #167: 167.diff

File 167.diff, 16.9 KB (added by each, 9 years ago)

diff against current trunk

  • src/bin/auth/asio_link.cc

    diff -r e30eeac8aadf src/bin/auth/asio_link.cc
    a b  
    1818
    1919#include <unistd.h>             // for some IPC/network system calls
    2020#include <asio.hpp>
     21#include <boost/lexical_cast.hpp>
    2122#include <boost/bind.hpp>
    2223
    2324#include <dns/buffer.h>
     
    3031
    3132#include "spec_config.h"        // for XFROUT.  should not be here.
    3233#include "auth_srv.h"
     34#include "common.h"
    3335
    3436using namespace asio;
    3537using ip::udp;
     
    200202class TCPServer {
    201203public:
    202204    TCPServer(AuthSrv* auth_server, io_service& io_service,
    203               int af, short port) :
     205              int af, uint16_t port) :
    204206        auth_server_(auth_server), io_service_(io_service),
    205207        acceptor_(io_service_), listening_(new TCPClient(auth_server_,
    206208                                                         io_service_))
     
    220222                                           listening_, placeholders::error));
    221223    }
    222224
     225    TCPServer(AuthSrv* auth_server, io_service& io_service,
     226              asio::ip::address addr, uint16_t port) :
     227        auth_server_(auth_server),
     228        io_service_(io_service), acceptor_(io_service_),
     229        listening_(new TCPClient(auth_server, io_service_))
     230    {
     231        tcp::endpoint endpoint(addr, port);
     232        acceptor_.open(endpoint.protocol());
     233
     234        acceptor_.set_option(tcp::acceptor::reuse_address(true));
     235        acceptor_.bind(endpoint);
     236        acceptor_.listen();
     237        acceptor_.async_accept(listening_->getSocket(),
     238                               boost::bind(&TCPServer::handleAccept, this,
     239                                           listening_, placeholders::error));
     240    }
     241
    223242    ~TCPServer() { delete listening_; }
    224243
    225244    void handleAccept(TCPClient* new_client,
     
    248267class UDPServer {
    249268public:
    250269    UDPServer(AuthSrv* auth_server, io_service& io_service,
    251               int af, short port) :
     270              int af, uint16_t port) :
    252271        auth_server_(auth_server),
    253272        io_service_(io_service),
    254273        socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
     
    267286        startReceive();
    268287    }
    269288
     289    UDPServer(AuthSrv* auth_server, io_service& io_service,
     290              asio::ip::address addr, uint16_t port) :
     291        auth_server_(auth_server), io_service_(io_service),
     292        socket_(io_service, addr.is_v6() ? udp::v6() : udp::v4()),
     293        response_buffer_(0),
     294        response_renderer_(response_buffer_),
     295        dns_message_(Message::PARSE)
     296    {
     297        socket_.bind(udp::endpoint(addr, port));
     298        startReceive();
     299    }
     300
    270301    void handleRequest(const asio::error_code& error,
    271302                       size_t bytes_recvd)
    272303    {
     
    347378
    348379class IOServiceImpl {
    349380public:
    350     IOServiceImpl(AuthSrv* auth_server, const char* port,
     381    IOServiceImpl(AuthSrv* auth_server, const char* address, const char* port,
    351382                  const bool use_ipv4, const bool use_ipv6);
    352383    ~IOServiceImpl();
    353384    asio::io_service io_service_;
     
    358389    TCPServer* tcp6_server_;
    359390};
    360391
    361 IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char* const port,
    362                              const bool use_ipv4, const bool use_ipv6) :
     392IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char* const address,
     393                             const char* const port, const bool use_ipv4,
     394                             const bool use_ipv6) :
    363395    auth_server_(auth_server), udp4_server_(NULL), udp6_server_(NULL),
    364396    tcp4_server_(NULL), tcp6_server_(NULL)
    365397{
    366398    ServerSet servers;
    367     short portnum = atoi(port);
     399    uint16_t portnum = atoi(port);
    368400
    369     if (use_ipv4) {
    370         servers.udp4_server = new UDPServer(auth_server, io_service_,
    371                                             AF_INET, portnum);
    372         servers.tcp4_server = new TCPServer(auth_server, io_service_,
    373                                             AF_INET, portnum);
     401    try {
     402        portnum = boost::lexical_cast<uint16_t>(port);
     403    } catch (const std::exception& ex) {
     404        isc_throw(FatalError, "[b10-auth] Invalid port number '"
     405                              << port << "'");
    374406    }
    375     if (use_ipv6) {
    376         servers.udp6_server = new UDPServer(auth_server, io_service_,
    377                                             AF_INET6, portnum);
    378         servers.tcp6_server = new TCPServer(auth_server, io_service_,
    379                                             AF_INET6, portnum);
     407
     408    if (address != NULL) {
     409        asio::ip::address addr = asio::ip::address::from_string(address);
     410
     411        if ((addr.is_v6() && !use_ipv6)) {
     412            isc_throw(FatalError,
     413                      "[b10-auth] Error: -4 conflicts with " << addr);
     414        }
     415
     416        if ((addr.is_v4() && !use_ipv4)) {
     417            isc_throw(FatalError,
     418                      "[b10-auth] Error: -6 conflicts with " << addr);
     419        }
     420
     421        if (addr.is_v4()) {
     422            servers.udp4_server = new UDPServer(auth_server, io_service_,
     423                                                addr, portnum);
     424            servers.tcp4_server = new TCPServer(auth_server, io_service_,
     425                                                addr, portnum);
     426         } else {
     427            servers.udp6_server = new UDPServer(auth_server, io_service_,
     428                                                addr, portnum);
     429            servers.tcp6_server = new TCPServer(auth_server, io_service_,
     430                                                addr, portnum);
     431        }
     432    } else {
     433        if (use_ipv4) {
     434            servers.udp4_server = new UDPServer(auth_server, io_service_,
     435                                                AF_INET, portnum);
     436            servers.tcp4_server = new TCPServer(auth_server, io_service_,
     437                                                AF_INET, portnum);
     438        }
     439        if (use_ipv6) {
     440            servers.udp6_server = new UDPServer(auth_server, io_service_,
     441                                                AF_INET6, portnum);
     442            servers.tcp6_server = new TCPServer(auth_server, io_service_,
     443                                                AF_INET6, portnum);
     444        }
    380445    }
    381446
    382447    // Now we don't have to worry about exception, and need to make sure that
     
    394459    delete tcp6_server_;
    395460}
    396461
    397 IOService::IOService(AuthSrv* auth_server, const char* const port,
    398                      const bool use_ipv4, const bool use_ipv6) {
    399     impl_ = new IOServiceImpl(auth_server, port, use_ipv4, use_ipv6);
     462IOService::IOService(AuthSrv* auth_server, const char* const address,
     463                     const char* const port, const bool use_ipv4,
     464                     const bool use_ipv6) {
     465    impl_ = new IOServiceImpl(auth_server, address, port, use_ipv4, use_ipv6);
    400466}
    401467
    402468IOService::~IOService() {
  • src/bin/auth/asio_link.h

    diff -r e30eeac8aadf src/bin/auth/asio_link.h
    a b  
    2424
    2525class IOService {
    2626public:
    27     IOService(AuthSrv* auth_server, const char* const port,
     27    IOService(AuthSrv* auth_server,
     28              const char* const address, const char* const port,
    2829              const bool use_ipv4, const bool use_ipv6);
    2930    ~IOService();
    3031    void run();
  • src/bin/auth/main.cc

    diff -r e30eeac8aadf src/bin/auth/main.cc
    a b  
    9595main(int argc, char* argv[]) {
    9696    int ch;
    9797    const char* port = DNSPORT;
     98    const char* address = NULL;
    9899    bool use_ipv4 = true, use_ipv6 = true, cache = true;
    99100
    100101    while ((ch = getopt(argc, argv, "46np:v")) != -1) {
     
    113114        case 'n':
    114115            cache = false;
    115116            break;
     117        case 'a':
     118            address = optarg;
     119            break;
    116120        case 'p':
    117121            port = optarg;
    118122            break;
     
    148152        auth_server = new AuthSrv(cache);
    149153        auth_server->setVerbose(verbose_mode);
    150154
    151         io_service = new asio_link::IOService(auth_server, port, use_ipv4,
    152                                               use_ipv6);
     155        io_service = new asio_link::IOService(auth_server, address, port,
     156                                              use_ipv4, use_ipv6);
    153157
    154158        ModuleCCSession cs(specfile, io_service->get_io_service(),
    155159                           my_config_handler, my_command_handler);
  • src/bin/bind10/bind10.py.in

    diff -r e30eeac8aadf src/bin/bind10/bind10.py.in
    a b  
    5656import time
    5757import select
    5858import random
     59import socket
    5960from optparse import OptionParser, OptionValueError
    6061import io
    6162import pwd
     
    173174    def respawn(self):
    174175        self._spawn()
    175176
     177class IPAddr:
     178    """Stores an IPv4 or IPv6 address."""
     179    family = None
     180    addr = None
     181
     182    def __init__(self, addr):
     183        try:
     184            a = socket.inet_pton(socket.AF_INET, addr)
     185            self.family = socket.AF_INET
     186            self.addr = a
     187            return
     188        except:
     189            pass
     190
     191        try:
     192            a = socket.inet_pton(socket.AF_INET6, addr)
     193            self.family = socket.AF_INET6
     194            self.addr = a
     195            return
     196        except Exception as e:
     197            raise e
     198   
     199    def __str__(self):
     200        return socket.inet_ntop(self.family, self.addr)
     201
    176202class BoB:
    177203    """Boss of BIND class."""
    178204   
    179     def __init__(self, msgq_socket_file=None, auth_port=5300, nocache=False,
    180                  verbose=False, setuid=None, username=None):
     205    def __init__(self, msgq_socket_file=None, auth_port=5300, address='',
     206                 nocache=False, verbose=False, setuid=None, username=None):
    181207        """Initialize the Boss of BIND. This is a singleton (only one
    182208        can run).
    183209       
     
    188214        self.verbose = verbose
    189215        self.msgq_socket_file = msgq_socket_file
    190216        self.auth_port = auth_port
     217        self.address = None
     218        if address:
     219            self.address = IPAddr(address)
    191220        self.cc_session = None
    192221        self.ccs = None
    193222        self.processes = {}
     
    303332        # start b10-auth
    304333        # XXX: this must be read from the configuration manager in the future
    305334        authargs = ['b10-auth', '-p', str(self.auth_port)]
     335        if self.address:
     336            authargs += ['-a', str(self.address)]
    306337        if self.nocache:
    307338            authargs += ['-n']
    308339        if self.verbose:
    309             sys.stdout.write("[bind10] Starting b10-auth using port %d\n" %
     340            authargs += ['-v']
     341            sys.stdout.write("Starting b10-auth using port %d" %
    310342                             self.auth_port)
    311             authargs += ['-v']
     343            if self.address:
     344                sys.stdout.write(" on %s" % str(self.address))
     345            sys.stdout.write("\n")
    312346        try:
    313347            auth = ProcessInfo("b10-auth", authargs,
    314348                               c_channel_env)
     
    549583    else:
    550584        raise OptionValueError("Unknown option " + opt_str)
    551585 
     586def check_addr(option, opt_str, value, parser):
     587    """Function to insure that the address we are passed is actually
     588    a valid address. Used by OptionParser() on startup."""
     589    try:
     590        IPAddr(value)
     591    except:
     592        raise OptionValueError("%s requires a valid IPv4 or IPv6 address" % opt_str)
     593    if (opt_str == '-a' or opt_str == '--address'):
     594        parser.values.address = value
     595    else:
     596        raise OptionValueError("Unknown option " + opt_str)
     597 
    552598def main():
    553599    global options
    554600    global boss_of_bind
     
    558604
    559605    # Parse any command-line options.
    560606    parser = OptionParser(version=__version__)
    561     parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
    562                       help="display more about what is going on")
     607    parser.add_option("-a", "--address", dest="address", type="string",
     608                      action="callback", callback=check_addr, default='',
     609                      help="address the b10-auth daemon will use (default: listen on all addresses)")
     610    parser.add_option("-m", "--msgq-socket-file", dest="msgq_socket_file",
     611                      type="string", default=None,
     612                      help="UNIX domain socket file the b10-msgq daemon will use")
    563613    parser.add_option("-n", "--no-cache", action="store_true", dest="nocache",
    564614                      default=False, help="disable hot-spot cache in b10-auth")
    565615    parser.add_option("-p", "--port", dest="auth_port", type="string",
    566616                      action="callback", callback=check_port, default="5300",
    567617                      help="port the b10-auth daemon will use (default 5300)")
    568     parser.add_option("-m", "--msgq-socket-file", dest="msgq_socket_file",
    569                       type="string", default=None,
    570                       help="UNIX domain socket file the b10-msgq daemon will use")
    571618    parser.add_option("-u", "--user", dest="user",
    572619                      type="string", default=None,
    573620                      help="Change user after startup (must run as root)")
     621    parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
     622                      help="display more about what is going on")
    574623    (options, args) = parser.parse_args()
    575624    if args:
    576625        parser.print_help()
     
    626675
    627676    # Go bob!
    628677    boss_of_bind = BoB(options.msgq_socket_file, int(options.auth_port),
    629                        options.nocache, options.verbose, setuid, username)
     678                       options.address, options.nocache, options.verbose,
     679                       setuid, username)
    630680    startup_result = boss_of_bind.startup()
    631681    if startup_result:
    632682        sys.stderr.write("[bind10] Error on startup: %s\n" % startup_result)
  • src/bin/bind10/tests/bind10_test.py

    diff -r e30eeac8aadf src/bin/bind10/tests/bind10_test.py
    a b  
    1 from bind10 import ProcessInfo, BoB
     1from bind10 import ProcessInfo, BoB, IPAddr
    22
    33# XXX: environment tests are currently disabled, due to the preprocessor
    44#      setup that we have now complicating the environment
     
    77import sys
    88import os
    99import signal
     10import socket
    1011
    1112class TestProcessInfo(unittest.TestCase):
    1213    def setUp(self):
     
    7172        self.assertTrue(type(pi.pid) is int)
    7273        self.assertNotEqual(pi.pid, old_pid)
    7374
     75class TestIPAddr(unittest.TestCase):
     76    def test_v6ok(self):
     77        addr = IPAddr('2001:4f8::1')
     78        self.assertEqual(addr.family, socket.AF_INET6)
     79        self.assertEqual(addr.addr, socket.inet_pton(socket.AF_INET6, '2001:4f8::1'))
     80
     81    def test_v4ok(self):
     82        addr = IPAddr('127.127.127.127')
     83        self.assertEqual(addr.family, socket.AF_INET)
     84        self.assertEqual(addr.addr, socket.inet_aton('127.127.127.127'))
     85
     86    def test_badaddr(self):
     87        self.assertRaises(socket.error, IPAddr, 'foobar')
     88        self.assertRaises(socket.error, IPAddr, 'foo::bar')
     89        self.assertRaises(socket.error, IPAddr, '123')
     90        self.assertRaises(socket.error, IPAddr, '123.456.789.0')
     91        self.assertRaises(socket.error, IPAddr, '127/8')
     92        self.assertRaises(socket.error, IPAddr, '0/0')
     93        self.assertRaises(socket.error, IPAddr, '1.2.3.4/32')
     94        self.assertRaises(socket.error, IPAddr, '0')
     95        self.assertRaises(socket.error, IPAddr, '')
     96
    7497class TestBoB(unittest.TestCase):
    7598    def test_init(self):
    7699        bob = BoB()
    77100        self.assertEqual(bob.verbose, False)
    78101        self.assertEqual(bob.msgq_socket_file, None)
     102        self.assertEqual(bob.auth_port, 5300)
    79103        self.assertEqual(bob.cc_session, None)
     104        self.assertEqual(bob.address, None)
    80105        self.assertEqual(bob.processes, {})
    81106        self.assertEqual(bob.dead_processes, {})
    82107        self.assertEqual(bob.runnable, False)
     
    90115        self.assertEqual(bob.dead_processes, {})
    91116        self.assertEqual(bob.runnable, False)
    92117
     118    def test_init_alternate_auth_port(self):
     119        bob = BoB(None, 9999)
     120        self.assertEqual(bob.verbose, False)
     121        self.assertEqual(bob.msgq_socket_file, None)
     122        self.assertEqual(bob.auth_port, 9999)
     123        self.assertEqual(bob.cc_session, None)
     124        self.assertEqual(bob.address, None)
     125        self.assertEqual(bob.processes, {})
     126        self.assertEqual(bob.dead_processes, {})
     127        self.assertEqual(bob.runnable, False)
     128
     129    def test_init_alternate_address(self):
     130        bob = BoB(None, 5300, '127.127.127.127')
     131        self.assertEqual(bob.verbose, False)
     132        self.assertEqual(bob.auth_port, 5300)
     133        self.assertEqual(bob.msgq_socket_file, None)
     134        self.assertEqual(bob.cc_session, None)
     135        self.assertEqual(bob.address.addr, socket.inet_aton('127.127.127.127'))
     136        self.assertEqual(bob.processes, {})
     137        self.assertEqual(bob.dead_processes, {})
     138        self.assertEqual(bob.runnable, False)
    93139    # verbose testing...
    94140
    95141if __name__ == '__main__':