123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- /*
- * Copyright (C)2013-2020 ZeroTier, Inc.
- *
- * Use of this software is governed by the Business Source License included
- * in the LICENSE.TXT file in the project's root directory.
- *
- * Change Date: 2025-01-01
- *
- * On the date above, in accordance with the Business Source License, use
- * of this software will be governed by version 2.0 of the Apache License.
- */
- /****/
- package zerotier
- import (
- "encoding/json"
- "fmt"
- "strconv"
- "strings"
- )
- // MAC represents an Ethernet hardware address
- type MAC uint64
- // NewMACFromString decodes a MAC address in canonical colon-separated hex format
- func NewMACFromString(s string) (MAC, error) {
- ss := strings.Split(s, ":")
- if len(ss) != 6 {
- return MAC(0), ErrInvalidMACAddress
- }
- var m uint64
- for i := 0; i < 6; i++ {
- m <<= 8
- c, _ := strconv.ParseUint(ss[i], 16, 64)
- if c > 0xff {
- return MAC(0), ErrInvalidMACAddress
- }
- m |= c & 0xff
- }
- return MAC(m), nil
- }
- // NewMACFromBytes decodes a MAC from a 6-byte array
- func NewMACFromBytes(b []byte) (MAC, error) {
- if len(b) < 6 {
- return MAC(0), ErrInvalidMACAddress
- }
- var m uint64
- for i := 0; i < 6; i++ {
- m <<= 8
- m |= uint64(b[i])
- }
- return MAC(m), nil
- }
- // NewMACForNetworkMember computes the static MAC for a given address and network ID
- func NewMACForNetworkMember(addr Address, nwid NetworkID) MAC {
- // This is the same algorithm as found in MAC::fromAddress() in MAC.hpp
- firstOctetForNetwork := byte((byte(nwid) & 0xfe) | 0x02)
- if firstOctetForNetwork == 0x52 {
- firstOctetForNetwork = 0x32
- }
- m := uint64(firstOctetForNetwork) << 40
- m |= uint64(addr)
- m ^= ((uint64(nwid) >> 8) & 0xff) << 32
- m ^= ((uint64(nwid) >> 16) & 0xff) << 24
- m ^= ((uint64(nwid) >> 24) & 0xff) << 16
- m ^= ((uint64(nwid) >> 32) & 0xff) << 8
- m ^= (uint64(nwid) >> 40) & 0xff
- return MAC(m)
- }
- // String returns this MAC address in canonical human-readable form
- func (m MAC) String() string {
- return fmt.Sprintf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (uint64(m)>>40)&0xff, (uint64(m)>>32)&0xff, (uint64(m)>>24)&0xff, (uint64(m)>>16)&0xff, (uint64(m)>>8)&0xff, uint64(m)&0xff)
- }
- // MarshalJSON marshals this MAC as a string
- func (m MAC) MarshalJSON() ([]byte, error) {
- return []byte("\"" + m.String() + "\""), nil
- }
- // UnmarshalJSON unmarshals this MAC from a string
- func (m *MAC) UnmarshalJSON(j []byte) error {
- var s string
- err := json.Unmarshal(j, &s)
- if err != nil {
- return err
- }
- *m, err = NewMACFromString(s)
- return err
- }
|