blob: 42d60da8f10f841eccba705dade8c57194a69db0 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001// Copyright 2011 Google Inc. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package uuid
6
7import (
8 "net"
9 "sync"
10)
11
12var (
13 nodeMu sync.Mutex
14 interfaces []net.Interface // cached list of interfaces
15 ifname string // name of interface being used
16 nodeID []byte // hardware for version 1 UUIDs
17)
18
19// NodeInterface returns the name of the interface from which the NodeID was
20// derived. The interface "user" is returned if the NodeID was set by
21// SetNodeID.
22func NodeInterface() string {
23 defer nodeMu.Unlock()
24 nodeMu.Lock()
25 return ifname
26}
27
28// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
29// If name is "" then the first usable interface found will be used or a random
30// Node ID will be generated. If a named interface cannot be found then false
31// is returned.
32//
33// SetNodeInterface never fails when name is "".
34func SetNodeInterface(name string) bool {
35 defer nodeMu.Unlock()
36 nodeMu.Lock()
37 return setNodeInterface(name)
38}
39
40func setNodeInterface(name string) bool {
41 if interfaces == nil {
42 var err error
43 interfaces, err = net.Interfaces()
44 if err != nil && name != "" {
45 return false
46 }
47 }
48
49 for _, ifs := range interfaces {
50 if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
51 if setNodeID(ifs.HardwareAddr) {
52 ifname = ifs.Name
53 return true
54 }
55 }
56 }
57
58 // We found no interfaces with a valid hardware address. If name
59 // does not specify a specific interface generate a random Node ID
60 // (section 4.1.6)
61 if name == "" {
62 if nodeID == nil {
63 nodeID = make([]byte, 6)
64 }
65 randomBits(nodeID)
66 return true
67 }
68 return false
69}
70
71// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
72// if not already set.
73func NodeID() []byte {
74 defer nodeMu.Unlock()
75 nodeMu.Lock()
76 if nodeID == nil {
77 setNodeInterface("")
78 }
79 nid := make([]byte, 6)
80 copy(nid, nodeID)
81 return nid
82}
83
84// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
85// of id are used. If id is less than 6 bytes then false is returned and the
86// Node ID is not set.
87func SetNodeID(id []byte) bool {
88 defer nodeMu.Unlock()
89 nodeMu.Lock()
90 if setNodeID(id) {
91 ifname = "user"
92 return true
93 }
94 return false
95}
96
97func setNodeID(id []byte) bool {
98 if len(id) < 6 {
99 return false
100 }
101 if nodeID == nil {
102 nodeID = make([]byte, 6)
103 }
104 copy(nodeID, id)
105 return true
106}
107
108// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
109// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
110func (uuid UUID) NodeID() []byte {
111 if len(uuid) != 16 {
112 return nil
113 }
114 node := make([]byte, 6)
115 copy(node, uuid[10:])
116 return node
117}