Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / syscalls / socket_linux.go
blobbc196a2ffc6d83925170b4180a415a61fa81c945
1 // socket_linux.go -- Socket handling specific to Linux.
3 // Copyright 2010 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 // Low-level socket interface.
8 // Only for implementing net package.
10 // DO NOT USE DIRECTLY.
12 package syscall
14 import "unsafe"
16 type RawSockaddrInet4 struct {
17 Family uint16;
18 Port uint16;
19 Addr [4]byte /* in_addr */;
20 Zero [8]uint8;
23 type RawSockaddrInet6 struct {
24 Family uint16;
25 Port uint16;
26 Flowinfo uint32;
27 Addr [16]byte /* in6_addr */;
28 Scope_id uint32;
31 type RawSockaddrUnix struct {
32 Family uint16;
33 Path [108]int8;
36 type RawSockaddr struct {
37 Family uint16;
38 Data [14]int8;
41 func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
42 if sa.Port < 0 || sa.Port > 0xFFFF {
43 return nil, 0, EINVAL;
45 sa.raw.Family = AF_INET;
46 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
47 p[0] = byte(sa.Port>>8);
48 p[1] = byte(sa.Port);
49 for i := 0; i < len(sa.Addr); i++ {
50 sa.raw.Addr[i] = sa.Addr[i];
52 return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
55 func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
56 if sa.Port < 0 || sa.Port > 0xFFFF {
57 return nil, 0, EINVAL;
59 sa.raw.Family = AF_INET6;
60 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
61 p[0] = byte(sa.Port>>8);
62 p[1] = byte(sa.Port);
63 for i := 0; i < len(sa.Addr); i++ {
64 sa.raw.Addr[i] = sa.Addr[i];
66 return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
69 func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
70 name := sa.Name;
71 n := len(name);
72 if n >= len(sa.raw.Path) || n == 0 {
73 return nil, 0, EINVAL;
75 sa.raw.Family = AF_UNIX;
76 for i := 0; i < n; i++ {
77 sa.raw.Path[i] = int8(name[i]);
79 if sa.raw.Path[0] == '@' {
80 sa.raw.Path[0] = 0;
83 // length is family, name, NUL.
84 return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0;
87 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
88 switch rsa.Addr.Family {
89 case AF_UNIX:
90 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
91 sa := new(SockaddrUnix);
92 if pp.Path[0] == 0 {
93 // "Abstract" Unix domain socket.
94 // Rewrite leading NUL as @ for textual display.
95 // (This is the standard convention.)
96 // Not friendly to overwrite in place,
97 // but the callers below don't care.
98 pp.Path[0] = '@';
101 // Assume path ends at NUL.
102 // This is not technically the Linux semantics for
103 // abstract Unix domain sockets--they are supposed
104 // to be uninterpreted fixed-size binary blobs--but
105 // everyone uses this convention.
106 n := 0;
107 for n < len(pp.Path) - 3 && pp.Path[n] != 0 {
108 n++;
110 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
111 sa.Name = string(bytes[0:n]);
112 return sa, 0;
114 case AF_INET:
115 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
116 sa := new(SockaddrInet4);
117 p := (*[2]byte)(unsafe.Pointer(&pp.Port));
118 sa.Port = int(p[0])<<8 + int(p[1]);
119 for i := 0; i < len(sa.Addr); i++ {
120 sa.Addr[i] = pp.Addr[i];
122 return sa, 0;
124 case AF_INET6:
125 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
126 sa := new(SockaddrInet6);
127 p := (*[2]byte)(unsafe.Pointer(&pp.Port));
128 sa.Port = int(p[0])<<8 + int(p[1]);
129 for i := 0; i < len(sa.Addr); i++ {
130 sa.Addr[i] = pp.Addr[i];
132 return sa, 0;
134 return nil, EAFNOSUPPORT;
137 // BindToDevice binds the socket associated with fd to device.
138 func BindToDevice(fd int, device string) (errno int) {
139 return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)