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