// Copyright 2011 Google Inc. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package uuid import ( "net" "sync" ) var ( nodeMu sync.Mutex interfaces []net.Interface // cached list of interfaces ifname string // name of interface being used nodeID []byte // hardware for version 1 UUIDs ) // NodeInterface returns the name of the interface from which the NodeID was // derived. The interface "user" is returned if the NodeID was set by // SetNodeID. func NodeInterface() string { defer nodeMu.Unlock() nodeMu.Lock() return ifname } // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. // If name is "" then the first usable interface found will be used or a random // Node ID will be generated. If a named interface cannot be found then false // is returned. // // SetNodeInterface never fails when name is "". func SetNodeInterface(name string) bool { defer nodeMu.Unlock() nodeMu.Lock() return setNodeInterface(name) } func setNodeInterface(name string) bool { if interfaces == nil { var err error interfaces, err = net.Interfaces() if err != nil && name != "" { return false } } for _, ifs := range interfaces { if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { if setNodeID(ifs.HardwareAddr) { ifname = ifs.Name return true } } } // We found no interfaces with a valid hardware address. If name // does not specify a specific interface generate a random Node ID // (section 4.1.6) if name == "" { if nodeID == nil { nodeID = make([]byte, 6) } randomBits(nodeID) return true } return false } // NodeID returns a slice of a copy of the current Node ID, setting the Node ID // if not already set. func NodeID() []byte { defer nodeMu.Unlock() nodeMu.Lock() if nodeID == nil { setNodeInterface("") } nid := make([]byte, 6) copy(nid, nodeID) return nid } // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes // of id are used. If id is less than 6 bytes then false is returned and the // Node ID is not set. func SetNodeID(id []byte) bool { defer nodeMu.Unlock() nodeMu.Lock() if setNodeID(id) { ifname = "user" return true } return false } func setNodeID(id []byte) bool { if len(id) < 6 { return false } if nodeID == nil { nodeID = make([]byte, 6) } copy(nodeID, id) return true } // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is // not valid. The NodeID is only well defined for version 1 and 2 UUIDs. func (uuid UUID) NodeID() []byte { if len(uuid) != 16 { return nil } node := make([]byte, 6) copy(node, uuid[10:]) return node }