ioctl_linux.go (11577B)
1 // Copyright 2021 The Go Authors. 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 5 package unix 6 7 import "unsafe" 8 9 // IoctlRetInt performs an ioctl operation specified by req on a device 10 // associated with opened file descriptor fd, and returns a non-negative 11 // integer that is returned by the ioctl syscall. 12 func IoctlRetInt(fd int, req uint) (int, error) { 13 ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0) 14 if err != 0 { 15 return 0, err 16 } 17 return int(ret), nil 18 } 19 20 func IoctlGetUint32(fd int, req uint) (uint32, error) { 21 var value uint32 22 err := ioctlPtr(fd, req, unsafe.Pointer(&value)) 23 return value, err 24 } 25 26 func IoctlGetRTCTime(fd int) (*RTCTime, error) { 27 var value RTCTime 28 err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value)) 29 return &value, err 30 } 31 32 func IoctlSetRTCTime(fd int, value *RTCTime) error { 33 return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value)) 34 } 35 36 func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { 37 var value RTCWkAlrm 38 err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value)) 39 return &value, err 40 } 41 42 func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error { 43 return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value)) 44 } 45 46 // IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network 47 // device specified by ifname. 48 func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { 49 ifr, err := NewIfreq(ifname) 50 if err != nil { 51 return nil, err 52 } 53 54 value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO} 55 ifrd := ifr.withData(unsafe.Pointer(&value)) 56 57 err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd) 58 return &value, err 59 } 60 61 // IoctlGetEthtoolTsInfo fetches ethtool timestamping and PHC 62 // association for the network device specified by ifname. 63 func IoctlGetEthtoolTsInfo(fd int, ifname string) (*EthtoolTsInfo, error) { 64 ifr, err := NewIfreq(ifname) 65 if err != nil { 66 return nil, err 67 } 68 69 value := EthtoolTsInfo{Cmd: ETHTOOL_GET_TS_INFO} 70 ifrd := ifr.withData(unsafe.Pointer(&value)) 71 72 err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd) 73 return &value, err 74 } 75 76 // IoctlGetHwTstamp retrieves the hardware timestamping configuration 77 // for the network device specified by ifname. 78 func IoctlGetHwTstamp(fd int, ifname string) (*HwTstampConfig, error) { 79 ifr, err := NewIfreq(ifname) 80 if err != nil { 81 return nil, err 82 } 83 84 value := HwTstampConfig{} 85 ifrd := ifr.withData(unsafe.Pointer(&value)) 86 87 err = ioctlIfreqData(fd, SIOCGHWTSTAMP, &ifrd) 88 return &value, err 89 } 90 91 // IoctlSetHwTstamp updates the hardware timestamping configuration for 92 // the network device specified by ifname. 93 func IoctlSetHwTstamp(fd int, ifname string, cfg *HwTstampConfig) error { 94 ifr, err := NewIfreq(ifname) 95 if err != nil { 96 return err 97 } 98 ifrd := ifr.withData(unsafe.Pointer(cfg)) 99 return ioctlIfreqData(fd, SIOCSHWTSTAMP, &ifrd) 100 } 101 102 // FdToClockID derives the clock ID from the file descriptor number 103 // - see clock_gettime(3), FD_TO_CLOCKID macros. The resulting ID is 104 // suitable for system calls like ClockGettime. 105 func FdToClockID(fd int) int32 { return int32((int(^fd) << 3) | 3) } 106 107 // IoctlPtpClockGetcaps returns the description of a given PTP device. 108 func IoctlPtpClockGetcaps(fd int) (*PtpClockCaps, error) { 109 var value PtpClockCaps 110 err := ioctlPtr(fd, PTP_CLOCK_GETCAPS2, unsafe.Pointer(&value)) 111 return &value, err 112 } 113 114 // IoctlPtpSysOffsetPrecise returns a description of the clock 115 // offset compared to the system clock. 116 func IoctlPtpSysOffsetPrecise(fd int) (*PtpSysOffsetPrecise, error) { 117 var value PtpSysOffsetPrecise 118 err := ioctlPtr(fd, PTP_SYS_OFFSET_PRECISE2, unsafe.Pointer(&value)) 119 return &value, err 120 } 121 122 // IoctlPtpSysOffsetExtended returns an extended description of the 123 // clock offset compared to the system clock. The samples parameter 124 // specifies the desired number of measurements. 125 func IoctlPtpSysOffsetExtended(fd int, samples uint) (*PtpSysOffsetExtended, error) { 126 value := PtpSysOffsetExtended{Samples: uint32(samples)} 127 err := ioctlPtr(fd, PTP_SYS_OFFSET_EXTENDED2, unsafe.Pointer(&value)) 128 return &value, err 129 } 130 131 // IoctlPtpPinGetfunc returns the configuration of the specified 132 // I/O pin on given PTP device. 133 func IoctlPtpPinGetfunc(fd int, index uint) (*PtpPinDesc, error) { 134 value := PtpPinDesc{Index: uint32(index)} 135 err := ioctlPtr(fd, PTP_PIN_GETFUNC2, unsafe.Pointer(&value)) 136 return &value, err 137 } 138 139 // IoctlPtpPinSetfunc updates configuration of the specified PTP 140 // I/O pin. 141 func IoctlPtpPinSetfunc(fd int, pd *PtpPinDesc) error { 142 return ioctlPtr(fd, PTP_PIN_SETFUNC2, unsafe.Pointer(pd)) 143 } 144 145 // IoctlPtpPeroutRequest configures the periodic output mode of the 146 // PTP I/O pins. 147 func IoctlPtpPeroutRequest(fd int, r *PtpPeroutRequest) error { 148 return ioctlPtr(fd, PTP_PEROUT_REQUEST2, unsafe.Pointer(r)) 149 } 150 151 // IoctlPtpExttsRequest configures the external timestamping mode 152 // of the PTP I/O pins. 153 func IoctlPtpExttsRequest(fd int, r *PtpExttsRequest) error { 154 return ioctlPtr(fd, PTP_EXTTS_REQUEST2, unsafe.Pointer(r)) 155 } 156 157 // IoctlGetWatchdogInfo fetches information about a watchdog device from the 158 // Linux watchdog API. For more information, see: 159 // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. 160 func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { 161 var value WatchdogInfo 162 err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value)) 163 return &value, err 164 } 165 166 // IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For 167 // more information, see: 168 // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. 169 func IoctlWatchdogKeepalive(fd int) error { 170 // arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr. 171 return ioctl(fd, WDIOC_KEEPALIVE, 0) 172 } 173 174 // IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the 175 // range of data conveyed in value to the file associated with the file 176 // descriptor destFd. See the ioctl_ficlonerange(2) man page for details. 177 func IoctlFileCloneRange(destFd int, value *FileCloneRange) error { 178 return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value)) 179 } 180 181 // IoctlFileClone performs an FICLONE ioctl operation to clone the entire file 182 // associated with the file description srcFd to the file associated with the 183 // file descriptor destFd. See the ioctl_ficlone(2) man page for details. 184 func IoctlFileClone(destFd, srcFd int) error { 185 return ioctl(destFd, FICLONE, uintptr(srcFd)) 186 } 187 188 type FileDedupeRange struct { 189 Src_offset uint64 190 Src_length uint64 191 Reserved1 uint16 192 Reserved2 uint32 193 Info []FileDedupeRangeInfo 194 } 195 196 type FileDedupeRangeInfo struct { 197 Dest_fd int64 198 Dest_offset uint64 199 Bytes_deduped uint64 200 Status int32 201 Reserved uint32 202 } 203 204 // IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the 205 // range of data conveyed in value from the file associated with the file 206 // descriptor srcFd to the value.Info destinations. See the 207 // ioctl_fideduperange(2) man page for details. 208 func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error { 209 buf := make([]byte, SizeofRawFileDedupeRange+ 210 len(value.Info)*SizeofRawFileDedupeRangeInfo) 211 rawrange := (*RawFileDedupeRange)(unsafe.Pointer(&buf[0])) 212 rawrange.Src_offset = value.Src_offset 213 rawrange.Src_length = value.Src_length 214 rawrange.Dest_count = uint16(len(value.Info)) 215 rawrange.Reserved1 = value.Reserved1 216 rawrange.Reserved2 = value.Reserved2 217 218 for i := range value.Info { 219 rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer( 220 uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) + 221 uintptr(i*SizeofRawFileDedupeRangeInfo))) 222 rawinfo.Dest_fd = value.Info[i].Dest_fd 223 rawinfo.Dest_offset = value.Info[i].Dest_offset 224 rawinfo.Bytes_deduped = value.Info[i].Bytes_deduped 225 rawinfo.Status = value.Info[i].Status 226 rawinfo.Reserved = value.Info[i].Reserved 227 } 228 229 err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0])) 230 231 // Output 232 for i := range value.Info { 233 rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer( 234 uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) + 235 uintptr(i*SizeofRawFileDedupeRangeInfo))) 236 value.Info[i].Dest_fd = rawinfo.Dest_fd 237 value.Info[i].Dest_offset = rawinfo.Dest_offset 238 value.Info[i].Bytes_deduped = rawinfo.Bytes_deduped 239 value.Info[i].Status = rawinfo.Status 240 value.Info[i].Reserved = rawinfo.Reserved 241 } 242 243 return err 244 } 245 246 func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error { 247 return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value)) 248 } 249 250 func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) { 251 var value HIDRawDevInfo 252 err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value)) 253 return &value, err 254 } 255 256 func IoctlHIDGetRawName(fd int) (string, error) { 257 var value [_HIDIOCGRAWNAME_LEN]byte 258 err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0])) 259 return ByteSliceToString(value[:]), err 260 } 261 262 func IoctlHIDGetRawPhys(fd int) (string, error) { 263 var value [_HIDIOCGRAWPHYS_LEN]byte 264 err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0])) 265 return ByteSliceToString(value[:]), err 266 } 267 268 func IoctlHIDGetRawUniq(fd int) (string, error) { 269 var value [_HIDIOCGRAWUNIQ_LEN]byte 270 err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0])) 271 return ByteSliceToString(value[:]), err 272 } 273 274 // IoctlIfreq performs an ioctl using an Ifreq structure for input and/or 275 // output. See the netdevice(7) man page for details. 276 func IoctlIfreq(fd int, req uint, value *Ifreq) error { 277 // It is possible we will add more fields to *Ifreq itself later to prevent 278 // misuse, so pass the raw *ifreq directly. 279 return ioctlPtr(fd, req, unsafe.Pointer(&value.raw)) 280 } 281 282 // TODO(mdlayher): export if and when IfreqData is exported. 283 284 // ioctlIfreqData performs an ioctl using an ifreqData structure for input 285 // and/or output. See the netdevice(7) man page for details. 286 func ioctlIfreqData(fd int, req uint, value *ifreqData) error { 287 // The memory layout of IfreqData (type-safe) and ifreq (not type-safe) are 288 // identical so pass *IfreqData directly. 289 return ioctlPtr(fd, req, unsafe.Pointer(value)) 290 } 291 292 // IoctlKCMClone attaches a new file descriptor to a multiplexor by cloning an 293 // existing KCM socket, returning a structure containing the file descriptor of 294 // the new socket. 295 func IoctlKCMClone(fd int) (*KCMClone, error) { 296 var info KCMClone 297 if err := ioctlPtr(fd, SIOCKCMCLONE, unsafe.Pointer(&info)); err != nil { 298 return nil, err 299 } 300 301 return &info, nil 302 } 303 304 // IoctlKCMAttach attaches a TCP socket and associated BPF program file 305 // descriptor to a multiplexor. 306 func IoctlKCMAttach(fd int, info KCMAttach) error { 307 return ioctlPtr(fd, SIOCKCMATTACH, unsafe.Pointer(&info)) 308 } 309 310 // IoctlKCMUnattach unattaches a TCP socket file descriptor from a multiplexor. 311 func IoctlKCMUnattach(fd int, info KCMUnattach) error { 312 return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info)) 313 } 314 315 // IoctlLoopGetStatus64 gets the status of the loop device associated with the 316 // file descriptor fd using the LOOP_GET_STATUS64 operation. 317 func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) { 318 var value LoopInfo64 319 if err := ioctlPtr(fd, LOOP_GET_STATUS64, unsafe.Pointer(&value)); err != nil { 320 return nil, err 321 } 322 return &value, nil 323 } 324 325 // IoctlLoopSetStatus64 sets the status of the loop device associated with the 326 // file descriptor fd using the LOOP_SET_STATUS64 operation. 327 func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error { 328 return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value)) 329 } 330 331 // IoctlLoopConfigure configures all loop device parameters in a single step 332 func IoctlLoopConfigure(fd int, value *LoopConfig) error { 333 return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value)) 334 }