Repository: valkey-io/valkey
File: src/anet.c (C)

Code before:
static int anetV6Only(char *err, int s) {
    int yes = 1;
    if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1) {
        anetSetError(err, "setsockopt: %s", strerror(errno));
        return ANET_ERR;
    }
    return ANET_OK;
}

/* Until glibc 2.39, getaddrinfo with hints.ai_protocol of IPPROTO_MPTCP leads error.
 * Use hints.ai_protocol IPPROTO_IP (0) or IPPROTO_TCP (6) to resolve address and overwrite
 * it when MPTCP is enabled.
 * Ref: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/net/mptcp/mptcp_connect.c
 */
static int anetTcpGetProtocol(char *err, int ai_protocol, int mptcp) {
    if (mptcp) {
#ifdef IPPROTO_MPTCP
        UNUSED(err);
        return IPPROTO_MPTCP;
#else
        anetSetError(err, "MPTCP is not supported on this platform");
        return ANET_ERR;
#endif
    }
    return ai_protocol;
}

static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog, int mptcp) {
    int s = -1, rv;
    char _port[6]; /* strlen("65535") */
    struct addrinfo hints, *servinfo, *p;

    snprintf(_port, 6, "%d", port);
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = af;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */
    if (bindaddr && !strcmp("*", bindaddr)) bindaddr = NULL;
    if (af == AF_INET6 && bindaddr && !strcmp("::*", bindaddr)) bindaddr = NULL;

    if ((rv = getaddrinfo(bindaddr, _port, &hints, &servinfo)) != 0) {
        anetSetError(err, "%s", gai_strerror(rv));
        return ANET_ERR;
    }
    for (p = servinfo; p != NULL; p = p->ai_next) {
        rv = anetTcpGetProtocol(err, p->ai_protocol, mptcp);
        if (rv == ANET_ERR) goto error;

        if ((s = socket(p->ai_family, p->ai_socktype, rv)) == -1) continue;

        if (af == AF_INET6 && anetV6Only(err, s) == ANET_ERR) goto error;

Review comment (suggestion):
We actually call this with `ai_protocol` set to `AF_INET` or `AF_INET6`.

I think the name and the behavior of this function is a little unintuitive.

I think we can check if MPTCP is supported only when the user tries to enable the config, i.e. in the config's `is_valid` callback, and refuse to enable it if it isn't supported, i.e. Valkey refuses to start if it's not supported. Then we don't need to check when we create a socket and we can just do like this:

```C
rv = mptcp ? IPPROTO_MPTCP : p->ai_protocol;
```

Code after:

static int anetV6Only(char *err, int s) {
    int yes = 1;
    if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1) {
        anetSetError(err, "setsockopt: %s", strerror(errno));
        return ANET_ERR;
    }
    return ANET_OK;
}

/* XXX: Until glibc 2.41, getaddrinfo with hints.ai_protocol of IPPROTO_MPTCP leads error.
 * Use hints.ai_protocol IPPROTO_IP (0) or IPPROTO_TCP (6) to resolve address and overwrite
 * it when MPTCP is enabled.
 * Ref: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/testing/selftests/net/mptcp/mptcp_connect.c
 *      https://sourceware.org/git/?p=glibc.git;a=commit;h=a8e9022e0f829d44a818c642fc85b3bfbd26a514
 */
static int anetTcpGetProtocol(int is_mptcp_enabled) {
#ifdef IPPROTO_MPTCP
    return is_mptcp_enabled ? IPPROTO_MPTCP : IPPROTO_TCP;
#else
    assert(!is_mptcp_enabled);
    return IPPROTO_TCP;
#endif
}

static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog, int mptcp) {
    int s = -1, rv;
    char _port[6]; /* strlen("65535") */
    struct addrinfo hints, *servinfo, *p;

    snprintf(_port, 6, "%d", port);
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = af;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */
    if (bindaddr && !strcmp("*", bindaddr)) bindaddr = NULL;
    if (af == AF_INET6 && bindaddr && !strcmp("::*", bindaddr)) bindaddr = NULL;

    if ((rv = getaddrinfo(bindaddr, _port, &hints, &servinfo)) != 0) {
        anetSetError(err, "%s", gai_strerror(rv));
        return ANET_ERR;
    }
    for (p = servinfo; p != NULL; p = p->ai_next) {
        if ((s = socket(p->ai_family, p->ai_socktype, anetTcpGetProtocol(mptcp))) == -1) continue;

        if (af == AF_INET6 && anetV6Only(err, s) == ANET_ERR) goto error;
        if (anetSetReuseAddr(err, s) == ANET_ERR) goto error;
        if (anetListen(err, s, p->ai_addr, p->ai_addrlen, backlog, 0, NULL) == ANET_ERR) s = ANET_ERR;
        goto end;
    }
    if (p == NULL) {