net.go 7.57 KB
Newer Older
Steven Allen's avatar
Steven Allen committed
1
// package sockaddrnet provides conversions between net.Addr and Sockaddr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
2
package sockaddrnet
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
3 4 5 6 7

import (
	"net"
)

Steven Allen's avatar
Steven Allen committed
8
// NetAddrAF returns the unix AF_* type for a given net.Addr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
9
// returns AF_UNSPEC if unknown
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
10 11 12 13 14 15 16 17 18 19 20 21
func NetAddrAF(addr net.Addr) int {
	switch addr := addr.(type) {
	case *net.IPAddr:
		return IPAF(addr.IP)

	case *net.TCPAddr:
		return IPAF(addr.IP)

	case *net.UDPAddr:
		return IPAF(addr.IP)

	case *net.UnixAddr:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
22
		return AF_UNIX
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
23 24 25

	default:
		return AF_UNSPEC
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
26 27 28
	}
}

Steven Allen's avatar
Steven Allen committed
29
// IPAF returns the unix AF_* type for a given IP address
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
30
// returns AF_UNSPEC if unknown
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
31 32 33
func IPAF(ip net.IP) int {
	switch {
	case ip.To4() != nil:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
34
		return AF_INET
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
35 36

	case ip.To16() != nil:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
37
		return AF_INET6
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
38 39 40

	default:
		return AF_UNSPEC
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
41 42 43
	}
}

Steven Allen's avatar
Steven Allen committed
44
// NetAddrIPPROTO returns the unix IPPROTO_* type for a given net.Addr
45 46 47 48 49 50
// returns -1 if protocol unknown
func NetAddrIPPROTO(addr net.Addr) int {
	switch addr := addr.(type) {
	case *net.IPAddr:
		switch {
		default:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
51
			return IPPROTO_IP
52 53

		case addr.IP.To4() != nil:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
54
			return IPPROTO_IPV4
55 56

		case addr.IP.To16() != nil:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
57
			return IPPROTO_IPV6
58 59 60
		}

	case *net.TCPAddr:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
61
		return IPPROTO_TCP
62 63

	case *net.UDPAddr:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
64
		return IPPROTO_UDP
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
65 66 67

	default:
		return -1
68 69 70
	}
}

Steven Allen's avatar
Steven Allen committed
71
// NetAddrSOCK returns the unix SOCK_* type for a given net.Addr
72 73 74 75
// returns 0 if type unknown
func NetAddrSOCK(addr net.Addr) int {
	switch addr := addr.(type) {
	case *net.IPAddr:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
76
		return SOCK_DGRAM
77
	case *net.TCPAddr:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
78
		return SOCK_STREAM
79
	case *net.UDPAddr:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
80
		return SOCK_DGRAM
81 82 83 84 85
	case *net.UnixAddr:
		switch addr.Net {
		default:
			return 0
		case "unix":
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
86
			return SOCK_STREAM
87
		case "unixgram":
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
88
			return SOCK_DGRAM
89
		case "unixpacket":
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
90
			return SOCK_SEQPACKET
91
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
92 93
	default:
		return 0
94 95 96
	}
}

Steven Allen's avatar
Steven Allen committed
97
// NetAddrToSockaddr converts a net.Addr to a Sockaddr.
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
98
// Returns nil if the input is invalid or conversion is not possible.
Steven Allen's avatar
Steven Allen committed
99
func NetAddrToSockaddr(addr net.Addr) Sockaddr {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
100 101 102 103 104 105 106 107 108 109
	switch addr := addr.(type) {
	case *net.IPAddr:
		return IPAddrToSockaddr(addr)
	case *net.TCPAddr:
		return TCPAddrToSockaddr(addr)
	case *net.UDPAddr:
		return UDPAddrToSockaddr(addr)
	case *net.UnixAddr:
		sa, _ := UnixAddrToSockaddr(addr)
		return sa
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
110 111
	default:
		return nil
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
112 113 114
	}
}

Steven Allen's avatar
Steven Allen committed
115
// IPAndZoneToSockaddr converts a net.IP (with optional IPv6 Zone) to a Sockaddr
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
116
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
117
func IPAndZoneToSockaddr(ip net.IP, zone string) Sockaddr {
118
	if ip4 := ip.To4(); ip4 != nil {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
119
		var buf [4]byte
120
		copy(buf[:], ip4) // last 4 bytes
Steven Allen's avatar
Steven Allen committed
121
		return &SockaddrInet4{Addr: buf}
122 123
	}
	if ip6 := ip.To16(); ip6 != nil {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
124
		var buf [16]byte
125
		copy(buf[:], ip6)
Steven Allen's avatar
Steven Allen committed
126
		return &SockaddrInet6{Addr: buf, ZoneId: uint32(IP6ZoneToInt(zone))}
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
127
	}
128 129 130 131 132
	if len(ip) == 0 {
		buf := [4]byte{0, 0, 0, 0}
		return &SockaddrInet4{Addr: buf}
	}
	panic("invalid IP address")
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
133 134
}

Steven Allen's avatar
Steven Allen committed
135
// IPAddrToSockaddr converts a net.IPAddr to a Sockaddr.
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
136
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
137
func IPAddrToSockaddr(addr *net.IPAddr) Sockaddr {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
138 139 140
	return IPAndZoneToSockaddr(addr.IP, addr.Zone)
}

Steven Allen's avatar
Steven Allen committed
141
// TCPAddrToSockaddr converts a net.TCPAddr to a Sockaddr.
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
142
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
143
func TCPAddrToSockaddr(addr *net.TCPAddr) Sockaddr {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
144 145
	sa := IPAndZoneToSockaddr(addr.IP, addr.Zone)
	switch sa := sa.(type) {
Steven Allen's avatar
Steven Allen committed
146
	case *SockaddrInet4:
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
147 148
		sa.Port = addr.Port
		return sa
Steven Allen's avatar
Steven Allen committed
149
	case *SockaddrInet6:
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
150 151
		sa.Port = addr.Port
		return sa
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
152 153
	default:
		return nil
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
154 155 156
	}
}

Steven Allen's avatar
Steven Allen committed
157
// UDPAddrToSockaddr converts a net.UDPAddr to a Sockaddr.
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
158
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
159
func UDPAddrToSockaddr(addr *net.UDPAddr) Sockaddr {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
160 161
	sa := IPAndZoneToSockaddr(addr.IP, addr.Zone)
	switch sa := sa.(type) {
Steven Allen's avatar
Steven Allen committed
162
	case *SockaddrInet4:
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
163 164
		sa.Port = addr.Port
		return sa
Steven Allen's avatar
Steven Allen committed
165
	case *SockaddrInet6:
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
166 167
		sa.Port = addr.Port
		return sa
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
168 169
	default:
		return nil
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
170 171 172
	}
}

Steven Allen's avatar
Steven Allen committed
173
// UnixAddrToSockaddr converts a net.UnixAddr to a Sockaddr, and returns
Steven Allen's avatar
Steven Allen committed
174
// the type (unix.SOCK_STREAM, unix.SOCK_DGRAM, unix.SOCK_SEQPACKET)
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
175
// Returns (nil, 0) if conversion fails.
Steven Allen's avatar
Steven Allen committed
176
func UnixAddrToSockaddr(addr *net.UnixAddr) (Sockaddr, int) {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
177 178 179
	t := 0
	switch addr.Net {
	case "unix":
Steven Allen's avatar
Steven Allen committed
180
		t = SOCK_STREAM
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
181
	case "unixgram":
Steven Allen's avatar
Steven Allen committed
182
		t = SOCK_DGRAM
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
183
	case "unixpacket":
Steven Allen's avatar
Steven Allen committed
184
		t = SOCK_SEQPACKET
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
185 186
	default:
		return nil, 0
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
187
	}
Steven Allen's avatar
Steven Allen committed
188
	return &SockaddrUnix{Name: addr.Name}, t
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
189 190
}

Steven Allen's avatar
Steven Allen committed
191
// IPAndZoneToSockaddr converts a net.IP (with optional IPv6 Zone) to a Sockaddr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
192
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
193
func SockaddrToIPAndZone(sa Sockaddr) (net.IP, string) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
194
	switch sa := sa.(type) {
Steven Allen's avatar
Steven Allen committed
195
	case *SockaddrInet4:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
196
		ip := make([]byte, 16)
197 198 199
		// V4InV6Prefix
		ip[10] = 0xff
		ip[11] = 0xff
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
200 201 202
		copy(ip[12:16], sa.Addr[:])
		return ip, ""

Steven Allen's avatar
Steven Allen committed
203
	case *SockaddrInet6:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
204
		ip := make([]byte, 16)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
205 206 207 208 209 210
		copy(ip, sa.Addr[:])
		return ip, IP6ZoneToString(int(sa.ZoneId))
	}
	return nil, ""
}

Steven Allen's avatar
Steven Allen committed
211
// SockaddrToIPAddr converts a Sockaddr to a net.IPAddr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
212
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
213
func SockaddrToIPAddr(sa Sockaddr) *net.IPAddr {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
214 215
	ip, zone := SockaddrToIPAndZone(sa)
	switch sa.(type) {
Steven Allen's avatar
Steven Allen committed
216
	case *SockaddrInet4:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
217
		return &net.IPAddr{IP: ip}
Steven Allen's avatar
Steven Allen committed
218
	case *SockaddrInet6:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
219 220 221 222 223
		return &net.IPAddr{IP: ip, Zone: zone}
	}
	return nil
}

Steven Allen's avatar
Steven Allen committed
224
// SockaddrToTCPAddr converts a Sockaddr to a net.TCPAddr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
225
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
226
func SockaddrToTCPAddr(sa Sockaddr) *net.TCPAddr {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
227 228
	ip, zone := SockaddrToIPAndZone(sa)
	switch sa := sa.(type) {
Steven Allen's avatar
Steven Allen committed
229
	case *SockaddrInet4:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
230
		return &net.TCPAddr{IP: ip, Port: sa.Port}
Steven Allen's avatar
Steven Allen committed
231
	case *SockaddrInet6:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
232 233 234 235 236
		return &net.TCPAddr{IP: ip, Port: sa.Port, Zone: zone}
	}
	return nil
}

Steven Allen's avatar
Steven Allen committed
237
// SockaddrToUDPAddr converts a Sockaddr to a net.UDPAddr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
238
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
239
func SockaddrToUDPAddr(sa Sockaddr) *net.UDPAddr {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
240 241
	ip, zone := SockaddrToIPAndZone(sa)
	switch sa := sa.(type) {
Steven Allen's avatar
Steven Allen committed
242
	case *SockaddrInet4:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
243
		return &net.UDPAddr{IP: ip, Port: sa.Port}
Steven Allen's avatar
Steven Allen committed
244
	case *SockaddrInet6:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
245 246 247 248 249
		return &net.UDPAddr{IP: ip, Port: sa.Port, Zone: zone}
	}
	return nil
}

Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
250 251
// from: go/src/pkg/net/unixsock_posix.go

Steven Allen's avatar
Steven Allen committed
252
// SockaddrToUnixAddr converts a Sockaddr to a net.UnixAddr
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
253
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
254 255
func SockaddrToUnixAddr(sa Sockaddr) *net.UnixAddr {
	if s, ok := sa.(*SockaddrUnix); ok {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
256 257 258 259 260
		return &net.UnixAddr{Name: s.Name, Net: "unix"}
	}
	return nil
}

Steven Allen's avatar
Steven Allen committed
261
// SockaddrToUnixgramAddr converts a Sockaddr to a net.UnixAddr
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
262
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
263 264
func SockaddrToUnixgramAddr(sa Sockaddr) *net.UnixAddr {
	if s, ok := sa.(*SockaddrUnix); ok {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
265 266 267 268 269
		return &net.UnixAddr{Name: s.Name, Net: "unixgram"}
	}
	return nil
}

Steven Allen's avatar
Steven Allen committed
270
// SockaddrToUnixpacketAddr converts a Sockaddr to a net.UnixAddr
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
271
// Returns nil if conversion fails.
Steven Allen's avatar
Steven Allen committed
272 273
func SockaddrToUnixpacketAddr(sa Sockaddr) *net.UnixAddr {
	if s, ok := sa.(*SockaddrUnix); ok {
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
274 275 276 277 278 279 280
		return &net.UnixAddr{Name: s.Name, Net: "unixpacket"}
	}
	return nil
}

// from: go/src/pkg/net/ipsock.go

Steven Allen's avatar
Steven Allen committed
281
// IP6ZoneToString converts an IP6 Zone unix int to a net string
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
282 283 284 285 286 287 288 289 290 291 292
// returns "" if zone is 0
func IP6ZoneToString(zone int) string {
	if zone == 0 {
		return ""
	}
	if ifi, err := net.InterfaceByIndex(zone); err == nil {
		return ifi.Name
	}
	return itod(uint(zone))
}

Steven Allen's avatar
Steven Allen committed
293
// IP6ZoneToInt converts an IP6 Zone net string to a unix int
Juan Batiz-Benet's avatar
net pkg  
Juan Batiz-Benet committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
// returns 0 if zone is ""
func IP6ZoneToInt(zone string) int {
	if zone == "" {
		return 0
	}
	if ifi, err := net.InterfaceByName(zone); err == nil {
		return ifi.Index
	}
	n, _, _ := dtoi(zone, 0)
	return n
}

// from: go/src/pkg/net/parse.go

// Convert i to decimal string.
func itod(i uint) string {
	if i == 0 {
		return "0"
	}

	// Assemble decimal in reverse order.
	var b [32]byte
	bp := len(b)
	for ; i > 0; i /= 10 {
		bp--
		b[bp] = byte(i%10) + '0'
	}

	return string(b[bp:])
}

// Bigger than we need, not too big to worry about overflow
const big = 0xFFFFFF

// Decimal to integer starting at &s[i0].
// Returns number, new offset, success.
func dtoi(s string, i0 int) (n int, i int, ok bool) {
	n = 0
	for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
		n = n*10 + int(s[i]-'0')
		if n >= big {
			return 0, i, false
		}
	}
	if i == i0 {
		return 0, i, false
	}
	return n, i, true
}