{"record":{"id":"2b7ca78b0277ba5a","repo":"AdguardTeam/AdGuardHome","slug":"converting-source-link-layer-address-w","errorCode":null,"errorMessage":"converting source link-layer address: %w","messagePattern":"converting source link-layer address: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dhcpd/routeradv.go","lineNumber":128,"sourceCode":"//\t  - Option=MTU(5):\n//\t    - Type[1]\n//\t    - Length * 8bytes[1]\n//\t    - Reserved[2]\n//\t    - MTU[4]\n//\t  - Option=Source link-layer address(1):\n//\t    - Link-Layer Address[8/24]\n//\t  - Option=Recursive DNS Server(25):\n//\t    - Type[1]\n//\t    - Length * 8bytes[1]\n//\t    - Reserved[2]\n//\t    - Lifetime[4]\n//\t    - Addresses of IPv6 Recursive DNS Servers[16]\n//\n// TODO(a.garipov): Replace with an existing implementation from a dependency.\nfunc createICMPv6RAPacket(params icmpv6RA) (data []byte, err error) {\n\tlla, err := hwAddrToLinkLayerAddr(params.sourceLinkLayerAddress)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"converting source link-layer address: %w\", err)\n\t}\n\n\t// Calculate length of the source link-layer address option.  As per RFC\n\t// 4861, section 4.6.1, the length should be in units of 8 octets, including\n\t// the type and length fields.\n\t//\n\t// See https://datatracker.ietf.org/doc/html/rfc4861#section-4.6.1.\n\tsrcLLAOptLen := len(lla) + 2\n\t// Make sure the value is rounded up to the nearest multiple of 8.\n\tsrcLLAOptLenValue := (srcLLAOptLen + 7) / 8\n\tsrcLLAPadLen := srcLLAOptLenValue*8 - srcLLAOptLen\n\n\t// TODO(a.garipov): Don't use a magic constant here.  Refactor the code\n\t// and make all constants named instead of all those comments.\n\tdata = make([]byte, 80+srcLLAOptLen+srcLLAPadLen)\n\ti := 0\n\n\t// ICMPv6:","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/dhcpd/routeradv.go#L110-L146","documentation":"Raised in createICMPv6RAPacket when the configured source link-layer address (MAC) cannot be converted into the NDP source link-layer address option format. The wrapped hwAddrToLinkLayerAddr error fires when the hardware address is nil, the wrong length (not 6 or 8 bytes), or otherwise unsuitable for an ICMPv6 RA.","triggerScenarios":"Building a router-advertisement packet where the interface's MAC address is unavailable (pure L3 interfaces, tunnels, some containers) or malformed; unit tests passing a zero-value MAC. Hit during RA Init or tests exercising createICMPv6RAPacket.","commonSituations":"Enabling DHCPv6/RA on tun/tap or VLAN-only interfaces with no hardware address; virtualized NICs reporting unusual MAC lengths; config referencing an interface index that resolves to a loopback.","solutions":["Verify the interface actually has a 6-byte (EUI-48) or 8-byte (EUI-64) hardware address: ip link show <iface>","Point the RA/DHCPv6 config at a real Ethernet/WLAN interface, not lo or a tunnel","Log iface.HardwareAddr length and value at startup to catch odd virtual NICs early"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"iface, err := net.InterfaceByName(name)\nif err != nil || len(iface.HardwareAddr) != 6 && len(iface.HardwareAddr) != 8 {\n    return fmt.Errorf(\"interface %s has no usable MAC\", name)\n}","typeGuard":"func hasUsableMAC(iface *net.Interface) bool {\n\tn := len(iface.HardwareAddr)\n\treturn n == 6 || n == 8\n}","tryCatchPattern":null,"preventionTips":["Don't enable RA on tunnels/loopback/veth interfaces without hardware addresses","Check iface.HardwareAddr length before enabling DHCPv6","Log the MAC at startup for quick diagnosis"],"tags":["dhcp","ipv6","router-advertisement","icmpv6","network-interface"],"backgroundTag":"invalid-mac-address","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}