Esempio n. 1
0
func sockaddrToAny(sa syscall.Sockaddr) (*syscall.RawSockaddrAny, Socklen, error) {
	if sa == nil {
		return nil, 0, syscall.EINVAL
	}

	switch sa := sa.(type) {
	case *syscall.SockaddrInet4:
		if sa.Port < 0 || sa.Port > 0xFFFF {
			return nil, 0, syscall.EINVAL
		}
		var raw syscall.RawSockaddrInet4
		raw.Len = syscall.SizeofSockaddrInet4
		raw.Family = syscall.AF_INET
		p := (*[2]byte)(unsafe.Pointer(&raw.Port))
		p[0] = byte(sa.Port >> 8)
		p[1] = byte(sa.Port)
		for i := 0; i < len(sa.Addr); i++ {
			raw.Addr[i] = sa.Addr[i]
		}
		return (*syscall.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil

	case *syscall.SockaddrInet6:
		if sa.Port < 0 || sa.Port > 0xFFFF {
			return nil, 0, syscall.EINVAL
		}
		var raw syscall.RawSockaddrInet6
		raw.Len = syscall.SizeofSockaddrInet6
		raw.Family = syscall.AF_INET6
		p := (*[2]byte)(unsafe.Pointer(&raw.Port))
		p[0] = byte(sa.Port >> 8)
		p[1] = byte(sa.Port)
		raw.Scope_id = sa.ZoneId
		for i := 0; i < len(sa.Addr); i++ {
			raw.Addr[i] = sa.Addr[i]
		}
		return (*syscall.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil

	case *syscall.SockaddrUnix:
		name := sa.Name
		n := len(name)
		var raw syscall.RawSockaddrUnix
		if n >= len(raw.Path) || n == 0 {
			return nil, 0, syscall.EINVAL
		}
		raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
		raw.Family = syscall.AF_UNIX
		for i := 0; i < n; i++ {
			raw.Path[i] = int8(name[i])
		}
		return (*syscall.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil

	case *syscall.SockaddrDatalink:
		if sa.Index == 0 {
			return nil, 0, syscall.EINVAL
		}
		var raw syscall.RawSockaddrDatalink
		raw.Len = sa.Len
		raw.Family = syscall.AF_LINK
		raw.Index = sa.Index
		raw.Type = sa.Type
		raw.Nlen = sa.Nlen
		raw.Alen = sa.Alen
		raw.Slen = sa.Slen
		for i := 0; i < len(raw.Data); i++ {
			raw.Data[i] = sa.Data[i]
		}
		return (*syscall.RawSockaddrAny)(unsafe.Pointer(&raw)), syscall.SizeofSockaddrDatalink, nil
	}
	return nil, 0, syscall.EAFNOSUPPORT
}