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条)