inspektor-gadget

Форк
0
679 строк · 18.9 Кб
1
// Copyright 2022-2023 The Inspektor Gadget authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
//go:build linux
16
// +build linux
17

18
package tracer_test
19

20
import (
21
	"fmt"
22
	"net"
23
	"sort"
24
	"testing"
25
	"time"
26

27
	"golang.org/x/sys/unix"
28

29
	utilstest "github.com/inspektor-gadget/inspektor-gadget/internal/test"
30
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/bind/tracer"
31
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/bind/types"
32
	eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
33
)
34

35
func TestBindTracerCreate(t *testing.T) {
36
	t.Parallel()
37

38
	utilstest.RequireRoot(t)
39

40
	tracer := createTracer(t, &tracer.Config{}, func(*types.Event) {})
41
	if tracer == nil {
42
		t.Fatal("Returned tracer was nil")
43
	}
44
}
45

46
func TestBindTracerStopIdempotent(t *testing.T) {
47
	t.Parallel()
48

49
	utilstest.RequireRoot(t)
50

51
	tracer := createTracer(t, &tracer.Config{}, func(*types.Event) {})
52

53
	// Check that a double stop doesn't cause issues
54
	tracer.Stop()
55
	tracer.Stop()
56
}
57

58
type sockOpt struct {
59
	level int
60
	opt   int
61
	value int
62
}
63

64
func TestBindTracer(t *testing.T) {
65
	t.Parallel()
66

67
	utilstest.RequireRoot(t)
68

69
	const unprivilegedUID = int(1435)
70
	const unprivilegedGID = int(6789)
71

72
	type testDefinition struct {
73
		getTracerConfig func(info *utilstest.RunnerInfo) *tracer.Config
74
		runnerConfig    *utilstest.RunnerConfig
75
		generateEvent   func() (uint16, error)
76
		validateEvent   func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event)
77
	}
78

79
	for name, test := range map[string]testDefinition{
80
		"captures_all_events_with_no_filters_configured": {
81
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
82
				return &tracer.Config{}
83
			},
84
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0),
85
			validateEvent: utilstest.ExpectAtLeastOneEvent(func(info *utilstest.RunnerInfo, port uint16) *types.Event {
86
				return &types.Event{
87
					Event: eventtypes.Event{
88
						Type: eventtypes.NORMAL,
89
					},
90
					Pid:           uint32(info.Pid),
91
					Comm:          info.Comm,
92
					Protocol:      "TCP",
93
					Addr:          "127.0.0.1",
94
					Port:          port,
95
					Options:       ".....",
96
					Interface:     "",
97
					WithMountNsID: eventtypes.WithMountNsID{MountNsID: info.MountNsID},
98
				}
99
			}),
100
		},
101
		"captures_no_events_with_no_matching_filter": {
102
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
103
				return &tracer.Config{
104
					MountnsMap: utilstest.CreateMntNsFilterMap(t, 0),
105
				}
106
			},
107
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0),
108
			validateEvent: utilstest.ExpectNoEvent[types.Event, uint16],
109
		},
110
		"captures_events_with_matching_filter": {
111
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
112
				return &tracer.Config{
113
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
114
				}
115
			},
116
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0),
117
			validateEvent: utilstest.ExpectOneEvent(func(info *utilstest.RunnerInfo, port uint16) *types.Event {
118
				return &types.Event{
119
					Event: eventtypes.Event{
120
						Type: eventtypes.NORMAL,
121
					},
122
					Pid:           uint32(info.Pid),
123
					Comm:          info.Comm,
124
					Protocol:      "TCP",
125
					Addr:          "127.0.0.1",
126
					Port:          port,
127
					Options:       ".....",
128
					Interface:     "",
129
					WithMountNsID: eventtypes.WithMountNsID{MountNsID: info.MountNsID},
130
				}
131
			}),
132
		},
133
		"tcp4": {
134
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
135
				return &tracer.Config{
136
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
137
				}
138
			},
139
			generateEvent: bindSocketFn("127.0.0.2", unix.AF_INET, unix.SOCK_STREAM, 0),
140
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
141
				if len(events) != 1 {
142
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
143
				}
144

145
				utilstest.Equal(t, "127.0.0.2", events[0].Addr, "Captured event has bad Addr")
146
				utilstest.Equal(t, "TCP", events[0].Protocol, "Captured event has bad Protocol")
147
			},
148
		},
149
		"tcp6": {
150
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
151
				return &tracer.Config{
152
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
153
				}
154
			},
155
			generateEvent: bindSocketFn("::", unix.AF_INET6, unix.SOCK_STREAM, 0),
156
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
157
				if len(events) != 1 {
158
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
159
				}
160

161
				utilstest.Equal(t, "::", events[0].Addr, "Captured event has bad Addr")
162
				utilstest.Equal(t, "TCP", events[0].Protocol, "Captured event has bad Protocol")
163
			},
164
		},
165
		"udp4": {
166
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
167
				return &tracer.Config{
168
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
169
				}
170
			},
171
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_DGRAM, 0),
172
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
173
				if len(events) != 1 {
174
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
175
				}
176

177
				utilstest.Equal(t, "127.0.0.1", events[0].Addr, "Captured event has bad Addr")
178
				utilstest.Equal(t, "UDP", events[0].Protocol, "Captured event has bad Protocol")
179
			},
180
		},
181
		"udp6": {
182
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
183
				return &tracer.Config{
184
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
185
				}
186
			},
187
			generateEvent: bindSocketFn("::", unix.AF_INET6, unix.SOCK_DGRAM, 0),
188
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
189
				if len(events) != 1 {
190
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
191
				}
192

193
				utilstest.Equal(t, "::", events[0].Addr, "Captured event has bad Addr")
194
				utilstest.Equal(t, "UDP", events[0].Protocol, "Captured event has bad Protocol")
195
			},
196
		},
197
		"interface": {
198
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
199
				return &tracer.Config{
200
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
201
				}
202
			},
203
			generateEvent: func() (uint16, error) {
204
				opts := []sockOpt{
205
					{
206
						level: unix.SOL_SOCKET,
207
						opt:   unix.SO_BINDTOIFINDEX,
208
						value: 1, // "lo" iface
209
					},
210
				}
211

212
				return bindSocketWithOpts("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0, opts)
213
			},
214
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
215
				if len(events) != 1 {
216
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
217
				}
218

219
				utilstest.Equal(t, "lo", events[0].Interface, "Captured event has bad Interface")
220
			},
221
		},
222
		"pid_filter_match": {
223
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
224
				return &tracer.Config{
225
					TargetPid: int32(info.Pid),
226
					// It's difficult to only test the PID filter since other
227
					// test events are generated from the same PID on this
228
					// test suite
229
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
230
				}
231
			},
232
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0),
233
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
234
				if len(events) != 1 {
235
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
236
				}
237
			},
238
		},
239
		"pid_filter_no_match": {
240
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
241
				return &tracer.Config{
242
					TargetPid:  int32(1),
243
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
244
				}
245
			},
246
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0),
247
			validateEvent: utilstest.ExpectNoEvent[types.Event, uint16],
248
		},
249
		"target_ports_filter_match": {
250
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
251
				return &tracer.Config{
252
					MountnsMap:  utilstest.CreateMntNsFilterMap(t, info.MountNsID),
253
					TargetPorts: []uint16{5555},
254
				}
255
			},
256
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 5555),
257
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
258
				if len(events) != 1 {
259
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
260
				}
261
			},
262
		},
263
		"target_ports_filter_no_match": {
264
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
265
				return &tracer.Config{
266
					MountnsMap:  utilstest.CreateMntNsFilterMap(t, info.MountNsID),
267
					TargetPorts: []uint16{5555},
268
				}
269
			},
270
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 5556),
271
			validateEvent: utilstest.ExpectNoEvent[types.Event, uint16],
272
		},
273
		"target_ports_filter_multiple_ports": {
274
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
275
				return &tracer.Config{
276
					MountnsMap:  utilstest.CreateMntNsFilterMap(t, info.MountNsID),
277
					TargetPorts: []uint16{5555, 5556, 5557, 5558},
278
				}
279
			},
280
			generateEvent: func() (uint16, error) {
281
				// Generate 5 events but only 4 should be captured
282
				ports := []uint16{5555, 5556, 5557, 5558, 5559}
283
				var err error
284
				for _, port := range ports {
285
					_, err = bindSocket("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, int(port))
286
					if err != nil {
287
						return 0, err
288
					}
289
				}
290

291
				return 0, nil
292
			},
293
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
294
				if len(events) != 4 {
295
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
296
				}
297
			},
298
		},
299
		"ignore_errors_false": {
300
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
301
				return &tracer.Config{
302
					MountnsMap:   utilstest.CreateMntNsFilterMap(t, info.MountNsID),
303
					IgnoreErrors: false,
304
				}
305
			},
306
			generateEvent: bindSocketError,
307
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
308
				if len(events) != 2 {
309
					t.Fatalf("Wrong number of events received %d, expected 2", len(events))
310
				}
311
			},
312
		},
313
		"ignore_errors_true": {
314
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
315
				return &tracer.Config{
316
					MountnsMap:   utilstest.CreateMntNsFilterMap(t, info.MountNsID),
317
					IgnoreErrors: true,
318
				}
319
			},
320
			generateEvent: bindSocketError,
321
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, port uint16, events []types.Event) {
322
				if len(events) != 1 {
323
					t.Fatalf("Wrong number of events received %d, expected 1", len(events))
324
				}
325
			},
326
		},
327
		"event_has_UID_and_GID_of_user_generating_event": {
328
			getTracerConfig: func(info *utilstest.RunnerInfo) *tracer.Config {
329
				return &tracer.Config{
330
					MountnsMap: utilstest.CreateMntNsFilterMap(t, info.MountNsID),
331
				}
332
			},
333
			runnerConfig: &utilstest.RunnerConfig{
334
				Uid: unprivilegedUID,
335
				Gid: unprivilegedGID,
336
			},
337
			generateEvent: bindSocketFn("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0),
338
			validateEvent: func(t *testing.T, info *utilstest.RunnerInfo, _ uint16, events []types.Event) {
339
				if len(events) != 1 {
340
					t.Fatalf("One event expected")
341
				}
342

343
				utilstest.Equal(t, uint32(info.Uid), events[0].Uid,
344
					"Event has bad UID")
345

346
				utilstest.Equal(t, uint32(info.Gid), events[0].Gid,
347
					"Event has bad GID")
348
			},
349
		},
350
	} {
351
		test := test
352

353
		t.Run(name, func(t *testing.T) {
354
			t.Parallel()
355

356
			events := []types.Event{}
357
			eventCallback := func(event *types.Event) {
358
				// normalize
359
				event.Timestamp = 0
360

361
				events = append(events, *event)
362
			}
363

364
			runner := utilstest.NewRunnerWithTest(t, test.runnerConfig)
365

366
			createTracer(t, test.getTracerConfig(runner.Info), eventCallback)
367

368
			var port uint16
369

370
			utilstest.RunWithRunner(t, runner, func() error {
371
				var err error
372
				port, err = test.generateEvent()
373
				return err
374
			})
375

376
			// Give some time for the tracer to capture the events
377
			time.Sleep(100 * time.Millisecond)
378

379
			test.validateEvent(t, runner.Info, port, events)
380
		})
381
	}
382
}
383

384
func TestBindTracerOpts(t *testing.T) {
385
	t.Parallel()
386

387
	utilstest.RequireRoot(t)
388

389
	type testDefinition struct {
390
		opts         []sockOpt
391
		expectedOpts string
392
	}
393

394
	for name, test := range map[string]testDefinition{
395
		"no_options": {
396
			opts:         nil,
397
			expectedOpts: ".....",
398
		},
399
		"SO_REUSEPORT": {
400
			opts: []sockOpt{
401
				{
402
					level: unix.SOL_SOCKET,
403
					opt:   unix.SO_REUSEPORT,
404
					value: 1,
405
				},
406
			},
407
			expectedOpts: "r....",
408
		},
409
		"SO_REUSEADDR": {
410
			opts: []sockOpt{
411
				{
412
					level: unix.SOL_SOCKET,
413
					opt:   unix.SO_REUSEADDR,
414
					value: 1,
415
				},
416
			},
417
			expectedOpts: ".R...",
418
		},
419
		"IP_TRANSPARENT": {
420
			opts: []sockOpt{
421
				{
422
					level: unix.IPPROTO_IP,
423
					opt:   unix.IP_TRANSPARENT,
424
					value: 1,
425
				},
426
			},
427
			expectedOpts: "...T.",
428
		},
429
		"IP_BIND_ADDRESS_NO_PORT": {
430
			opts: []sockOpt{
431
				{
432
					level: unix.IPPROTO_IP,
433
					opt:   unix.IP_BIND_ADDRESS_NO_PORT,
434
					value: 1,
435
				},
436
			},
437
			expectedOpts: "..N..",
438
		},
439
		"IP_FREEBIND": {
440
			opts: []sockOpt{
441
				{
442
					level: unix.IPPROTO_IP,
443
					opt:   unix.IP_FREEBIND,
444
					value: 1,
445
				},
446
			},
447
			expectedOpts: "....F",
448
		},
449
		"SO_REUSEPORT|SO_REUSEADDR": {
450
			opts: []sockOpt{
451
				{
452
					level: unix.SOL_SOCKET,
453
					opt:   unix.SO_REUSEPORT,
454
					value: 1,
455
				},
456
				{
457
					level: unix.SOL_SOCKET,
458
					opt:   unix.SO_REUSEADDR,
459
					value: 1,
460
				},
461
			},
462
			expectedOpts: "rR...",
463
		},
464
		"IP_TRANSPARENT|IP_BIND_ADDRESS_NO_PORT|IP_FREEBIND": {
465
			opts: []sockOpt{
466
				{
467
					level: unix.IPPROTO_IP,
468
					opt:   unix.IP_TRANSPARENT,
469
					value: 1,
470
				},
471
				{
472
					level: unix.IPPROTO_IP,
473
					opt:   unix.IP_BIND_ADDRESS_NO_PORT,
474
					value: 1,
475
				},
476
				{
477
					level: unix.IPPROTO_IP,
478
					opt:   unix.IP_FREEBIND,
479
					value: 1,
480
				},
481
			},
482
			expectedOpts: "..NTF",
483
		},
484
	} {
485
		test := test
486

487
		t.Run(name, func(t *testing.T) {
488
			t.Parallel()
489

490
			events := []types.Event{}
491
			eventCallback := func(event *types.Event) {
492
				events = append(events, *event)
493
			}
494

495
			runner := utilstest.NewRunnerWithTest(t, nil)
496

497
			tracerConfig := &tracer.Config{
498
				MountnsMap: utilstest.CreateMntNsFilterMap(t, runner.Info.MountNsID),
499
			}
500

501
			createTracer(t, tracerConfig, eventCallback)
502

503
			utilstest.RunWithRunner(t, runner, func() error {
504
				_, err := bindSocketWithOpts("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0, test.opts)
505
				return err
506
			})
507

508
			// Give some time for the tracer to capture the events
509
			time.Sleep(100 * time.Millisecond)
510

511
			if len(events) != 1 {
512
				t.Fatalf("Wrong number of events received %d, expected 1", len(events))
513
			}
514

515
			utilstest.Equal(t, test.expectedOpts, events[0].Options,
516
				"Captured event has wrong options")
517
		})
518
	}
519
}
520

521
func TestBindTracerMultipleMntNsIDsFilter(t *testing.T) {
522
	t.Parallel()
523

524
	utilstest.RequireRoot(t)
525

526
	events := []types.Event{}
527
	eventCallback := func(event *types.Event) {
528
		events = append(events, *event)
529
	}
530

531
	// struct with only fields we want to check on this test
532
	type expectedEvent struct {
533
		mntNsID uint64
534
		port    uint16
535
	}
536

537
	const n int = 5
538
	runners := make([]*utilstest.Runner, n)
539
	expectedEvents := make([]expectedEvent, n)
540
	mntNsIDs := make([]uint64, n)
541

542
	for i := 0; i < n; i++ {
543
		runners[i] = utilstest.NewRunnerWithTest(t, nil)
544
		mntNsIDs[i] = runners[i].Info.MountNsID
545
		expectedEvents[i].mntNsID = runners[i].Info.MountNsID
546
	}
547

548
	// Filter events from all runners but last one
549
	config := &tracer.Config{
550
		MountnsMap: utilstest.CreateMntNsFilterMap(t, mntNsIDs[:n-1]...),
551
	}
552

553
	createTracer(t, config, eventCallback)
554

555
	for i := 0; i < n; i++ {
556
		utilstest.RunWithRunner(t, runners[i], func() error {
557
			var err error
558
			expectedEvents[i].port, err = bindSocket("127.0.0.1", unix.AF_INET, unix.SOCK_STREAM, 0)
559
			return err
560
		})
561
	}
562

563
	// Give some time for the tracer to capture the events
564
	time.Sleep(100 * time.Millisecond)
565

566
	if len(events) != n-1 {
567
		t.Fatalf("%d events were expected, %d found", n-1, len(events))
568
	}
569

570
	// Pop last event since it shouldn't have been captured
571
	expectedEvents = expectedEvents[:n-1]
572

573
	// Order of events is not guaranteed, then we need to sort before comparing
574
	sort.Slice(expectedEvents, func(i, j int) bool {
575
		return expectedEvents[i].mntNsID < expectedEvents[j].mntNsID
576
	})
577
	sort.Slice(events, func(i, j int) bool {
578
		return events[i].WithMountNsID.MountNsID < events[j].WithMountNsID.MountNsID
579
	})
580

581
	for i := 0; i < n-1; i++ {
582
		utilstest.Equal(t, expectedEvents[i].mntNsID, events[i].WithMountNsID.MountNsID,
583
			"Captured event has bad MountNsID")
584

585
		utilstest.Equal(t, expectedEvents[i].port, events[i].Port,
586
			"Captured event has bad Port")
587
	}
588
}
589

590
func createTracer(
591
	t *testing.T, config *tracer.Config, callback func(*types.Event),
592
) *tracer.Tracer {
593
	t.Helper()
594

595
	tracer, err := tracer.NewTracer(config, nil, callback)
596
	if err != nil {
597
		t.Fatalf("Error creating tracer: %s", err)
598
	}
599
	t.Cleanup(tracer.Stop)
600

601
	return tracer
602
}
603

604
// bindSocketFn returns a function that creates a socket, binds it and
605
// returns the port the socket was bound to.
606
func bindSocketFn(ipStr string, domain, typ int, port int) func() (uint16, error) {
607
	return func() (uint16, error) {
608
		return bindSocket(ipStr, domain, typ, port)
609
	}
610
}
611

612
func bindSocket(ipStr string, domain, typ int, port int) (uint16, error) {
613
	return bindSocketWithOpts(ipStr, domain, typ, port, nil)
614
}
615

616
func bindSocketWithOpts(ipStr string, domain, typ int, port int, opts []sockOpt) (uint16, error) {
617
	fd, err := unix.Socket(domain, typ, 0)
618
	if err != nil {
619
		return 0, err
620
	}
621
	defer unix.Close(fd)
622

623
	for _, opt := range opts {
624
		if err := unix.SetsockoptInt(fd, opt.level, opt.opt, opt.value); err != nil {
625
			return 0, fmt.Errorf("SetsockoptInt: %w", err)
626
		}
627
	}
628

629
	var sa unix.Sockaddr
630

631
	ip := net.ParseIP(ipStr)
632

633
	if ip.To4() != nil {
634
		sa4 := &unix.SockaddrInet4{Port: port}
635
		copy(sa4.Addr[:], ip.To4())
636
		sa = sa4
637
	} else if ip.To16() != nil {
638
		sa6 := &unix.SockaddrInet6{Port: port}
639
		copy(sa6.Addr[:], ip.To16())
640
		sa = sa6
641
	} else {
642
		return 0, fmt.Errorf("invalid IP address")
643
	}
644

645
	if err := unix.Bind(fd, sa); err != nil {
646
		return 0, fmt.Errorf("Bind: %w", err)
647
	}
648

649
	sa2, err := unix.Getsockname(fd)
650
	if err != nil {
651
		return 0, fmt.Errorf("Getsockname: %w", err)
652
	}
653

654
	if ip.To4() != nil {
655
		return uint16(sa2.(*unix.SockaddrInet4).Port), nil
656
	} else if ip.To16() != nil {
657
		return uint16(sa2.(*unix.SockaddrInet6).Port), nil
658
	} else {
659
		return 0, fmt.Errorf("invalid IP address")
660
	}
661
}
662

663
func bindSocketError() (uint16, error) {
664
	fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0)
665
	if err != nil {
666
		return 0, err
667
	}
668
	defer unix.Close(fd)
669

670
	if err := unix.Bind(fd, &unix.SockaddrInet4{}); err != nil {
671
		return 0, fmt.Errorf("Bind: %w", err)
672
	}
673

674
	if err := unix.Bind(fd, &unix.SockaddrInet4{}); err == nil {
675
		return 0, fmt.Errorf("Bind should have returned error")
676
	}
677

678
	return 0, nil
679
}
680

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.