github.com/pawelgaczynski/gain@v0.4.0-alpha.0.20230821120126-41f1e60a18da/pkg/socket/sock_posix.go (about) 1 /* 2 * Copyright 2009 The Go Authors. All rights reserved. 3 * Copyright (c) 2022 Andy Pan. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package socket 20 21 import ( 22 "fmt" 23 "net" 24 "syscall" 25 26 "golang.org/x/sys/unix" 27 ) 28 29 func ipToSockaddrInet4(ip net.IP, port int) (unix.SockaddrInet4, error) { 30 if len(ip) == 0 { 31 ip = net.IPv4zero 32 } 33 34 ip4 := ip.To4() 35 if ip4 == nil { 36 return unix.SockaddrInet4{}, &net.AddrError{Err: "non-IPv4 address", Addr: ip.String()} 37 } 38 sa := unix.SockaddrInet4{Port: port} 39 copy(sa.Addr[:], ip4) 40 41 return sa, nil 42 } 43 44 func ipToSockaddrInet6(ip net.IP, port int, zone string) (unix.SockaddrInet6, error) { 45 // In general, an IP wildcard address, which is either 46 // "0.0.0.0" or "::", means the entire IP addressing 47 // space. For some historical reason, it is used to 48 // specify "any available address" on some operations 49 // of IP node. 50 // 51 // When the IP node supports IPv4-mapped IPv6 address, 52 // we allow a listener to listen to the wildcard 53 // address of both IP addressing spaces by specifying 54 // IPv6 wildcard address. 55 if len(ip) == 0 || ip.Equal(net.IPv4zero) { 56 ip = net.IPv6zero 57 } 58 // We accept any IPv6 address including IPv4-mapped 59 // IPv6 address. 60 ip6 := ip.To16() 61 if ip6 == nil { 62 return unix.SockaddrInet6{}, &net.AddrError{Err: "non-IPv6 address", Addr: ip.String()} 63 } 64 65 sockAddr := unix.SockaddrInet6{Port: port} 66 copy(sockAddr.Addr[:], ip6) 67 68 iface, err := net.InterfaceByName(zone) 69 if err != nil { 70 return sockAddr, fmt.Errorf("interfaceByName: %w", err) 71 } 72 sockAddr.ZoneId = uint32(iface.Index) 73 74 return sockAddr, nil 75 } 76 77 func ipToSockaddr(family int, ip net.IP, port int, zone string) (unix.Sockaddr, error) { 78 switch family { 79 case syscall.AF_INET: 80 sa, err := ipToSockaddrInet4(ip, port) 81 if err != nil { 82 return nil, err 83 } 84 85 return &sa, nil 86 87 case syscall.AF_INET6: 88 sa, err := ipToSockaddrInet6(ip, port, zone) 89 if err != nil { 90 return nil, err 91 } 92 93 return &sa, nil 94 } 95 96 return nil, &net.AddrError{Err: "invalid address family", Addr: ip.String()} 97 }