github.com/vmware/govmomi@v0.37.1/toolbox/guest_info.go (about) 1 /* 2 Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package toolbox 18 19 import ( 20 "bytes" 21 "fmt" 22 "net" 23 24 xdr "github.com/rasky/go-xdr/xdr2" 25 ) 26 27 // Defs from: open-vm-tools/lib/guestRpc/nicinfo.x 28 29 type TypedIPAddress struct { 30 Type int32 31 Address []byte 32 } 33 34 type IPAddressEntry struct { 35 Address TypedIPAddress 36 PrefixLength uint32 37 Origin *int32 `xdr:"optional"` 38 Status *int32 `xdr:"optional"` 39 } 40 41 type InetCidrRouteEntry struct { 42 Dest TypedIPAddress 43 PrefixLength uint32 44 NextHop *TypedIPAddress `xdr:"optional"` 45 IfIndex uint32 46 Type int32 47 Metric uint32 48 } 49 50 type DNSConfigInfo struct { 51 HostName *string `xdr:"optional"` 52 DomainName *string `xdr:"optional"` 53 Servers []TypedIPAddress 54 Search *string `xdr:"optional"` 55 } 56 57 type WinsConfigInfo struct { 58 Primary TypedIPAddress 59 Secondary TypedIPAddress 60 } 61 62 type DhcpConfigInfo struct { 63 Enabled bool 64 Settings string 65 } 66 67 type GuestNicV3 struct { 68 MacAddress string 69 IPs []IPAddressEntry 70 DNSConfigInfo *DNSConfigInfo `xdr:"optional"` 71 WinsConfigInfo *WinsConfigInfo `xdr:"optional"` 72 DhcpConfigInfov4 *DhcpConfigInfo `xdr:"optional"` 73 DhcpConfigInfov6 *DhcpConfigInfo `xdr:"optional"` 74 } 75 76 type NicInfoV3 struct { 77 Nics []GuestNicV3 78 Routes []InetCidrRouteEntry 79 DNSConfigInfo *DNSConfigInfo `xdr:"optional"` 80 WinsConfigInfo *WinsConfigInfo `xdr:"optional"` 81 DhcpConfigInfov4 *DhcpConfigInfo `xdr:"optional"` 82 DhcpConfigInfov6 *DhcpConfigInfo `xdr:"optional"` 83 } 84 85 type GuestNicInfo struct { 86 Version int32 87 V3 *NicInfoV3 `xdr:"optional"` 88 } 89 90 func EncodeXDR(val interface{}) ([]byte, error) { 91 var buf bytes.Buffer 92 93 _, err := xdr.Marshal(&buf, val) 94 if err != nil { 95 return nil, err 96 } 97 98 return buf.Bytes(), nil 99 } 100 101 func DecodeXDR(buf []byte, val interface{}) error { 102 r := bytes.NewReader(buf) 103 _, err := xdr.Unmarshal(r, val) 104 return err 105 } 106 107 func NewGuestNicInfo() *GuestNicInfo { 108 return &GuestNicInfo{ 109 Version: 3, 110 V3: &NicInfoV3{}, 111 } 112 } 113 114 func (nic *GuestNicV3) AddIP(addr net.Addr) { 115 ip, ok := addr.(*net.IPNet) 116 if !ok { 117 return 118 } 119 120 kind := int32(1) // IAT_IPV4 121 if ip.IP.To4() == nil { 122 kind = 2 // IAT_IPV6 123 } else { 124 ip.IP = ip.IP.To4() // convert to 4-byte representation 125 } 126 127 size, _ := ip.Mask.Size() 128 129 // nicinfo.x defines enum IpAddressStatus, but vmtoolsd only uses IAS_PREFERRED 130 var status int32 = 1 // IAS_PREFERRED 131 132 e := IPAddressEntry{ 133 Address: TypedIPAddress{ 134 Type: kind, 135 Address: []byte(ip.IP), 136 }, 137 PrefixLength: uint32(size), 138 Status: &status, 139 } 140 141 nic.IPs = append(nic.IPs, e) 142 } 143 144 func GuestInfoCommand(kind int, req []byte) []byte { 145 request := fmt.Sprintf("SetGuestInfo %d ", kind) 146 return append([]byte(request), req...) 147 } 148 149 var ( 150 netInterfaces = net.Interfaces 151 maxNics = 16 // guestRpc/nicinfo.x:NICINFO_MAX_NICS 152 ) 153 154 func DefaultGuestNicInfo() *GuestNicInfo { 155 proto := NewGuestNicInfo() 156 info := proto.V3 157 // #nosec: Errors unhandled 158 ifs, _ := netInterfaces() 159 160 for _, i := range ifs { 161 if i.Flags&net.FlagLoopback == net.FlagLoopback { 162 continue 163 } 164 165 if len(i.HardwareAddr) == 0 { 166 continue // Not useful from outside the guest without a MAC 167 } 168 169 // #nosec: Errors unhandled 170 addrs, _ := i.Addrs() 171 172 if len(addrs) == 0 { 173 continue // Not useful from outside the guest without an IP 174 } 175 176 nic := GuestNicV3{ 177 MacAddress: i.HardwareAddr.String(), 178 } 179 180 for _, addr := range addrs { 181 nic.AddIP(addr) 182 } 183 184 info.Nics = append(info.Nics, nic) 185 186 if len(info.Nics) >= maxNics { 187 break 188 } 189 } 190 191 return proto 192 } 193 194 func GuestInfoNicInfoRequest() ([]byte, error) { 195 r, err := EncodeXDR(DefaultGuestNicInfo()) 196 if err != nil { 197 return nil, err 198 } 199 200 return GuestInfoCommand(9 /*INFO_IPADDRESS_V3*/, r), nil 201 }