1
1
package kvm
2
2
3
3
import (
4
+ "bytes"
4
5
"fmt"
6
+ "net"
7
+ "os"
8
+ "strings"
9
+ "time"
10
+
11
+ "os/exec"
12
+
13
+ "github.com/hashicorp/go-envparse"
5
14
"github.com/pion/mdns/v2"
6
15
"golang.org/x/net/ipv4"
7
16
"golang.org/x/net/ipv6"
8
- "net"
9
- "os/exec"
10
- "time"
11
17
12
18
"github.com/vishvananda/netlink"
13
19
"github.com/vishvananda/netlink/nl"
14
20
)
15
21
16
22
var mDNSConn * mdns.Conn
17
23
18
- var networkState struct {
24
+ var networkState NetworkState
25
+
26
+ type NetworkState struct {
19
27
Up bool
20
28
IPv4 string
21
29
IPv6 string
22
30
MAC string
31
+
32
+ checked bool
23
33
}
24
34
25
35
type LocalIpInfo struct {
@@ -28,43 +38,45 @@ type LocalIpInfo struct {
28
38
MAC string
29
39
}
30
40
41
+ const (
42
+ NetIfName = "eth0"
43
+ DHCPLeaseFile = "/run/udhcpc.%s.info"
44
+ )
45
+
31
46
// setDhcpClientState sends signals to udhcpc to change it's current mode
32
47
// of operation. Setting active to true will force udhcpc to renew the DHCP lease.
33
48
// Setting active to false will put udhcpc into idle mode.
34
49
func setDhcpClientState (active bool ) {
35
- var signal string ;
50
+ var signal string
36
51
if active {
37
52
signal = "-SIGUSR1"
38
53
} else {
39
54
signal = "-SIGUSR2"
40
55
}
41
56
42
- cmd := exec .Command ("/usr/bin/killall" , signal , "udhcpc" );
57
+ cmd := exec .Command ("/usr/bin/killall" , signal , "udhcpc" )
43
58
if err := cmd .Run (); err != nil {
44
59
fmt .Printf ("network: setDhcpClientState: failed to change udhcpc state: %s\n " , err )
45
60
}
46
61
}
47
62
48
63
func checkNetworkState () {
49
- iface , err := netlink .LinkByName ("eth0" )
64
+ iface , err := netlink .LinkByName (NetIfName )
50
65
if err != nil {
51
- fmt .Printf ("failed to get eth0 interface: %v\n " , err )
66
+ fmt .Printf ("failed to get [%s] interface: %v\n " , NetIfName , err )
52
67
return
53
68
}
54
69
55
- newState := struct {
56
- Up bool
57
- IPv4 string
58
- IPv6 string
59
- MAC string
60
- }{
70
+ newState := NetworkState {
61
71
Up : iface .Attrs ().OperState == netlink .OperUp ,
62
72
MAC : iface .Attrs ().HardwareAddr .String (),
73
+
74
+ checked : true ,
63
75
}
64
76
65
77
addrs , err := netlink .AddrList (iface , nl .FAMILY_ALL )
66
78
if err != nil {
67
- fmt .Printf ("failed to get addresses for eth0 : %v\n " , err )
79
+ fmt .Printf ("failed to get addresses for [%s] : %v\n " , NetIfName , err )
68
80
}
69
81
70
82
// If the link is going down, put udhcpc into idle mode.
@@ -94,15 +106,15 @@ func checkNetworkState() {
94
106
95
107
if newState != networkState {
96
108
fmt .Println ("network state changed" )
97
- //restart MDNS
109
+ // restart MDNS
98
110
startMDNS ()
99
111
networkState = newState
100
112
requestDisplayUpdate ()
101
113
}
102
114
}
103
115
104
116
func startMDNS () error {
105
- //If server was previously running, stop it
117
+ // If server was previously running, stop it
106
118
if mDNSConn != nil {
107
119
fmt .Printf ("Stopping mDNS server\n " )
108
120
err := mDNSConn .Close ()
@@ -111,7 +123,7 @@ func startMDNS() error {
111
123
}
112
124
}
113
125
114
- //Start a new server
126
+ // Start a new server
115
127
fmt .Printf ("Starting mDNS server on jetkvm.local\n " )
116
128
addr4 , err := net .ResolveUDPAddr ("udp4" , mdns .DefaultAddressIPv4 )
117
129
if err != nil {
@@ -144,6 +156,39 @@ func startMDNS() error {
144
156
return nil
145
157
}
146
158
159
+ func getNTPServersFromDHCPInfo () ([]string , error ) {
160
+ buf , err := os .ReadFile (fmt .Sprintf (DHCPLeaseFile , NetIfName ))
161
+ if err != nil {
162
+ // do not return error if file does not exist
163
+ if os .IsNotExist (err ) {
164
+ return nil , nil
165
+ }
166
+ return nil , fmt .Errorf ("failed to load udhcpc info: %w" , err )
167
+ }
168
+
169
+ // parse udhcpc info
170
+ env , err := envparse .Parse (bytes .NewReader (buf ))
171
+ if err != nil {
172
+ return nil , fmt .Errorf ("failed to parse udhcpc info: %w" , err )
173
+ }
174
+
175
+ val , ok := env ["ntpsrv" ]
176
+ if ! ok {
177
+ return nil , nil
178
+ }
179
+
180
+ var servers []string
181
+
182
+ for _ , server := range strings .Fields (val ) {
183
+ if net .ParseIP (server ) == nil {
184
+ fmt .Printf ("invalid NTP server IP: %s, ignoring ... \n " , server )
185
+ }
186
+ servers = append (servers , server )
187
+ }
188
+
189
+ return servers , nil
190
+ }
191
+
147
192
func init () {
148
193
updates := make (chan netlink.LinkUpdate )
149
194
done := make (chan struct {})
@@ -162,7 +207,7 @@ func init() {
162
207
for {
163
208
select {
164
209
case update := <- updates :
165
- if update .Link .Attrs ().Name == "eth0" {
210
+ if update .Link .Attrs ().Name == NetIfName {
166
211
fmt .Printf ("link update: %+v\n " , update )
167
212
checkNetworkState ()
168
213
}
0 commit comments