macos - IPv6 Address Assignment on en0 Throws 'Cannot Allocate Memory' Error After Multiple Additions - Stack Ov

I was running a service that assigned a Unique Local Address (ULA) IPv6 to my en0 interface. Initially,

I was running a service that assigned a Unique Local Address (ULA) IPv6 to my en0 interface. Initially, I was able to add multiple IPv6 addresses without any issues. However, after adding 18 IPv6 addresses, I encountered the following error:

ifconfig: ioctl (SIOCAIFADDR): Cannot allocate memory

Even when I manually tried to assign another IPv6 address using:

sudo ifconfig en0 inet6 fc00:45bd::81aa:15c6 prefixlen 64 alias

I continued to receive the same error. This error persisted until I removed some of the previously assigned IPv6 addresses. Essentially, the 17th IPv6 address was added without any issues, but the error started appearing when attempting to add the 18th one.

At first, I suspected that Duplicate Address Detection (DAD) might be causing the issue. I checked my DAD settings when 18 IPv6 addresses were already assigned using:

sysctl -a | grep dad

The initial values were:

net.inet6.ip6.dad_count: 1
net.inet6.ip6.dad_enhanced: 1
net.inet6.ip6.nd6_dad_nonce_max_count: 3
net.inet6.icmp6.nd6_optimistic_dad: 63

To investigate further, I ran the following command:

/usr/bin/sudo ifconfig en0 inet6 add fc00:2703::53eb:6d0a; while sleep 0.001; do ifconfig en0 | grep net6 | cat -n | grep fc00:2703::53eb:6d0a; done

Initially, it returned:

ifconfig: ioctl (SIOCAIFADDR): Cannot allocate memory
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 tentative 
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 tentative 
.....
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 tentative 
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 
.....
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 
  1302      inet6 fc00:2703::53eb:6d0a prefixlen 64 

After some time, the address became fully assigned without the "tentative" status.

I then disabled DAD by setting:

net.inet6.ip6.dad_count: 0
net.inet6.ip6.dad_enhanced: 0
net.inet6.ip6.nd6_dad_nonce_max_count: 0
net.inet6.icmp6.nd6_optimistic_dad: 0

Despite disabling DAD, I still encountered the "Cannot allocate memory" error when attempting to add another IPv6 address:

/usr/bin/sudo ifconfig en0 inet6 add fc00:3940::7013:336d; while sleep 0.001; do ifconfig en0 | grep net6 | cat -n | grep fc00:3940::7013:336d; done

The output was:

ifconfig: ioctl (SIOCAIFADDR): Cannot allocate memory
  1303      inet6 fc00:3940::7013:336d prefixlen 64 
  1303      inet6 fc00:3940::7013:336d prefixlen 64 
....
  1303      inet6 fc00:3940::7013:336d prefixlen 64 

The address was listed in the interface configuration but still resulted in the same error.

To further test this behavior, I ran the following minimal Go program that attempts to add multiple IPv6 addresses to my en0 interface:

package main

import (
    "crypto/sha256"
    "fmt"
    "math/big"
    "math/rand"
    "net/netip"
    "os/exec"
)

func main() {
    i := 0
    for {
        i++
        //command := exec.Command("sudo", "ifconfig", "en0", "inet6", GenerateIPv6Address().String(), "prefixlen", "64", "alias")
        command := exec.Command("sudo", "ifconfig", "en0", "inet6", "add", GenerateIPv6Address().String())
        out, err := command.CombinedOutput()

        if err != nil {
            fmt.Println("\u001B[33m", i, command.String(), "\u001B[0m")
            fmt.Println(fmt.Errorf(err.Error()))
            fmt.Println("\u001B[31m" + string(out) + "\u001B[0m")
            break
        } else {
            fmt.Println("\u001B[32m", i, command.String()+"\u001B[0m")
            fmt.Println(string(out))
        }
    }
}

func GenerateIPv6Address() netip.Addr {
    seedBytes := make([]byte, 8)
    _, err := rand.Read(seedBytes)
    if err != nil {
        return netip.Addr{}
    }

    hash := sha256.Sum256(seedBytes)
    seedValue := new(big.Int).SetBytes(hash[:8])

    randInt := seedValue.Uint64()
    group2 := randInt % 65534
    group3 := (randInt >> 16) % 65534
    group4 := (randInt >> 32) % 65534

    ipStr := fmt.Sprintf("fc00:%x::%x:%x", group2, group3, group4)

    if ip, err := netip.ParseAddr(ipStr); err == nil {
        return ip
    }

    return netip.Addr{}
}

Directly calling the ioctl system call with the SIOCAIFADDR operation also results in the same error.

#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet6/nd6.h>
#include <sys/errno.h>
#include <stdint.h>

char* generateIPv6() {
    unsigned short group[8];
    char *buffer = malloc(40); // IPv6 max length is 39 characters + null terminator

    if (!buffer) {
        perror("Failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    group[0] = 0xfc00; // Unique local address prefix
    for (int i = 1; i < 8; i++) {
        group[i] = arc4random() % 65536;
    }

    // Format the IPv6 address into the buffer
    snprintf(buffer, 40, "%x:%x:%x:%x:%x:%x:%x:%x",
           group[0], group[1], group[2], group[3],
           group[4], group[5], group[6], group[7]);

    return buffer; // Return the dynamically allocated address
}

int main() {
    int sockfd;
    struct in6_aliasreq ifr6;
    const char *interface = "en0";
    int prefix_len = 64;

    // Create socket
    sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("Socket creation failed");
        return 1;
    }

    // Infinite loop to generate and add IPv6 addresses
    while (1) {
        char *ip_address = generateIPv6();

        // Prepare interface request
        memset(&ifr6, 0, sizeof(ifr6));
        strncpy(ifr6.ifra_name, interface, IFNAMSIZ);

        if (inet_pton(AF_INET6, ip_address, &ifr6.ifra_addr.sin6_addr) != 1) {
            perror("Invalid IP address");
            free(ip_address);
            close(sockfd);
            return 1;
        }

        ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr;
        ifr6.ifra_addr.sin6_family = AF_INET6;
        ifr6.ifra_prefixmask.sin6_family = AF_INET6;
        ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask;
        memset(&ifr6.ifra_prefixmask.sin6_addr, 0xFF, prefix_len / 8);

        // Set infinite lifetime
        ifr6.ifra_lifetime.ia6t_vltime = ifr6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;

        // Perform ioctl to add the address
        if (ioctl(sockfd, SIOCAIFADDR_IN6, &ifr6) < 0) {
            perror("Failed to add IPv6 address");
            fprintf(stderr, "Error: %s\n", strerror(errno));
            free(ip_address);
            break; // Exit loop on error
        }

        printf("IPv6 address added successfully: %s\n", ip_address);
        free(ip_address);
    }

    close(sockfd);
    return 0;
}

$ sudo ktrace trace -Ss -f C4 -c ./output/bind_ipv6_using_syscall | grep bind_ipv6_using_sys

...
IPv6 address added successfully: fc00:2452:fc7e:5604:3d5c:ee50:a275:1ee3
IPv6 address added successfully: fc00:a332:1532:86bc:4f09:c01:b845:1685
IPv6 address added successfully: fc00:5f4c:dcfe:100:4542:9626:430c:de7f
IPv6 address added successfully: fc00:eb40:218a:6561:8f5a:ebab:7ed1:d3dc
IPv6 address added successfully: fc00:3422:b629:5d3a:7b69:caf0:4524:a18d
IPv6 address added successfully: fc00:cd47:a34b:f045:9620:2edd:9bc4:49f5
IPv6 address added successfully: fc00:305d:582c:94ff:d0fe:6d6f:b7df:31e1
IPv6 address added successfully: fc00:42e2:4920:93cc:6dec:8b3c:f34f:b7ef
IPv6 address added successfully: fc00:e1c3:dd39:53e:64f2:f047:8135:ee6c
IPv6 address added successfully: fc00:91ee:9b52:7cd0:862f:9101:84fd:9935
Failed to add IPv6 address: Cannot allocate memory
Error: Cannot allocate memory

I am trying to understand what might be causing this issue and whether there is a limit on the number of IPv6 addresses that can be assigned to my en0 interface.

Could this be due to an internal kernel or system limit on the number of IPv6 addresses per interface?

Is there a way to increase this limit, or is it hardcoded within macOS?

Are there any logs or diagnostic tools that could provide more insight into why the system refuses to allocate more addresses?

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744201574a4562902.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信