Exemplo n.º 1
0
/**
 * Open the tun device.
 *
 * @param interfaceName the interface name you *want* to use or NULL to let the kernel decide.
 * @param assignedInterfaceName the interface name you get.
 * @param log
 * @param eh
 * @return a file descriptor for the tunnel.
 */
void* TUNConfigurator_initTun(const char* interfaceName,
                              char assignedInterfaceName[TUNConfigurator_IFNAMSIZ],
                              struct Log* logger,
                              struct Except* eh)
{
    // Open the descriptor
    int tunFd = open("/dev/tun", O_RDWR);

    //Get the resulting device name
    const char* assignedDevname;
    assignedDevname = fdevname(tunFd);

    // Extract the number eg: 0 from tun0
    int ppa = 0;
    for (uint32_t i = 0; i < strlen(assignedDevname); i++) {
        if (isdigit(assignedDevname[i])) {
            ppa = atoi(assignedDevname);
        }
    }

    if (tunFd < 0 || ppa < 0 ) {
        enum Errno err = Errno_get();
        close(tunFd);

        char* error = NULL;
        if (tunFd < 0) {
            error = "open(\"/dev/tun\")";
        } else if (ppa < 0) {
            error = "fdevname/getting number from fdevname";
        }
        Except_raise(eh, TUNConfigurator_initTun_INTERNAL, error, Errno_strerror(err));
    }

    // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0
    // so we'll skip the pretty names and call everything tunX
    snprintf(assignedInterfaceName, TUNConfigurator_IFNAMSIZ, "tun%d", ppa);

    char* error = NULL;

    // We want to send IPv6 through our tun device, so we need to be able to specify "ethertype"
    int tunhead = 1;
    if (ioctl(tunFd,TUNSIFHEAD,&tunhead) == -1) {
        error = "TUNSIFHEAD";
    }

    if (error) {
        enum Errno err = Errno_get();
        close(tunFd);
        Except_raise(eh, TUNConfigurator_initTun_INTERNAL, "%s [%s]", error, Errno_strerror(err));
    }


    intptr_t ret = (intptr_t) tunFd;
    return (void*) ret;
}
Exemplo n.º 2
0
/** @see BencSerializer.h */
static int32_t parseint64_t(const struct Reader* reader,
                            int64_t* output)
{
    uint8_t buffer[32];

    for (int i = 0; i < 21; i++) {
        int32_t status = reader->read(buffer + i, 0, reader);
        if (i == 0 && buffer[i] == '-' && status == 0) {
            // It's just a negative number, no need to fail it.
            continue;
        }
        if (buffer[i] < '0' || buffer[i] > '9' || status != 0 /* end of input */) {
            buffer[i] = '\0';
            Errno_clear();
            int64_t out = strtol((char*)buffer, NULL, 10);
            // Failed parse causes 0 to be set.
            if (out == 0 && buffer[0] != '0' && (buffer[0] != '-' || buffer[1] != '0')) {
                printf("Failed to parse \"%s\": not a number\n",buffer);
                return UNPARSABLE;
            }
            if ((out == INT64_MAX || out == INT64_MIN) && Errno_get() == Errno_ERANGE) {
                printf("Failed to parse \"%s\": number too large/small\n",buffer);
                return UNPARSABLE;
            }
            *output = out;
            return 0;
        }
        reader->skip(1, reader);
    }

    // Larger than the max possible int64.
    buffer[22] = '\0';
    printf("Failed to parse \"%s\": number too large\n",buffer);
    return UNPARSABLE;
}
Exemplo n.º 3
0
static uint8_t sendMessage(struct Message* message, struct Interface* iface)
{
    struct UDPAddrInterface_pvt* context =
        Identity_cast((struct UDPAddrInterface_pvt*) iface->senderContext);

    struct Sockaddr_storage addrStore;
    Message_pop(message, &addrStore, context->pub.addr->addrLen);
    Assert_true(addrStore.addr.addrLen == context->pub.addr->addrLen);

    if (Socket_sendto(context->socket,
                      message->bytes,
                      message->length,
                      0,
                      &addrStore.addr) < 0)
    {
        switch (Errno_get()) {
            case Errno_EMSGSIZE:
                return Error_OVERSIZE_MESSAGE;

            case Errno_ENOBUFS:
            case Errno_EAGAIN:
                return Error_LINK_LIMIT_EXCEEDED;

            default:;
                Log_info(context->logger, "Got error sending to socket [%s]",
                         Errno_getString());
        }
    }
    return 0;
}
Exemplo n.º 4
0
void TUNConfigurator_setMTU(const char* interfaceName,
                            uint32_t mtu,
                            struct Log* logger,
                            struct Except* eh)
{
    int s = socket(AF_INET6, SOCK_DGRAM, 0);

    if (s < 0) {
        Except_raise(eh,
                     TUNConfigurator_ERROR_GETTING_ADMIN_SOCKET,
                     "socket() failed [%s]",
                     Errno_getString());
    }


    struct ifreq ifRequest;

    strncpy(ifRequest.ifr_name, interfaceName, IFNAMSIZ);
    ifRequest.ifr_mtu = mtu;

    Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu);

    if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
       enum Errno err = Errno_get();
       close(s);
       Except_raise(eh,
                    TUNConfigurator_setMTU_INTERNAL,
                    "ioctl(SIOCSIFMTU) failed [%s]",
                    Errno_strerror(err));
    }
}
Exemplo n.º 5
0
/** @see BencSerializer.h */
static int32_t parseint64_t(const struct Reader* reader,
                            int64_t* output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3
    char buffer[32];
    int i;
    for (i = 0; ; i++) {
        if (reader->read(buffer + i, 1, reader) != 0) {
            return OUT_OF_CONTENT_TO_READ;
        }
        if (i == 0) {
            if (buffer[i] != 'i') {
                /* Not an int. */
                return UNPARSABLE;
            } else {
                continue;
            }
        }
        if (buffer[i] == 'e') {
            break;
        }
        if (i == 1 && buffer[i] == '-') {
            /* It's just a negative number, no need to fail it. */
            continue;
        }
        if (buffer[i] < '0' || buffer[i] > '9') {
            return UNPARSABLE;
        }
        if (i > 21) {
            /* Larger than the max possible int64. */
            return UNPARSABLE;
        }
    }

    /* buffer + 1, skip the 'i' */
    int64_t out = strtol(buffer + 1, NULL, 10);

    /* Failed parse causes 0 to be set. */
    if (out == 0 && buffer[1] != '0' && (buffer[1] != '-' || buffer[2] != '0')) {
        return UNPARSABLE;
    }
    if ((out == LONG_MAX || out == LONG_MIN) && Errno_get() == Errno_ERANGE) {
        /* errno (holds nose) */
        return UNPARSABLE;
    }

    *output = out;
    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
}
Exemplo n.º 6
0
void TUNConfigurator_setIpAddress(const char* interfaceName,
                                  const uint8_t address[16],
                                  int prefixLen,
                                  struct Log* logger,
                                  struct Except* eh)
{
    /* stringify our IP address */
    char myIp[40];
    AddrTools_printIp((uint8_t*)myIp, address);

    /* set up the interface ip assignment request */
    struct in6_aliasreq in6_addreq;
    memset(&in6_addreq, 0, sizeof(in6_addreq));
    in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
    in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;

    /* parse the IPv6 address and add it to the request */
    struct addrinfo hints, *result;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_family = AF_INET6;
    int err = getaddrinfo((const char *)myIp, NULL, &hints, &result);
    if (err) {
        // Should never happen since the address is specified as binary.
        Except_raise(eh,
                     TUNConfigurator_setIpAddress_INTERNAL,
                     "bad IPv6 address [%s]",
                     gai_strerror(err));
    }

    Bits_memcpy(&in6_addreq.ifra_addr, result->ai_addr, result->ai_addrlen);

    /* turn the prefixlen into a mask, and add it to the request */
    struct sockaddr_in6* mask = &in6_addreq.ifra_prefixmask;
    u_char *cp;

    int len = prefixLen;
    mask->sin6_len = sizeof(*mask);
    if ((prefixLen == 0) || (prefixLen == 128)) {
        memset(&mask->sin6_addr, 0xff, sizeof(struct in6_addr));
    } else {
        memset((void *)&mask->sin6_addr, 0x00, sizeof(mask->sin6_addr));
        for (cp = (u_char *)&mask->sin6_addr; len > 7; len -= 8) {
            *cp++ = 0xff;
        }
        *cp = 0xff << (8 - len);
    }

    strncpy(in6_addreq.ifra_name, interfaceName, sizeof(in6_addreq.ifra_name));

    /* do the actual assignment ioctl */
    int s = socket(AF_INET6, SOCK_DGRAM, 0);
    if (s < 0) {
        Except_raise(eh,
                     TUNConfigurator_setIpAddress_INTERNAL,
                     "socket() failed [%s]",
                     Errno_getString());
    }

    if (ioctl(s, SIOCAIFADDR_IN6, &in6_addreq) < 0) {
        enum Errno err = Errno_get();
        close(s);
        Except_raise(eh,
                     TUNConfigurator_setIpAddress_INTERNAL,
                     "ioctl(SIOCAIFADDR) failed [%s]",
                     Errno_strerror(err));
    }

    Log_info(logger, "Configured IPv6 [%s/%i] for [%s]", myIp, prefixLen, interfaceName);

    close(s);
}
Exemplo n.º 7
0
/**
 * handle incoming tcp data from client connections in the admin process
 */
static void incomingFromClient(evutil_socket_t socket, short eventType, void* vconn)
{
    struct Connection* conn = (struct Connection*) vconn;
    struct AngelContext* context = conn->context;

    uint8_t buf[PipeInterface_MAX_MESSAGE_SIZE + PipeInterface_PADDING];
    uint32_t connNumber = conn - context->connections;

    struct Message message = {
        .bytes = buf + PipeInterface_PADDING,
        .length = PipeInterface_MAX_MESSAGE_SIZE,
        .padding = PipeInterface_PADDING
    };
    ssize_t result = recv(socket, message.bytes, message.length, 0);

    if (result > 0) {
        message.length = result;
        sendToCore(&message, connNumber, context);
    } else if (result < 0 && Errno_get() == Errno_EAGAIN) {
        return;
    } else {
        // The return value will be 0 when the peer has performed an orderly shutdown.
        EVUTIL_CLOSESOCKET(conn->socket);
        event_free(conn->read);
        conn->read = NULL;
        // send close channel
        message.length = 0;
        sendToCore(&message, connNumber, context);
        // set conn->socket = -1 later when we recv close ACK
    }
}

static struct Connection* newConnection(struct AngelContext* context, evutil_socket_t fd)
{
    struct Connection* conn = NULL;
    for (int i = 0; i < Angel_MAX_CONNECTIONS; i++) {
        if (context->connections[i].read == NULL && context->connections[i].socket == -1) {
            conn = &context->connections[i];
            break;
        }
    }

    if (!conn) {
        return NULL;
    }

    conn->read = event_new(context->eventBase, fd, EV_READ | EV_PERSIST, incomingFromClient, conn);
    conn->socket = fd;
    conn->context = context;

    if (!conn->read) {
        return NULL;
    }

    event_add(conn->read, NULL);
    return conn;
}

static void acceptConn(evutil_socket_t socket, short eventType, void* vcontext)
{
    struct AngelContext* context = (struct AngelContext*) vcontext;

    struct sockaddr_storage ss;
    ev_socklen_t slen = sizeof(ss);
    evutil_socket_t fd = accept(socket, (struct sockaddr*)&ss, &slen);
    if (fd < 0) {
        perror("acceptConn() fd < 0");
        return;
    } else if (fd > (evutil_socket_t) FD_SETSIZE) {
        EVUTIL_CLOSESOCKET(fd);
        return;
    }

    evutil_make_socket_nonblocking(fd);

    struct Connection* conn = newConnection(context, fd);
    if (!conn) {
        EVUTIL_CLOSESOCKET(fd);
    }
}

void Angel_start(String* pass,
                 evutil_socket_t tcpSocket,
                 struct Interface* coreIface,
                 struct event_base* eventBase,
                 struct Log* logger,
                 struct Allocator* alloc)
{
    struct AngelContext contextStore;
    struct AngelContext* context = &contextStore;
    Bits_memset(context, 0, sizeof(struct AngelContext));

    for (int i = 0; i < Angel_MAX_CONNECTIONS; i++) {
        context->connections[i].socket = -1;
    }
    context->eventBase = eventBase;
    context->logger = logger;

    context->coreIface = coreIface;
    context->coreIface->receiveMessage = receiveMessage;
    context->coreIface->receiverContext = context;

    context->socketEvent =
        event_new(context->eventBase, tcpSocket, EV_READ | EV_PERSIST, acceptConn, context);
    event_add(context->socketEvent, NULL);

    event_base_dispatch(context->eventBase);
}