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// +build linux 6 7package unix 8 9import ( 10 "reflect" 11 "strings" 12 "testing" 13 "unsafe" 14) 15 16// as per socket(2) 17type SocketSpec struct { 18 domain int 19 typ int 20 protocol int 21} 22 23func Test_anyToSockaddr(t *testing.T) { 24 tests := []struct { 25 name string 26 rsa *RawSockaddrAny 27 sa Sockaddr 28 err error 29 skt SocketSpec 30 }{ 31 { 32 name: "AF_TIPC bad addrtype", 33 rsa: &RawSockaddrAny{ 34 Addr: RawSockaddr{ 35 Family: AF_TIPC, 36 }, 37 }, 38 err: EINVAL, 39 }, 40 { 41 name: "AF_TIPC NameSeq", 42 rsa: sockaddrTIPCToAny(RawSockaddrTIPC{ 43 Family: AF_TIPC, 44 Addrtype: TIPC_SERVICE_RANGE, 45 Scope: 1, 46 Addr: (&TIPCServiceRange{ 47 Type: 1, 48 Lower: 2, 49 Upper: 3, 50 }).tipcAddr(), 51 }), 52 sa: &SockaddrTIPC{ 53 Scope: 1, 54 Addr: &TIPCServiceRange{ 55 Type: 1, 56 Lower: 2, 57 Upper: 3, 58 }, 59 }, 60 }, 61 { 62 name: "AF_TIPC Name", 63 rsa: sockaddrTIPCToAny(RawSockaddrTIPC{ 64 Family: AF_TIPC, 65 Addrtype: TIPC_SERVICE_ADDR, 66 Scope: 2, 67 Addr: (&TIPCServiceName{ 68 Type: 1, 69 Instance: 2, 70 Domain: 3, 71 }).tipcAddr(), 72 }), 73 sa: &SockaddrTIPC{ 74 Scope: 2, 75 Addr: &TIPCServiceName{ 76 Type: 1, 77 Instance: 2, 78 Domain: 3, 79 }, 80 }, 81 }, 82 { 83 name: "AF_TIPC ID", 84 rsa: sockaddrTIPCToAny(RawSockaddrTIPC{ 85 Family: AF_TIPC, 86 Addrtype: TIPC_SOCKET_ADDR, 87 Scope: 3, 88 Addr: (&TIPCSocketAddr{ 89 Ref: 1, 90 Node: 2, 91 }).tipcAddr(), 92 }), 93 sa: &SockaddrTIPC{ 94 Scope: 3, 95 Addr: &TIPCSocketAddr{ 96 Ref: 1, 97 Node: 2, 98 }, 99 }, 100 }, 101 { 102 name: "AF_INET IPPROTO_L2TP", 103 rsa: sockaddrL2TPIPToAny(RawSockaddrL2TPIP{ 104 Family: AF_INET, 105 Addr: [4]byte{0xef, 0x10, 0x5b, 0xa2}, 106 Conn_id: 0x1234abcd, 107 }), 108 sa: &SockaddrL2TPIP{ 109 Addr: [4]byte{0xef, 0x10, 0x5b, 0xa2}, 110 ConnId: 0x1234abcd, 111 }, 112 skt: SocketSpec{domain: AF_INET, typ: SOCK_DGRAM, protocol: IPPROTO_L2TP}, 113 }, 114 { 115 name: "AF_INET6 IPPROTO_L2TP", 116 rsa: sockaddrL2TPIP6ToAny(RawSockaddrL2TPIP6{ 117 Family: AF_INET6, 118 Flowinfo: 42, 119 Addr: [16]byte{ 120 0x20, 0x01, 0x0d, 0xb8, 121 0x85, 0xa3, 0x00, 0x00, 122 0x00, 0x00, 0x8a, 0x2e, 123 0x03, 0x70, 0x73, 0x34, 124 }, 125 Scope_id: 90210, 126 Conn_id: 0x1234abcd, 127 }), 128 sa: &SockaddrL2TPIP6{ 129 Addr: [16]byte{ 130 0x20, 0x01, 0x0d, 0xb8, 131 0x85, 0xa3, 0x00, 0x00, 132 0x00, 0x00, 0x8a, 0x2e, 133 0x03, 0x70, 0x73, 0x34, 134 }, 135 ZoneId: 90210, 136 ConnId: 0x1234abcd, 137 }, 138 skt: SocketSpec{domain: AF_INET6, typ: SOCK_DGRAM, protocol: IPPROTO_L2TP}, 139 }, 140 { 141 name: "AF_UNIX unnamed/abstract", 142 rsa: sockaddrUnixToAny(RawSockaddrUnix{ 143 Family: AF_UNIX, 144 }), 145 sa: &SockaddrUnix{ 146 Name: "@", 147 }, 148 }, 149 { 150 name: "AF_UNIX named", 151 rsa: sockaddrUnixToAny(RawSockaddrUnix{ 152 Family: AF_UNIX, 153 Path: [108]int8{'g', 'o', 'p', 'h', 'e', 'r'}, 154 }), 155 sa: &SockaddrUnix{ 156 Name: "gopher", 157 }, 158 }, 159 { 160 name: "AF_IUCV", 161 rsa: sockaddrIUCVToAny(RawSockaddrIUCV{ 162 Family: AF_IUCV, 163 User_id: [8]int8{'*', 'M', 'S', 'G', ' ', ' ', ' ', ' '}, 164 Name: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 165 }), 166 sa: &SockaddrIUCV{ 167 UserID: "*MSG ", 168 Name: " ", 169 }, 170 }, 171 { 172 name: "AF_CAN", 173 rsa: sockaddrCANToAny(RawSockaddrCAN{ 174 Family: AF_CAN, 175 Ifindex: 12345678, 176 Addr: [16]byte{ 177 0xAA, 0xAA, 0xAA, 0xAA, 178 0xBB, 0xBB, 0xBB, 0xBB, 179 0x0, 0x0, 0x0, 0x0, 180 0x0, 0x0, 0x0, 0x0, 181 }, 182 }), 183 sa: &SockaddrCAN{ 184 Ifindex: 12345678, 185 RxID: 0xAAAAAAAA, 186 TxID: 0xBBBBBBBB, 187 }, 188 }, 189 { 190 name: "AF_MAX EAFNOSUPPORT", 191 rsa: &RawSockaddrAny{ 192 Addr: RawSockaddr{ 193 Family: AF_MAX, 194 }, 195 }, 196 err: EAFNOSUPPORT, 197 }, 198 // TODO: expand to support other families. 199 } 200 201 for _, tt := range tests { 202 t.Run(tt.name, func(t *testing.T) { 203 fd := int(0) 204 var err error 205 if tt.skt.domain != 0 { 206 fd, err = Socket(tt.skt.domain, tt.skt.typ, tt.skt.protocol) 207 // Some sockaddr types need specific kernel modules running: if these 208 // are not present we'll get EPROTONOSUPPORT back when trying to create 209 // the socket. Skip the test in this situation. 210 if err == EPROTONOSUPPORT { 211 t.Skip("socket family/protocol not supported by kernel") 212 } else if err != nil { 213 t.Fatalf("socket(%v): %v", tt.skt, err) 214 } 215 defer Close(fd) 216 } 217 sa, err := anyToSockaddr(fd, tt.rsa) 218 if err != tt.err { 219 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 220 } 221 222 if !reflect.DeepEqual(sa, tt.sa) { 223 t.Fatalf("unexpected Sockaddr:\n got: %#v\nwant: %#v", sa, tt.sa) 224 } 225 }) 226 } 227} 228 229func TestSockaddrTIPC_sockaddr(t *testing.T) { 230 tests := []struct { 231 name string 232 sa *SockaddrTIPC 233 raw *RawSockaddrTIPC 234 err error 235 }{ 236 { 237 name: "no fields set", 238 sa: &SockaddrTIPC{}, 239 err: EINVAL, 240 }, 241 { 242 name: "ID", 243 sa: &SockaddrTIPC{ 244 Scope: 1, 245 Addr: &TIPCSocketAddr{ 246 Ref: 1, 247 Node: 2, 248 }, 249 }, 250 raw: &RawSockaddrTIPC{ 251 Family: AF_TIPC, 252 Addrtype: TIPC_SOCKET_ADDR, 253 Scope: 1, 254 Addr: (&TIPCSocketAddr{ 255 Ref: 1, 256 Node: 2, 257 }).tipcAddr(), 258 }, 259 }, 260 { 261 name: "NameSeq", 262 sa: &SockaddrTIPC{ 263 Scope: 2, 264 Addr: &TIPCServiceRange{ 265 Type: 1, 266 Lower: 2, 267 Upper: 3, 268 }, 269 }, 270 raw: &RawSockaddrTIPC{ 271 Family: AF_TIPC, 272 Addrtype: TIPC_SERVICE_RANGE, 273 Scope: 2, 274 Addr: (&TIPCServiceRange{ 275 Type: 1, 276 Lower: 2, 277 Upper: 3, 278 }).tipcAddr(), 279 }, 280 }, 281 { 282 name: "Name", 283 sa: &SockaddrTIPC{ 284 Scope: 3, 285 Addr: &TIPCServiceName{ 286 Type: 1, 287 Instance: 2, 288 Domain: 3, 289 }, 290 }, 291 raw: &RawSockaddrTIPC{ 292 Family: AF_TIPC, 293 Addrtype: TIPC_SERVICE_ADDR, 294 Scope: 3, 295 Addr: (&TIPCServiceName{ 296 Type: 1, 297 Instance: 2, 298 Domain: 3, 299 }).tipcAddr(), 300 }, 301 }, 302 } 303 304 for _, tt := range tests { 305 t.Run(tt.name, func(t *testing.T) { 306 out, l, err := tt.sa.sockaddr() 307 if err != tt.err { 308 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 309 } 310 311 // Must be 0 on error or a fixed size otherwise. 312 if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrTIPC) { 313 t.Fatalf("unexpected Socklen: %d", l) 314 } 315 if out == nil { 316 // No pointer to cast, return early. 317 return 318 } 319 320 raw := (*RawSockaddrTIPC)(out) 321 if !reflect.DeepEqual(raw, tt.raw) { 322 t.Fatalf("unexpected RawSockaddrTIPC:\n got: %#v\nwant: %#v", raw, tt.raw) 323 } 324 }) 325 } 326} 327 328func TestSockaddrL2TPIP_sockaddr(t *testing.T) { 329 tests := []struct { 330 name string 331 sa *SockaddrL2TPIP 332 raw *RawSockaddrL2TPIP 333 err error 334 }{ 335 { 336 name: "L2TPIP", 337 sa: &SockaddrL2TPIP{ 338 Addr: [4]byte{0xef, 0x10, 0x5b, 0xa2}, 339 ConnId: 0x1234abcd, 340 }, 341 raw: &RawSockaddrL2TPIP{ 342 Family: AF_INET, 343 Addr: [4]byte{0xef, 0x10, 0x5b, 0xa2}, 344 Conn_id: 0x1234abcd, 345 }, 346 }, 347 } 348 349 for _, tt := range tests { 350 t.Run(tt.name, func(t *testing.T) { 351 out, l, err := tt.sa.sockaddr() 352 if err != tt.err { 353 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 354 } 355 356 // Must be 0 on error or a fixed size otherwise. 357 if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrL2TPIP) { 358 t.Fatalf("unexpected Socklen: %d", l) 359 } 360 361 if out != nil { 362 raw := (*RawSockaddrL2TPIP)(out) 363 if !reflect.DeepEqual(raw, tt.raw) { 364 t.Fatalf("unexpected RawSockaddrL2TPIP:\n got: %#v\nwant: %#v", raw, tt.raw) 365 } 366 } 367 }) 368 } 369} 370 371func TestSockaddrL2TPIP6_sockaddr(t *testing.T) { 372 tests := []struct { 373 name string 374 sa *SockaddrL2TPIP6 375 raw *RawSockaddrL2TPIP6 376 err error 377 }{ 378 { 379 name: "L2TPIP6", 380 sa: &SockaddrL2TPIP6{ 381 Addr: [16]byte{ 382 0x20, 0x01, 0x0d, 0xb8, 383 0x85, 0xa3, 0x00, 0x00, 384 0x00, 0x00, 0x8a, 0x2e, 385 0x03, 0x70, 0x73, 0x34, 386 }, 387 ZoneId: 90210, 388 ConnId: 0x1234abcd, 389 }, 390 raw: &RawSockaddrL2TPIP6{ 391 Family: AF_INET6, 392 Addr: [16]byte{ 393 0x20, 0x01, 0x0d, 0xb8, 394 0x85, 0xa3, 0x00, 0x00, 395 0x00, 0x00, 0x8a, 0x2e, 396 0x03, 0x70, 0x73, 0x34, 397 }, 398 Scope_id: 90210, 399 Conn_id: 0x1234abcd, 400 }, 401 }, 402 } 403 404 for _, tt := range tests { 405 t.Run(tt.name, func(t *testing.T) { 406 out, l, err := tt.sa.sockaddr() 407 if err != tt.err { 408 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 409 } 410 411 // Must be 0 on error or a fixed size otherwise. 412 if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrL2TPIP6) { 413 t.Fatalf("unexpected Socklen: %d", l) 414 } 415 416 if out != nil { 417 raw := (*RawSockaddrL2TPIP6)(out) 418 if !reflect.DeepEqual(raw, tt.raw) { 419 t.Fatalf("unexpected RawSockaddrL2TPIP6:\n got: %#v\nwant: %#v", raw, tt.raw) 420 } 421 } 422 }) 423 } 424} 425 426func TestSockaddrUnix_sockaddr(t *testing.T) { 427 tests := []struct { 428 name string 429 sa *SockaddrUnix 430 raw *RawSockaddrUnix 431 slen _Socklen 432 err error 433 }{ 434 { 435 name: "unnamed", 436 sa: &SockaddrUnix{}, 437 raw: &RawSockaddrUnix{ 438 Family: AF_UNIX, 439 }, 440 slen: 2, // family (uint16) 441 }, 442 { 443 name: "abstract", 444 sa: &SockaddrUnix{ 445 Name: "@", 446 }, 447 raw: &RawSockaddrUnix{ 448 Family: AF_UNIX, 449 }, 450 slen: 3, // family (uint16) + NULL 451 }, 452 { 453 name: "named", 454 sa: &SockaddrUnix{ 455 Name: "gopher", 456 }, 457 raw: &RawSockaddrUnix{ 458 Family: AF_UNIX, 459 Path: [108]int8{'g', 'o', 'p', 'h', 'e', 'r'}, 460 }, 461 slen: _Socklen(3 + len("gopher")), // family (uint16) + len(gopher) 462 }, 463 { 464 name: "named too long", 465 sa: &SockaddrUnix{ 466 Name: strings.Repeat("A", 108), 467 }, 468 err: EINVAL, 469 }, 470 } 471 472 for _, tt := range tests { 473 t.Run(tt.name, func(t *testing.T) { 474 out, l, err := tt.sa.sockaddr() 475 if err != tt.err { 476 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 477 } 478 479 if l != tt.slen { 480 t.Fatalf("unexpected Socklen: %d, want %d", l, tt.slen) 481 } 482 if out == nil { 483 // No pointer to cast, return early. 484 return 485 } 486 487 raw := (*RawSockaddrUnix)(out) 488 if !reflect.DeepEqual(raw, tt.raw) { 489 t.Fatalf("unexpected RawSockaddrUnix:\n got: %#v\nwant: %#v", raw, tt.raw) 490 } 491 }) 492 } 493} 494 495func TestSockaddrIUCV_sockaddr(t *testing.T) { 496 tests := []struct { 497 name string 498 sa *SockaddrIUCV 499 raw *RawSockaddrIUCV 500 err error 501 }{ 502 { 503 name: "no fields set", 504 sa: &SockaddrIUCV{}, 505 raw: &RawSockaddrIUCV{ 506 Family: AF_IUCV, 507 Nodeid: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 508 User_id: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 509 Name: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 510 }, 511 }, 512 { 513 name: "both fields set", 514 sa: &SockaddrIUCV{ 515 UserID: "USERID", 516 Name: "NAME", 517 }, 518 raw: &RawSockaddrIUCV{ 519 Family: AF_IUCV, 520 Nodeid: [8]int8{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}, 521 User_id: [8]int8{'U', 'S', 'E', 'R', 'I', 'D', ' ', ' '}, 522 Name: [8]int8{'N', 'A', 'M', 'E', ' ', ' ', ' ', ' '}, 523 }, 524 }, 525 { 526 name: "too long userid", 527 sa: &SockaddrIUCV{ 528 UserID: "123456789", 529 }, 530 err: EINVAL, 531 }, 532 { 533 name: "too long name", 534 sa: &SockaddrIUCV{ 535 Name: "123456789", 536 }, 537 err: EINVAL, 538 }, 539 } 540 541 for _, tt := range tests { 542 t.Run(tt.name, func(t *testing.T) { 543 out, l, err := tt.sa.sockaddr() 544 if err != tt.err { 545 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 546 } 547 548 // Must be 0 on error or a fixed size otherwise. 549 if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrIUCV) { 550 t.Fatalf("unexpected Socklen: %d", l) 551 } 552 if out == nil { 553 // No pointer to cast, return early. 554 return 555 } 556 557 raw := (*RawSockaddrIUCV)(out) 558 if !reflect.DeepEqual(raw, tt.raw) { 559 t.Fatalf("unexpected RawSockaddrIUCV:\n got: %#v\nwant: %#v", raw, tt.raw) 560 } 561 }) 562 } 563} 564 565func TestSockaddrCAN_sockaddr(t *testing.T) { 566 tests := []struct { 567 name string 568 sa *SockaddrCAN 569 raw *RawSockaddrCAN 570 err error 571 }{ 572 { 573 name: "with ids", 574 sa: &SockaddrCAN{ 575 Ifindex: 12345678, 576 RxID: 0xAAAAAAAA, 577 TxID: 0xBBBBBBBB, 578 }, 579 raw: &RawSockaddrCAN{ 580 Family: AF_CAN, 581 Ifindex: 12345678, 582 Addr: [16]byte{ 583 0xAA, 0xAA, 0xAA, 0xAA, 584 0xBB, 0xBB, 0xBB, 0xBB, 585 0x0, 0x0, 0x0, 0x0, 586 0x0, 0x0, 0x0, 0x0, 587 }, 588 }, 589 }, 590 { 591 name: "negative ifindex", 592 sa: &SockaddrCAN{ 593 Ifindex: -1, 594 }, 595 err: EINVAL, 596 }, 597 } 598 599 for _, tt := range tests { 600 t.Run(tt.name, func(t *testing.T) { 601 out, l, err := tt.sa.sockaddr() 602 if err != tt.err { 603 t.Fatalf("unexpected error: %v, want: %v", err, tt.err) 604 } 605 606 // Must be 0 on error or a fixed size otherwise. 607 if (tt.err != nil && l != 0) || (tt.raw != nil && l != SizeofSockaddrCAN) { 608 t.Fatalf("unexpected Socklen: %d", l) 609 } 610 611 if out != nil { 612 raw := (*RawSockaddrCAN)(out) 613 if !reflect.DeepEqual(raw, tt.raw) { 614 t.Fatalf("unexpected RawSockaddrCAN:\n got: %#v\nwant: %#v", raw, tt.raw) 615 } 616 } 617 }) 618 } 619} 620 621// These helpers explicitly copy the contents of in into out to produce 622// the correct sockaddr structure, without relying on unsafe casting to 623// a type of a larger size. 624func sockaddrTIPCToAny(in RawSockaddrTIPC) *RawSockaddrAny { 625 var out RawSockaddrAny 626 copy( 627 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 628 (*(*[SizeofSockaddrTIPC]byte)(unsafe.Pointer(&in)))[:], 629 ) 630 return &out 631} 632 633func sockaddrL2TPIPToAny(in RawSockaddrL2TPIP) *RawSockaddrAny { 634 var out RawSockaddrAny 635 copy( 636 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 637 (*(*[SizeofSockaddrL2TPIP]byte)(unsafe.Pointer(&in)))[:], 638 ) 639 return &out 640} 641 642func sockaddrL2TPIP6ToAny(in RawSockaddrL2TPIP6) *RawSockaddrAny { 643 var out RawSockaddrAny 644 copy( 645 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 646 (*(*[SizeofSockaddrL2TPIP6]byte)(unsafe.Pointer(&in)))[:], 647 ) 648 return &out 649} 650 651func sockaddrUnixToAny(in RawSockaddrUnix) *RawSockaddrAny { 652 var out RawSockaddrAny 653 copy( 654 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 655 (*(*[SizeofSockaddrUnix]byte)(unsafe.Pointer(&in)))[:], 656 ) 657 return &out 658} 659 660func sockaddrIUCVToAny(in RawSockaddrIUCV) *RawSockaddrAny { 661 var out RawSockaddrAny 662 copy( 663 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 664 (*(*[SizeofSockaddrUnix]byte)(unsafe.Pointer(&in)))[:], 665 ) 666 return &out 667} 668 669func sockaddrCANToAny(in RawSockaddrCAN) *RawSockaddrAny { 670 var out RawSockaddrAny 671 copy( 672 (*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:], 673 (*(*[SizeofSockaddrCAN]byte)(unsafe.Pointer(&in)))[:], 674 ) 675 return &out 676} 677