<commit_before>#include "transport.h"
#include "util.h"
#include "varlink.h"

#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>

static void freeaddrinfop(struct addrinfo **ai) {
        if (*ai)
                freeaddrinfo(*ai);
}

static long resolve_addrinfo(const char *address, struct addrinfo **resultp) {
        _cleanup_(freep) char *name = NULL;
        char *port;
        struct addrinfo hints = {
                .ai_family = AF_UNSPEC,
                .ai_socktype = SOCK_STREAM,
                .ai_flags = AI_NUMERICSERV
        };
        _cleanup_(freeaddrinfop) struct addrinfo *result = NULL;

        port = strrchr(address, ':');
        if (!port)
                return -VARLINK_ERROR_INVALID_ADDRESS;

        name = strndup(address, port - address);
        if (!name)
                return -VARLINK_ERROR_PANIC;

        port += 1;

        if (getaddrinfo(name, port, &hints, &result) != 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (result->ai_family != AF_INET &&
            result->ai_family != AF_INET6)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        *resultp = result;
        result = NULL;

        return 0;
}

int varlink_connect_ip(const char *address) {
        _cleanup_(freeaddrinfop) struct addrinfo *result = NULL;
        _cleanup_(closep) int fd = -1;
        int r;

        r = resolve_addrinfo(address, &result);
        if (r < 0)
                return r;

        fd = socket(result->ai_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
        if (fd < 0)
                return -VARLINK_ERROR_CANNOT_CONNECT;

        if (connect(fd, result->ai_addr, result->ai_addrlen) < 0 && errno != EINPROGRESS)
                return -VARLINK_ERROR_CANNOT_CONNECT;

        r = fd;
        fd = -1;

        return r;
}

int varlink_listen_ip(const char *address) {
        _cleanup_(closep) int fd = -1;
        const int on = 1;
        _cleanup_(freeaddrinfop) struct addrinfo *result = NULL;
        int r;

        r = resolve_addrinfo(address, &result);
        if (r < 0)
                return r;

        fd = socket(result->ai_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
        if (fd < 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (bind(fd, result->ai_addr, result->ai_addrlen))
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (listen(fd, SOMAXCONN) < 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        r = fd;
        fd = -1;

        return r;
}

int varlink_accept_ip(int listen_fd) {
        _cleanup_(closep) int fd = -1;
        _cleanup_(freep) char *address = NULL;
        int r;

        fd = accept4(listen_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
        if (fd < 0)
                return -VARLINK_ERROR_CANNOT_ACCEPT;

        r = fd;
        fd = -1;

        return r;
}
<commit_msg>lib: Require IPv6 literal addresses to be enclosed in []<commit_after>#include "transport.h"
#include "util.h"
#include "varlink.h"

#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>

static void freeaddrinfop(struct addrinfo **ai) {
        if (*ai)
                freeaddrinfo(*ai);
}

static long resolve_addrinfo(const char *address, struct addrinfo **resultp) {
        _cleanup_(freep) char *host = NULL;
        char *endptr;
        char *port;
        struct addrinfo hints = {
                .ai_family = AF_UNSPEC,
                .ai_socktype = SOCK_STREAM,
                .ai_flags = AI_NUMERICSERV
        };
        _cleanup_(freeaddrinfop) struct addrinfo *result = NULL;

        /* Split host and port */
        port = strrchr(address, ':');
        if (!port)
                return -VARLINK_ERROR_INVALID_ADDRESS;

        host = strndup(address, port - address);
        if (!host)
                return -VARLINK_ERROR_PANIC;

        port += 1;

        /* Require decimal port specification */
        if (strtol(port, &endptr, 10) < 0 ||
            endptr == port || endptr[0] != '\0')
                return -VARLINK_ERROR_INVALID_ADDRESS;

        /* IPv6 literal addresses must be enclosed in [] */
        if (strchr(host, ':')) {
                char *s, *p;

                if (host[0] != '[')
                        return -VARLINK_ERROR_INVALID_ADDRESS;

                p = strchr(host, ']');
                if (!p || p[1] != '\0')
                        return -VARLINK_ERROR_INVALID_ADDRESS;

                s = strndup(host + 1, p - host - 1);
                if (!s)
                        return -VARLINK_ERROR_PANIC;

                free(host);
                host = s;

                hints.ai_family = AF_INET6;
        }

        if (getaddrinfo(host, port, &hints, &result) != 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (result->ai_family != AF_INET &&
            result->ai_family != AF_INET6)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        *resultp = result;
        result = NULL;

        return 0;
}

int varlink_connect_ip(const char *address) {
        _cleanup_(freeaddrinfop) struct addrinfo *result = NULL;
        _cleanup_(closep) int fd = -1;
        int r;

        r = resolve_addrinfo(address, &result);
        if (r < 0)
                return r;

        fd = socket(result->ai_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
        if (fd < 0)
                return -VARLINK_ERROR_CANNOT_CONNECT;

        if (connect(fd, result->ai_addr, result->ai_addrlen) < 0 && errno != EINPROGRESS)
                return -VARLINK_ERROR_CANNOT_CONNECT;

        r = fd;
        fd = -1;

        return r;
}

int varlink_listen_ip(const char *address) {
        _cleanup_(closep) int fd = -1;
        const int on = 1;
        _cleanup_(freeaddrinfop) struct addrinfo *result = NULL;
        int r;

        r = resolve_addrinfo(address, &result);
        if (r < 0)
                return r;

        fd = socket(result->ai_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
        if (fd < 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (bind(fd, result->ai_addr, result->ai_addrlen))
                return -VARLINK_ERROR_CANNOT_LISTEN;

        if (listen(fd, SOMAXCONN) < 0)
                return -VARLINK_ERROR_CANNOT_LISTEN;

        r = fd;
        fd = -1;

        return r;
}

int varlink_accept_ip(int listen_fd) {
        _cleanup_(closep) int fd = -1;
        _cleanup_(freep) char *address = NULL;
        int r;

        fd = accept4(listen_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
        if (fd < 0)
                return -VARLINK_ERROR_CANNOT_ACCEPT;

        r = fd;
        fd = -1;

        return r;
}

{'fraction_non_alphanumeric': 0.10842179759377212, 'fraction_numerical': 0.008067940552016985, 'mean_word_length': 1.8230123851378346, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5959693', 'n_tokens_mistral': 2395, 'n_tokens_neox': 2251, 'n_words': 539}