Opened 6 years ago

Last modified 3 years ago

#3188 new enhancement

socket creator support for raw sockets

Reported by: shane Owned by:
Priority: medium Milestone: Outstanding Tasks
Component: sockcreator Version:
Keywords: Cc:
CVSS Scoring: Parent Tickets:
Sensitive: no Defect Severity: N/A
Sub-Project: Core Feature Depending on Ticket:
Estimated Difficulty: 5 Add Hours to Ticket: 0
Total Hours: 0 Internal?: no

Description (last modified by tomek)

The DHCP team needs to have support for raw sockets in the socket creator.

Currently this is done directly in the code (iface_mgr_linux.cc):

    fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd_ < 0) {
        isc_throw(Unexpected, "Failed to create NETLINK socket.");
    }

    if (setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &SNDBUF_SIZE, sizeof(SNDBUF_SIZE)) < 0) {
        isc_throw(Unexpected, "Failed to set send buffer in NETLINK socket.");
    }

    if (setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &RCVBUF_SIZE, sizeof(RCVBUF_SIZE)) < 0) {
        isc_throw(Unexpected, "Failed to set receive buffer in NETLINK socket.");
    }

    local_.nl_family = AF_NETLINK;
    local_.nl_groups = 0;

    if (bind(fd_, convertSockAddr(&local_), sizeof(local_)) < 0) {
        isc_throw(Unexpected, "Failed to bind netlink socket.");
    }

Or in pkt_filter_lpf:

    int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sock < 0) {
        isc_throw(SocketConfigError, "Failed to create raw LPF socket");
    }

    // Create socket filter program. This program will only allow incoming UDP
    // traffic which arrives on the specific (DHCP) port). It will also filter
    // out all fragmented packets.
    struct sock_fprog filter_program;
    memset(&filter_program, 0, sizeof(filter_program));

    filter_program.filter = dhcp_sock_filter;
    filter_program.len = sizeof(dhcp_sock_filter) / sizeof(struct sock_filter);
    // Override the default port value.
    dhcp_sock_filter[8].k = port;
    // Apply the filter.
    if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter_program,
                   sizeof(filter_program)) < 0) {
        close(sock);
        isc_throw(SocketConfigError, "Failed to install packet filtering program"
                  << " on the socket " << sock);
    }

    struct sockaddr_ll sa;
    memset(&sa, 0, sizeof(sockaddr_ll));
    sa.sll_family = AF_PACKET;
    sa.sll_ifindex = iface.getIndex();

    // For raw sockets we construct IP headers on our own, so we don't bind
    // socket to IP address but to the interface. We will later use the
    // Linux Packet Filtering to filter out these packets that we are
    // interested in.
    if (bind(sock, reinterpret_cast<const struct sockaddr*>(&sa),
             sizeof(sa)) < 0) {
        close(sock);
        isc_throw(SocketConfigError, "Failed to bind LPF socket '" << sock
                  << "' to interface '" << iface.getName() << "'");
    }

    return (sock);

This may be a simple change to the protocol (described in src/bin/socketcreator/README). The current command consists of:

  • 'S' 'U|T' '4|6' port address: Asks it to create a port.

Probably we want to add something like:

  • 'R' 'N|L' ifindex: Asks it to create a raw port for either netlink or LPF (with the specified interface index).

Subtickets

Change History (15)

comment:1 Changed 6 years ago by muks

It would also require changes in src/lib/server_common/* which contain higher-level methods to work with the socketcreator (so bin programs don't have to pass these raw commands).

comment:2 Changed 6 years ago by muks

  • Estimated Difficulty changed from 0 to 5

comment:3 Changed 6 years ago by muks

See also #2780.

comment:4 Changed 6 years ago by tomek

Note: the first snippet seems to be opening NETLINK socket. That is used to read interfaces list and does not require root. Probably wrong piece of code was copied.

comment:5 Changed 6 years ago by muks

Also move the contents of the README file describing the sockcreator protocol to Doxygen.

comment:6 Changed 6 years ago by muks

  • Milestone changed from Next-Sprint-Proposed to Sprint-20131015

comment:7 Changed 6 years ago by muks

This ticket also involves doing some equivalent of:

  • Update b10-sockcreator to create the raw socket, set socket options and bind it as required by the code
  • update socketcreator.py to speak the b10-sockcreator "protocol" to handle raw sockets
  • updating the socket cache to cache raw sockets
  • modify b10-init to handle a get_raw_socket command and create a token for it
  • modify b10-init to send raw sockets for a token over its unix domain socket
  • Update isc::server_common::SocketRequestor (or create something equivalent) to get a raw socket from b10-init using its unix domain socket
  • Update the DHCP code itself to use this socket requestor

comment:8 Changed 6 years ago by muks

I have started work on this in trac3188, by first adding sockcreator support to create the filtering raw socket that the DHCP code requires.

comment:9 Changed 6 years ago by muks

  • Priority changed from medium to very high

comment:10 Changed 6 years ago by stephen

  • Milestone changed from bind10-1.2-release-freeze to DHCP-Kea0.9-alpha

comment:11 Changed 6 years ago by tomek

  • Priority changed from very high to medium

comment:12 Changed 6 years ago by stephen

  • Milestone changed from DHCP-Kea0.9-alpha to DHCP-Kea0.9-beta

comment:13 Changed 6 years ago by tomek

  • Milestone changed from DHCP-Kea0.9 to DHCP Outstanding Tasks

comment:14 Changed 4 years ago by tomek

  • Milestone changed from DHCP Outstanding Tasks to Outstanding Tasks

Milestone renamed

comment:15 Changed 3 years ago by tomek

  • Component changed from Unclassified to sockcreator
  • Description modified (diff)
Note: See TracTickets for help on using tickets.