1// Copyright 2019 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//go:build linux
6// +build linux
7
8package unix
9
10import (
11	"reflect"
12	"strings"
13	"testing"
14	"unsafe"
15)
16
17func makeProto(proto int) *int {
18	return &proto
19}
20
21func Test_anyToSockaddr(t *testing.T) {
22	tests := []struct {
23		name  string
24		rsa   *RawSockaddrAny
25		sa    Sockaddr
26		err   error
27		proto *int
28	}{
29		{
30			name: "AF_TIPC bad addrtype",
31			rsa: &RawSockaddrAny{
32				Addr: RawSockaddr{
33					Family: AF_TIPC,
34				},
35			},
36			err: EINVAL,
37		},
38		{
39			name: "AF_TIPC NameSeq",
40			rsa: sockaddrTIPCToAny(RawSockaddrTIPC{
41				Family:   AF_TIPC,
42				Addrtype: TIPC_SERVICE_RANGE,
43				Scope:    1,
44				Addr: (&TIPCServiceRange{
45					Type:  1,
46					Lower: 2,
47					Upper: 3,
48				}).tipcAddr(),
49			}),
50			sa: &SockaddrTIPC{
51				Scope: 1,
52				Addr: &TIPCServiceRange{
53					Type:  1,
54					Lower: 2,
55					Upper: 3,
56				},
57			},
58		},
59		{
60			name: "AF_TIPC Name",
61			rsa: sockaddrTIPCToAny(RawSockaddrTIPC{
62				Family:   AF_TIPC,
63				Addrtype: TIPC_SERVICE_ADDR,
64				Scope:    2,
65				Addr: (&TIPCServiceName{
66					Type:     1,
67					Instance: 2,
68					Domain:   3,
69				}).tipcAddr(),
70			}),
71			sa: &SockaddrTIPC{
72				Scope: 2,
73				Addr: &TIPCServiceName{
74					Type:     1,
75					Instance: 2,
76					Domain:   3,
77				},
78			},
79		},
80		{
81			name: "AF_TIPC ID",
82			rsa: sockaddrTIPCToAny(RawSockaddrTIPC{
83				Family:   AF_TIPC,
84				Addrtype: TIPC_SOCKET_ADDR,
85				Scope:    3,
86				Addr: (&TIPCSocketAddr{
87					Ref:  1,
88					Node: 2,
89				}).tipcAddr(),
90			}),
91			sa: &SockaddrTIPC{
92				Scope: 3,
93				Addr: &TIPCSocketAddr{
94					Ref:  1,
95					Node: 2,
96				},
97			},
98		},
99		{
100			name: "AF_INET IPPROTO_L2TP",
101			rsa: sockaddrL2TPIPToAny(RawSockaddrL2TPIP{
102				Family:  AF_INET,
103				Addr:    [4]byte{0xef, 0x10, 0x5b, 0xa2},
104				Conn_id: 0x1234abcd,
105			}),
106			sa: &SockaddrL2TPIP{
107				Addr:   [4]byte{0xef, 0x10, 0x5b, 0xa2},
108				ConnId: 0x1234abcd,
109			},
110			proto: makeProto(IPPROTO_L2TP),
111		},
112		{
113			name: "AF_INET6 IPPROTO_L2TP",
114			rsa: sockaddrL2TPIP6ToAny(RawSockaddrL2TPIP6{
115				Family:   AF_INET6,
116				Flowinfo: 42,
117				Addr: [16]byte{
118					0x20, 0x01, 0x0d, 0xb8,
119					0x85, 0xa3, 0x00, 0x00,
120					0x00, 0x00, 0x8a, 0x2e,
121					0x03, 0x70, 0x73, 0x34,
122				},
123				Scope_id: 90210,
124				Conn_id:  0x1234abcd,
125			}),
126			sa: &SockaddrL2TPIP6{
127				Addr: [16]byte{
128					0x20, 0x01, 0x0d, 0xb8,
129					0x85, 0xa3, 0x00, 0x00,
130					0x00, 0x00, 0x8a, 0x2e,
131					0x03, 0x70, 0x73, 0x34,
132				},
133				ZoneId: 90210,
134				ConnId: 0x1234abcd,
135			},
136			proto: makeProto(IPPROTO_L2TP),
137		},
138		{
139			name: "AF_UNIX unnamed/abstract",
140			rsa: sockaddrUnixToAny(RawSockaddrUnix{
141				Family: AF_UNIX,
142			}),
143			sa: &SockaddrUnix{
144				Name: "@",
145			},
146		},
147		{
148			name: "AF_UNIX named",
149			rsa: sockaddrUnixToAny(RawSockaddrUnix{
150				Family: AF_UNIX,
151				Path:   [108]int8{'g', 'o', 'p', 'h', 'e', 'r'},
152			}),
153			sa: &SockaddrUnix{
154				Name: "gopher",
155			},
156		},
157		{
158			name: "AF_IUCV",
159			rsa: sockaddrIUCVToAny(RawSockaddrIUCV{
160				Family:  AF_IUCV,
161				User_id: [8]int8{'*', 'M', 'S', 'G', ' ', ' ', ' ', ' '},
162				Name:    [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
163			}),
164			sa: &SockaddrIUCV{
165				UserID: "*MSG    ",
166				Name:   "        ",
167			},
168		},
169		{
170			name: "AF_CAN CAN_RAW",
171			rsa: sockaddrCANToAny(RawSockaddrCAN{
172				Family:  AF_CAN,
173				Ifindex: 12345678,
174				Addr: [16]byte{
175					0xAA, 0xAA, 0xAA, 0xAA,
176					0xBB, 0xBB, 0xBB, 0xBB,
177					0x0, 0x0, 0x0, 0x0,
178					0x0, 0x0, 0x0, 0x0,
179				},
180			}),
181			sa: &SockaddrCAN{
182				Ifindex: 12345678,
183				RxID:    0xAAAAAAAA,
184				TxID:    0xBBBBBBBB,
185			},
186			proto: makeProto(CAN_RAW),
187		},
188		{
189			name: "AF_CAN CAN_J1939",
190			rsa: sockaddrCANToAny(RawSockaddrCAN{
191				Family:  AF_CAN,
192				Ifindex: 12345678,
193				Addr: [16]byte{
194					0xAA, 0xAA, 0xAA, 0xAA,
195					0xAA, 0xAA, 0xAA, 0xAA,
196					0xBB, 0xBB, 0xBB, 0xBB,
197					0xCC, 0x00, 0x00, 0x00,
198				},
199			}),
200			sa: &SockaddrCANJ1939{
201				Ifindex: 12345678,
202				Name:    0xAAAAAAAAAAAAAAAA,
203				PGN:     0xBBBBBBBB,
204				Addr:    0xCC,
205			},
206			proto: makeProto(CAN_J1939),
207		},
208		{
209			name: "AF_NFC RAW",
210			rsa: sockaddrNFCToAny(RawSockaddrNFC{
211				Sa_family:    AF_NFC,
212				Dev_idx:      10,
213				Target_idx:   20,
214				Nfc_protocol: 30,
215			}),
216			sa: &SockaddrNFC{
217				DeviceIdx:   10,
218				TargetIdx:   20,
219				NFCProtocol: 30,
220			},
221			proto: makeProto(NFC_SOCKPROTO_RAW),
222		},
223		{
224			name: "AF_NFC LLCP",
225			rsa: sockaddrNFCLLCPToAny(RawSockaddrNFCLLCP{
226				Sa_family:        AF_NFC,
227				Dev_idx:          10,
228				Target_idx:       20,
229				Nfc_protocol:     30,
230				Dsap:             40,
231				Ssap:             50,
232				Service_name:     [63]uint8{'t', 'e', 's', 't'},
233				Service_name_len: 4,
234			}),
235			sa: &SockaddrNFCLLCP{
236				DeviceIdx:      10,
237				TargetIdx:      20,
238				NFCProtocol:    30,
239				DestinationSAP: 40,
240				SourceSAP:      50,
241				ServiceName:    "test",
242			},
243			proto: makeProto(NFC_SOCKPROTO_LLCP),
244		},
245		{
246			name: "AF_NFC unknown",
247			rsa: sockaddrNFCToAny(RawSockaddrNFC{
248				Sa_family:    AF_NFC,
249				Dev_idx:      10,
250				Target_idx:   20,
251				Nfc_protocol: 30,
252			}),
253			err:   EINVAL,
254			proto: makeProto(^0),
255		},
256		{
257			name: "AF_MAX EAFNOSUPPORT",
258			rsa: &RawSockaddrAny{
259				Addr: RawSockaddr{
260					Family: AF_MAX,
261				},
262			},
263			err: EAFNOSUPPORT,
264		},
265		// TODO: expand to support other families.
266	}
267
268	realSocketProtocol := socketProtocol
269
270	for _, tt := range tests {
271		t.Run(tt.name, func(t *testing.T) {
272			fd := int(0)
273			if tt.proto != nil {
274				socketProtocol = func(fd int) (int, error) { return *tt.proto, nil }
275			} else {
276				socketProtocol = realSocketProtocol
277			}
278			sa, err := anyToSockaddr(fd, tt.rsa)
279			if err != tt.err {
280				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
281			}
282
283			if !reflect.DeepEqual(sa, tt.sa) {
284				t.Fatalf("unexpected Sockaddr:\n got: %#v\nwant: %#v", sa, tt.sa)
285			}
286		})
287	}
288}
289
290func TestSockaddrTIPC_sockaddr(t *testing.T) {
291	tests := []struct {
292		name string
293		sa   *SockaddrTIPC
294		raw  *RawSockaddrTIPC
295		err  error
296	}{
297		{
298			name: "no fields set",
299			sa:   &SockaddrTIPC{},
300			err:  EINVAL,
301		},
302		{
303			name: "ID",
304			sa: &SockaddrTIPC{
305				Scope: 1,
306				Addr: &TIPCSocketAddr{
307					Ref:  1,
308					Node: 2,
309				},
310			},
311			raw: &RawSockaddrTIPC{
312				Family:   AF_TIPC,
313				Addrtype: TIPC_SOCKET_ADDR,
314				Scope:    1,
315				Addr: (&TIPCSocketAddr{
316					Ref:  1,
317					Node: 2,
318				}).tipcAddr(),
319			},
320		},
321		{
322			name: "NameSeq",
323			sa: &SockaddrTIPC{
324				Scope: 2,
325				Addr: &TIPCServiceRange{
326					Type:  1,
327					Lower: 2,
328					Upper: 3,
329				},
330			},
331			raw: &RawSockaddrTIPC{
332				Family:   AF_TIPC,
333				Addrtype: TIPC_SERVICE_RANGE,
334				Scope:    2,
335				Addr: (&TIPCServiceRange{
336					Type:  1,
337					Lower: 2,
338					Upper: 3,
339				}).tipcAddr(),
340			},
341		},
342		{
343			name: "Name",
344			sa: &SockaddrTIPC{
345				Scope: 3,
346				Addr: &TIPCServiceName{
347					Type:     1,
348					Instance: 2,
349					Domain:   3,
350				},
351			},
352			raw: &RawSockaddrTIPC{
353				Family:   AF_TIPC,
354				Addrtype: TIPC_SERVICE_ADDR,
355				Scope:    3,
356				Addr: (&TIPCServiceName{
357					Type:     1,
358					Instance: 2,
359					Domain:   3,
360				}).tipcAddr(),
361			},
362		},
363	}
364
365	for _, tt := range tests {
366		t.Run(tt.name, func(t *testing.T) {
367			out, l, err := tt.sa.sockaddr()
368			if err != tt.err {
369				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
370			}
371
372			// Must be 0 on error or a fixed size otherwise.
373			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrTIPC) {
374				t.Fatalf("unexpected Socklen: %d", l)
375			}
376			if out == nil {
377				// No pointer to cast, return early.
378				return
379			}
380
381			raw := (*RawSockaddrTIPC)(out)
382			if !reflect.DeepEqual(raw, tt.raw) {
383				t.Fatalf("unexpected RawSockaddrTIPC:\n got: %#v\nwant: %#v", raw, tt.raw)
384			}
385		})
386	}
387}
388
389func TestSockaddrL2TPIP_sockaddr(t *testing.T) {
390	tests := []struct {
391		name string
392		sa   *SockaddrL2TPIP
393		raw  *RawSockaddrL2TPIP
394		err  error
395	}{
396		{
397			name: "L2TPIP",
398			sa: &SockaddrL2TPIP{
399				Addr:   [4]byte{0xef, 0x10, 0x5b, 0xa2},
400				ConnId: 0x1234abcd,
401			},
402			raw: &RawSockaddrL2TPIP{
403				Family:  AF_INET,
404				Addr:    [4]byte{0xef, 0x10, 0x5b, 0xa2},
405				Conn_id: 0x1234abcd,
406			},
407		},
408	}
409
410	for _, tt := range tests {
411		t.Run(tt.name, func(t *testing.T) {
412			out, l, err := tt.sa.sockaddr()
413			if err != tt.err {
414				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
415			}
416
417			// Must be 0 on error or a fixed size otherwise.
418			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrL2TPIP) {
419				t.Fatalf("unexpected Socklen: %d", l)
420			}
421
422			if out != nil {
423				raw := (*RawSockaddrL2TPIP)(out)
424				if !reflect.DeepEqual(raw, tt.raw) {
425					t.Fatalf("unexpected RawSockaddrL2TPIP:\n got: %#v\nwant: %#v", raw, tt.raw)
426				}
427			}
428		})
429	}
430}
431
432func TestSockaddrL2TPIP6_sockaddr(t *testing.T) {
433	tests := []struct {
434		name string
435		sa   *SockaddrL2TPIP6
436		raw  *RawSockaddrL2TPIP6
437		err  error
438	}{
439		{
440			name: "L2TPIP6",
441			sa: &SockaddrL2TPIP6{
442				Addr: [16]byte{
443					0x20, 0x01, 0x0d, 0xb8,
444					0x85, 0xa3, 0x00, 0x00,
445					0x00, 0x00, 0x8a, 0x2e,
446					0x03, 0x70, 0x73, 0x34,
447				},
448				ZoneId: 90210,
449				ConnId: 0x1234abcd,
450			},
451			raw: &RawSockaddrL2TPIP6{
452				Family: AF_INET6,
453				Addr: [16]byte{
454					0x20, 0x01, 0x0d, 0xb8,
455					0x85, 0xa3, 0x00, 0x00,
456					0x00, 0x00, 0x8a, 0x2e,
457					0x03, 0x70, 0x73, 0x34,
458				},
459				Scope_id: 90210,
460				Conn_id:  0x1234abcd,
461			},
462		},
463	}
464
465	for _, tt := range tests {
466		t.Run(tt.name, func(t *testing.T) {
467			out, l, err := tt.sa.sockaddr()
468			if err != tt.err {
469				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
470			}
471
472			// Must be 0 on error or a fixed size otherwise.
473			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrL2TPIP6) {
474				t.Fatalf("unexpected Socklen: %d", l)
475			}
476
477			if out != nil {
478				raw := (*RawSockaddrL2TPIP6)(out)
479				if !reflect.DeepEqual(raw, tt.raw) {
480					t.Fatalf("unexpected RawSockaddrL2TPIP6:\n got: %#v\nwant: %#v", raw, tt.raw)
481				}
482			}
483		})
484	}
485}
486
487func TestSockaddrUnix_sockaddr(t *testing.T) {
488	tests := []struct {
489		name string
490		sa   *SockaddrUnix
491		raw  *RawSockaddrUnix
492		slen _Socklen
493		err  error
494	}{
495		{
496			name: "unnamed",
497			sa:   &SockaddrUnix{},
498			raw: &RawSockaddrUnix{
499				Family: AF_UNIX,
500			},
501			slen: 2, // family (uint16)
502		},
503		{
504			name: "abstract",
505			sa: &SockaddrUnix{
506				Name: "@",
507			},
508			raw: &RawSockaddrUnix{
509				Family: AF_UNIX,
510			},
511			slen: 3, // family (uint16) + NULL
512		},
513		{
514			name: "named",
515			sa: &SockaddrUnix{
516				Name: "gopher",
517			},
518			raw: &RawSockaddrUnix{
519				Family: AF_UNIX,
520				Path:   [108]int8{'g', 'o', 'p', 'h', 'e', 'r'},
521			},
522			slen: _Socklen(3 + len("gopher")), // family (uint16) + len(gopher)
523		},
524		{
525			name: "named too long",
526			sa: &SockaddrUnix{
527				Name: strings.Repeat("A", 108),
528			},
529			err: EINVAL,
530		},
531	}
532
533	for _, tt := range tests {
534		t.Run(tt.name, func(t *testing.T) {
535			out, l, err := tt.sa.sockaddr()
536			if err != tt.err {
537				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
538			}
539
540			if l != tt.slen {
541				t.Fatalf("unexpected Socklen: %d, want %d", l, tt.slen)
542			}
543			if out == nil {
544				// No pointer to cast, return early.
545				return
546			}
547
548			raw := (*RawSockaddrUnix)(out)
549			if !reflect.DeepEqual(raw, tt.raw) {
550				t.Fatalf("unexpected RawSockaddrUnix:\n got: %#v\nwant: %#v", raw, tt.raw)
551			}
552		})
553	}
554}
555
556func TestSockaddrIUCV_sockaddr(t *testing.T) {
557	tests := []struct {
558		name string
559		sa   *SockaddrIUCV
560		raw  *RawSockaddrIUCV
561		err  error
562	}{
563		{
564			name: "no fields set",
565			sa:   &SockaddrIUCV{},
566			raw: &RawSockaddrIUCV{
567				Family:  AF_IUCV,
568				Nodeid:  [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
569				User_id: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
570				Name:    [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
571			},
572		},
573		{
574			name: "both fields set",
575			sa: &SockaddrIUCV{
576				UserID: "USERID",
577				Name:   "NAME",
578			},
579			raw: &RawSockaddrIUCV{
580				Family:  AF_IUCV,
581				Nodeid:  [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
582				User_id: [8]int8{'U', 'S', 'E', 'R', 'I', 'D', ' ', ' '},
583				Name:    [8]int8{'N', 'A', 'M', 'E', ' ', ' ', ' ', ' '},
584			},
585		},
586		{
587			name: "too long userid",
588			sa: &SockaddrIUCV{
589				UserID: "123456789",
590			},
591			err: EINVAL,
592		},
593		{
594			name: "too long name",
595			sa: &SockaddrIUCV{
596				Name: "123456789",
597			},
598			err: EINVAL,
599		},
600	}
601
602	for _, tt := range tests {
603		t.Run(tt.name, func(t *testing.T) {
604			out, l, err := tt.sa.sockaddr()
605			if err != tt.err {
606				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
607			}
608
609			// Must be 0 on error or a fixed size otherwise.
610			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrIUCV) {
611				t.Fatalf("unexpected Socklen: %d", l)
612			}
613			if out == nil {
614				// No pointer to cast, return early.
615				return
616			}
617
618			raw := (*RawSockaddrIUCV)(out)
619			if !reflect.DeepEqual(raw, tt.raw) {
620				t.Fatalf("unexpected RawSockaddrIUCV:\n got: %#v\nwant: %#v", raw, tt.raw)
621			}
622		})
623	}
624}
625
626func TestSockaddrCAN_sockaddr(t *testing.T) {
627	tests := []struct {
628		name string
629		sa   *SockaddrCAN
630		raw  *RawSockaddrCAN
631		err  error
632	}{
633		{
634			name: "with ids",
635			sa: &SockaddrCAN{
636				Ifindex: 12345678,
637				RxID:    0xAAAAAAAA,
638				TxID:    0xBBBBBBBB,
639			},
640			raw: &RawSockaddrCAN{
641				Family:  AF_CAN,
642				Ifindex: 12345678,
643				Addr: [16]byte{
644					0xAA, 0xAA, 0xAA, 0xAA,
645					0xBB, 0xBB, 0xBB, 0xBB,
646					0x0, 0x0, 0x0, 0x0,
647					0x0, 0x0, 0x0, 0x0,
648				},
649			},
650		},
651		{
652			name: "negative ifindex",
653			sa: &SockaddrCAN{
654				Ifindex: -1,
655			},
656			err: EINVAL,
657		},
658	}
659
660	for _, tt := range tests {
661		t.Run(tt.name, func(t *testing.T) {
662			out, l, err := tt.sa.sockaddr()
663			if err != tt.err {
664				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
665			}
666
667			// Must be 0 on error or a fixed size otherwise.
668			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrCAN) {
669				t.Fatalf("unexpected Socklen: %d", l)
670			}
671
672			if out != nil {
673				raw := (*RawSockaddrCAN)(out)
674				if !reflect.DeepEqual(raw, tt.raw) {
675					t.Fatalf("unexpected RawSockaddrCAN:\n got: %#v\nwant: %#v", raw, tt.raw)
676				}
677			}
678		})
679	}
680}
681
682func TestSockaddrNFC_sockaddr(t *testing.T) {
683	tests := []struct {
684		name string
685		sa   *SockaddrNFC
686		raw  *RawSockaddrNFC
687		err  error
688	}{
689		{
690			name: "NFC RAW",
691			sa: &SockaddrNFC{
692				DeviceIdx:   12345678,
693				TargetIdx:   87654321,
694				NFCProtocol: 0xBBBBBBBB,
695			},
696			raw: &RawSockaddrNFC{
697				Sa_family:    AF_NFC,
698				Dev_idx:      12345678,
699				Target_idx:   87654321,
700				Nfc_protocol: 0xBBBBBBBB,
701			},
702		},
703	}
704
705	for _, tt := range tests {
706		t.Run(tt.name, func(t *testing.T) {
707			out, l, err := tt.sa.sockaddr()
708			if err != tt.err {
709				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
710			}
711
712			// Must be 0 on error or a fixed size otherwise.
713			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrNFC) {
714				t.Fatalf("unexpected Socklen: %d", l)
715			}
716
717			if out != nil {
718				raw := (*RawSockaddrNFC)(out)
719				if !reflect.DeepEqual(raw, tt.raw) {
720					t.Fatalf("unexpected RawSockaddrNFC:\n got: %#v\nwant: %#v", raw, tt.raw)
721				}
722			}
723		})
724	}
725}
726
727func TestSockaddrNFCLLCP_sockaddr(t *testing.T) {
728	tests := []struct {
729		name string
730		sa   *SockaddrNFCLLCP
731		raw  *RawSockaddrNFCLLCP
732		err  error
733	}{
734		{
735			name: "valid",
736			sa: &SockaddrNFCLLCP{
737				DeviceIdx:      12345678,
738				TargetIdx:      87654321,
739				NFCProtocol:    0xBBBBBBBB,
740				DestinationSAP: 55,
741				SourceSAP:      56,
742				ServiceName:    "test service",
743			},
744			raw: &RawSockaddrNFCLLCP{
745				Sa_family:        AF_NFC,
746				Dev_idx:          12345678,
747				Target_idx:       87654321,
748				Nfc_protocol:     0xBBBBBBBB,
749				Dsap:             55,
750				Ssap:             56,
751				Service_name:     [63]uint8{'t', 'e', 's', 't', ' ', 's', 'e', 'r', 'v', 'i', 'c', 'e'},
752				Service_name_len: 12,
753			},
754		},
755		{
756			name: "too long service name",
757			sa: &SockaddrNFCLLCP{
758				DeviceIdx:      12345678,
759				TargetIdx:      87654321,
760				NFCProtocol:    0xBBBBBBBB,
761				DestinationSAP: 55,
762				SourceSAP:      56,
763				ServiceName:    "too long too long too long too long too long too long too long too long too long",
764			},
765			err: EINVAL,
766		},
767	}
768
769	for _, tt := range tests {
770		t.Run(tt.name, func(t *testing.T) {
771			out, l, err := tt.sa.sockaddr()
772			if err != tt.err {
773				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
774			}
775
776			// Must be 0 on error or a fixed size otherwise.
777			if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrNFCLLCP) {
778				t.Fatalf("unexpected Socklen: %d", l)
779			}
780
781			if out != nil {
782				raw := (*RawSockaddrNFCLLCP)(out)
783				if !reflect.DeepEqual(raw, tt.raw) {
784					t.Fatalf("unexpected RawSockaddrNFCLLCP:\n got: %#v\nwant: %#v", raw, tt.raw)
785				}
786			}
787		})
788	}
789}
790
791// These helpers explicitly copy the contents of in into out to produce
792// the correct sockaddr structure, without relying on unsafe casting to
793// a type of a larger size.
794func sockaddrTIPCToAny(in RawSockaddrTIPC) *RawSockaddrAny {
795	var out RawSockaddrAny
796	copy(
797		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
798		(*(*[SizeofSockaddrTIPC]byte)(unsafe.Pointer(&in)))[:],
799	)
800	return &out
801}
802
803func sockaddrL2TPIPToAny(in RawSockaddrL2TPIP) *RawSockaddrAny {
804	var out RawSockaddrAny
805	copy(
806		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
807		(*(*[SizeofSockaddrL2TPIP]byte)(unsafe.Pointer(&in)))[:],
808	)
809	return &out
810}
811
812func sockaddrL2TPIP6ToAny(in RawSockaddrL2TPIP6) *RawSockaddrAny {
813	var out RawSockaddrAny
814	copy(
815		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
816		(*(*[SizeofSockaddrL2TPIP6]byte)(unsafe.Pointer(&in)))[:],
817	)
818	return &out
819}
820
821func sockaddrUnixToAny(in RawSockaddrUnix) *RawSockaddrAny {
822	var out RawSockaddrAny
823	copy(
824		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
825		(*(*[SizeofSockaddrUnix]byte)(unsafe.Pointer(&in)))[:],
826	)
827	return &out
828}
829
830func sockaddrIUCVToAny(in RawSockaddrIUCV) *RawSockaddrAny {
831	var out RawSockaddrAny
832	copy(
833		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
834		(*(*[SizeofSockaddrUnix]byte)(unsafe.Pointer(&in)))[:],
835	)
836	return &out
837}
838
839func sockaddrCANToAny(in RawSockaddrCAN) *RawSockaddrAny {
840	var out RawSockaddrAny
841	copy(
842		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
843		(*(*[SizeofSockaddrCAN]byte)(unsafe.Pointer(&in)))[:],
844	)
845	return &out
846}
847
848func sockaddrNFCToAny(in RawSockaddrNFC) *RawSockaddrAny {
849	var out RawSockaddrAny
850	copy(
851		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
852		(*(*[SizeofSockaddrNFC]byte)(unsafe.Pointer(&in)))[:],
853	)
854	return &out
855}
856
857func sockaddrNFCLLCPToAny(in RawSockaddrNFCLLCP) *RawSockaddrAny {
858	var out RawSockaddrAny
859	copy(
860		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
861		(*(*[SizeofSockaddrNFCLLCP]byte)(unsafe.Pointer(&in)))[:],
862	)
863	return &out
864}
865