This repository has been archived by the owner on Oct 14, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
unicast_ip_address_row.go
203 lines (159 loc) · 6.39 KB
/
unicast_ip_address_row.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"fmt"
"net"
)
// Corresponds to MIB_UNICASTIPADDRESS_ROW defined in netioapi.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_mib_unicastipaddress_row).
type UnicastIpAddressRow struct {
Address *SockaddrInet
InterfaceLuid uint64
InterfaceIndex uint32
PrefixOrigin NlPrefixOrigin
SuffixOrigin NlSuffixOrigin
ValidLifetime uint32
PreferredLifetime uint32
OnLinkPrefixLength uint8
SkipAsSource bool
DadState NlDadState
ScopeId uint32
CreationTimeStamp int64
}
func (address *UnicastIpAddressRow) equal(other *UnicastIpAddressRow) bool {
if address == nil || other == nil {
return false
}
return address.InterfaceLuid == other.InterfaceLuid && address.InterfaceIndex == other.InterfaceIndex &&
address.PrefixOrigin == other.PrefixOrigin && address.SuffixOrigin == other.SuffixOrigin &&
address.ValidLifetime == other.ValidLifetime && address.PreferredLifetime == other.PreferredLifetime &&
address.OnLinkPrefixLength == other.OnLinkPrefixLength && address.SkipAsSource == other.SkipAsSource &&
address.DadState == other.DadState && address.ScopeId == other.ScopeId &&
address.CreationTimeStamp == other.CreationTimeStamp && address.Address.equal(other.Address)
}
func (address *UnicastIpAddressRow) toWtMibUnicastipaddressRow() (*wtMibUnicastipaddressRow, error) {
if address == nil {
return nil, nil
}
wtsai, err := address.Address.toWtSockaddrInet()
if err != nil {
return nil, err
}
return &wtMibUnicastipaddressRow{
Address: *wtsai,
InterfaceLuid: address.InterfaceLuid,
InterfaceIndex: address.InterfaceIndex,
PrefixOrigin: address.PrefixOrigin,
SuffixOrigin: address.SuffixOrigin,
ValidLifetime: address.ValidLifetime,
PreferredLifetime: address.PreferredLifetime,
OnLinkPrefixLength: address.OnLinkPrefixLength,
SkipAsSource: boolToUint8(address.SkipAsSource),
DadState: address.DadState,
ScopeId: address.ScopeId,
CreationTimeStamp: address.CreationTimeStamp,
}, nil
}
func (address *UnicastIpAddressRow) copyChangeableFieldsTo(row *wtMibUnicastipaddressRow) {
row.PrefixOrigin = address.PrefixOrigin
row.SuffixOrigin = address.SuffixOrigin
row.ValidLifetime = address.ValidLifetime
row.PreferredLifetime = address.PreferredLifetime
row.OnLinkPrefixLength = address.OnLinkPrefixLength
row.SkipAsSource = boolToUint8(address.SkipAsSource)
}
// Returns all unicast IP addresses assigned to any interface. Corresponds to GetUnicastIpAddressTable function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddresstable).
func GetUnicastAddresses(family AddressFamily) ([]*UnicastIpAddressRow, error) {
wtas, err := getWtMibUnicastipaddressRows(family)
if err != nil {
return nil, err
}
count := len(wtas)
addresses := make([]*UnicastIpAddressRow, count, count)
for idx, wta := range wtas {
address, err := wta.toUnicastIpAddressRow()
if err != nil {
return nil, err
}
addresses[idx] = address
}
return addresses, nil
}
// Returns UnicastIpAddressRow struct that matches to provided 'ip' argument, or nil if no such unicast address is found
// on the system.
func GetMatchingUnicastIpAddressRow(ip *net.IP) (*UnicastIpAddressRow, error) {
row, err := getMatchingWtMibUnicastipaddressRow(ip)
if err != nil {
return nil, err
} else if row == nil {
return nil, nil
} else {
return row.toUnicastIpAddressRow()
}
}
// Adds new unicast IP address to the system. Similar to Interface.AddAddress() method, but allows setting more options.
// Additional options you can set by using this method are all "changeable" fields of UnicastIpAddressRow struct (see
// UnicastIpAddressRow.Set() method for more details).
func (address *UnicastIpAddressRow) Add() error {
wtsainet, err := address.Address.toWtSockaddrInet()
if err != nil {
return err
}
row := getInitializedWtMibUnicastipaddressRow(address.InterfaceLuid)
row.Address = *wtsainet
address.copyChangeableFieldsTo(row)
return row.add()
}
// Saves (activates) modified UnicastIpAddressRow. Corresponds to SetUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-setunicastipaddressentry).
//
// Note that fields Address, InterfaceLuid and InterfaceIndex are used for identifying address to change, meaning that
// they cannot be changed by using this method. Changing some of these fields would cause updating some other unicast IP
// address. On the other side, fields DadState, ScopeId and CreationTimeStamp are read-only, so they also cannot be
// changed. So fields that are "changeable" this way are: PrefixOrigin, SuffixOrigin, ValidLifetime, PreferredLifetime,
// OnLinkPrefixLength and SkipAsSource.
// The workflow of using this method is:
// 1) Get UnicastIpAddressRow instance by using any of getter methods (i.e. GetMatchingUnicastIpAddressRow or any other);
// 2) Change one or more of "changeable" fields enumerated above;
// 3) Calling this method to activate the changes.
func (address *UnicastIpAddressRow) Set() error {
old, err := getWtMibUnicastipaddressRow(address.InterfaceLuid, &address.Address.Address)
if err != nil {
return err
}
address.copyChangeableFieldsTo(old)
return old.set()
}
// Deletes unicast IP address from the system. Corresponds to DeleteUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry).
func (address *UnicastIpAddressRow) Delete() error {
row, err := getWtMibUnicastipaddressRow(address.InterfaceLuid, &address.Address.Address)
if err == nil {
return row.delete()
} else {
return err
}
}
func (address *UnicastIpAddressRow) String() string {
if address == nil {
return "<nil>"
}
return fmt.Sprintf(`Address: [%s]/%d
InterfaceLuid: %d
InterfaceIndex: %d
PrefixOrigin: %s
SuffixOrigin: %s
ValidLifetime: %d
PreferredLifetime: %d
SkipAsSource: %v
DadState: %s
ScopeId: %d
CreationTimeStamp: %d`, address.Address.String(), address.OnLinkPrefixLength, address.InterfaceLuid,
address.InterfaceIndex, address.PrefixOrigin.String(), address.SuffixOrigin.String(), address.ValidLifetime,
address.PreferredLifetime, address.SkipAsSource, address.DadState.String(), address.ScopeId,
address.CreationTimeStamp)
}