1
2
3 package net
4
5 import (
6 "context"
7 "fmt"
8 "net"
9 "os"
10 "syscall"
11 "unsafe"
12
13 "github.com/shirou/gopsutil/internal/common"
14 "golang.org/x/sys/windows"
15 )
16
17 var (
18 modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
19 procGetExtendedTCPTable = modiphlpapi.NewProc("GetExtendedTcpTable")
20 procGetExtendedUDPTable = modiphlpapi.NewProc("GetExtendedUdpTable")
21 procGetIfEntry2 = modiphlpapi.NewProc("GetIfEntry2")
22 )
23
24 const (
25 TCPTableBasicListener = iota
26 TCPTableBasicConnections
27 TCPTableBasicAll
28 TCPTableOwnerPIDListener
29 TCPTableOwnerPIDConnections
30 TCPTableOwnerPIDAll
31 TCPTableOwnerModuleListener
32 TCPTableOwnerModuleConnections
33 TCPTableOwnerModuleAll
34 )
35
36 type netConnectionKindType struct {
37 family uint32
38 sockType uint32
39 filename string
40 }
41
42 var kindTCP4 = netConnectionKindType{
43 family: syscall.AF_INET,
44 sockType: syscall.SOCK_STREAM,
45 filename: "tcp",
46 }
47 var kindTCP6 = netConnectionKindType{
48 family: syscall.AF_INET6,
49 sockType: syscall.SOCK_STREAM,
50 filename: "tcp6",
51 }
52 var kindUDP4 = netConnectionKindType{
53 family: syscall.AF_INET,
54 sockType: syscall.SOCK_DGRAM,
55 filename: "udp",
56 }
57 var kindUDP6 = netConnectionKindType{
58 family: syscall.AF_INET6,
59 sockType: syscall.SOCK_DGRAM,
60 filename: "udp6",
61 }
62
63 var netConnectionKindMap = map[string][]netConnectionKindType{
64 "all": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
65 "tcp": {kindTCP4, kindTCP6},
66 "tcp4": {kindTCP4},
67 "tcp6": {kindTCP6},
68 "udp": {kindUDP4, kindUDP6},
69 "udp4": {kindUDP4},
70 "udp6": {kindUDP6},
71 "inet": {kindTCP4, kindTCP6, kindUDP4, kindUDP6},
72 "inet4": {kindTCP4, kindUDP4},
73 "inet6": {kindTCP6, kindUDP6},
74 }
75
76
77 type guid struct {
78 Data1 uint32
79 Data2 uint16
80 Data3 uint16
81 Data4 [8]byte
82 }
83
84 const (
85 maxStringSize = 256
86 maxPhysAddressLength = 32
87 pad0for64_4for32 = 0
88 )
89
90 type mibIfRow2 struct {
91 InterfaceLuid uint64
92 InterfaceIndex uint32
93 InterfaceGuid guid
94 Alias [maxStringSize + 1]uint16
95 Description [maxStringSize + 1]uint16
96 PhysicalAddressLength uint32
97 PhysicalAddress [maxPhysAddressLength]uint8
98 PermanentPhysicalAddress [maxPhysAddressLength]uint8
99 Mtu uint32
100 Type uint32
101 TunnelType uint32
102 MediaType uint32
103 PhysicalMediumType uint32
104 AccessType uint32
105 DirectionType uint32
106 InterfaceAndOperStatusFlags uint32
107 OperStatus uint32
108 AdminStatus uint32
109 MediaConnectState uint32
110 NetworkGuid guid
111 ConnectionType uint32
112 padding1 [pad0for64_4for32]byte
113 TransmitLinkSpeed uint64
114 ReceiveLinkSpeed uint64
115 InOctets uint64
116 InUcastPkts uint64
117 InNUcastPkts uint64
118 InDiscards uint64
119 InErrors uint64
120 InUnknownProtos uint64
121 InUcastOctets uint64
122 InMulticastOctets uint64
123 InBroadcastOctets uint64
124 OutOctets uint64
125 OutUcastPkts uint64
126 OutNUcastPkts uint64
127 OutDiscards uint64
128 OutErrors uint64
129 OutUcastOctets uint64
130 OutMulticastOctets uint64
131 OutBroadcastOctets uint64
132 OutQLen uint64
133 }
134
135 func IOCounters(pernic bool) ([]IOCountersStat, error) {
136 return IOCountersWithContext(context.Background(), pernic)
137 }
138
139 func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
140 ifs, err := net.Interfaces()
141 if err != nil {
142 return nil, err
143 }
144 var counters []IOCountersStat
145
146 err = procGetIfEntry2.Find()
147 if err == nil {
148 for _, ifi := range ifs {
149 c := IOCountersStat{
150 Name: ifi.Name,
151 }
152
153 row := mibIfRow2{InterfaceIndex: uint32(ifi.Index)}
154 ret, _, err := procGetIfEntry2.Call(uintptr(unsafe.Pointer(&row)))
155 if ret != 0 {
156 return nil, os.NewSyscallError("GetIfEntry2", err)
157 }
158 c.BytesSent = uint64(row.OutOctets)
159 c.BytesRecv = uint64(row.InOctets)
160 c.PacketsSent = uint64(row.OutUcastPkts)
161 c.PacketsRecv = uint64(row.InUcastPkts)
162 c.Errin = uint64(row.InErrors)
163 c.Errout = uint64(row.OutErrors)
164 c.Dropin = uint64(row.InDiscards)
165 c.Dropout = uint64(row.OutDiscards)
166
167 counters = append(counters, c)
168 }
169 } else {
170 for _, ifi := range ifs {
171 c := IOCountersStat{
172 Name: ifi.Name,
173 }
174
175 row := windows.MibIfRow{Index: uint32(ifi.Index)}
176 err = windows.GetIfEntry(&row)
177 if err != nil {
178 return nil, os.NewSyscallError("GetIfEntry", err)
179 }
180 c.BytesSent = uint64(row.OutOctets)
181 c.BytesRecv = uint64(row.InOctets)
182 c.PacketsSent = uint64(row.OutUcastPkts)
183 c.PacketsRecv = uint64(row.InUcastPkts)
184 c.Errin = uint64(row.InErrors)
185 c.Errout = uint64(row.OutErrors)
186 c.Dropin = uint64(row.InDiscards)
187 c.Dropout = uint64(row.OutDiscards)
188
189 counters = append(counters, c)
190 }
191 }
192
193 if !pernic {
194 return getIOCountersAll(counters)
195 }
196 return counters, nil
197 }
198
199
200 func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) {
201 return IOCountersByFileWithContext(context.Background(), pernic, filename)
202 }
203
204 func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
205 return IOCounters(pernic)
206 }
207
208
209
210
211 func Connections(kind string) ([]ConnectionStat, error) {
212 return ConnectionsWithContext(context.Background(), kind)
213 }
214
215 func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
216 return ConnectionsPidWithContext(ctx, kind, 0)
217 }
218
219
220 func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
221 return ConnectionsPidWithContext(context.Background(), kind, pid)
222 }
223
224 func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
225 tmap, ok := netConnectionKindMap[kind]
226 if !ok {
227 return nil, fmt.Errorf("invalid kind, %s", kind)
228 }
229 return getProcInet(tmap, pid)
230 }
231
232 func getProcInet(kinds []netConnectionKindType, pid int32) ([]ConnectionStat, error) {
233 stats := make([]ConnectionStat, 0)
234
235 for _, kind := range kinds {
236 s, err := getNetStatWithKind(kind)
237 if err != nil {
238 continue
239 }
240
241 if pid == 0 {
242 stats = append(stats, s...)
243 } else {
244 for _, ns := range s {
245 if ns.Pid != pid {
246 continue
247 }
248 stats = append(stats, ns)
249 }
250 }
251 }
252
253 return stats, nil
254 }
255
256 func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
257 if kindType.filename == "" {
258 return nil, fmt.Errorf("kind filename must be required")
259 }
260
261 switch kindType.filename {
262 case kindTCP4.filename:
263 return getTCPConnections(kindTCP4.family)
264 case kindTCP6.filename:
265 return getTCPConnections(kindTCP6.family)
266 case kindUDP4.filename:
267 return getUDPConnections(kindUDP4.family)
268 case kindUDP6.filename:
269 return getUDPConnections(kindUDP6.family)
270 }
271
272 return nil, fmt.Errorf("invalid kind filename, %s", kindType.filename)
273 }
274
275
276
277 func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) {
278 return ConnectionsMaxWithContext(context.Background(), kind, max)
279 }
280
281 func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
282 return []ConnectionStat{}, common.ErrNotImplementedError
283 }
284
285
286
287
288 func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
289 return ConnectionsWithoutUidsWithContext(context.Background(), kind)
290 }
291
292 func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
293 return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
294 }
295
296 func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
297 return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
298 }
299
300 func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
301 return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
302 }
303
304 func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
305 return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
306 }
307
308 func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
309 return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
310 }
311
312 func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
313 return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
314 }
315
316 func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
317 return []ConnectionStat{}, common.ErrNotImplementedError
318 }
319
320 func FilterCounters() ([]FilterStat, error) {
321 return FilterCountersWithContext(context.Background())
322 }
323
324 func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
325 return nil, common.ErrNotImplementedError
326 }
327
328 func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
329 return ConntrackStatsWithContext(context.Background(), percpu)
330 }
331
332 func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
333 return nil, common.ErrNotImplementedError
334 }
335
336
337
338
339
340
341 func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
342 return ProtoCountersWithContext(context.Background(), protocols)
343 }
344
345 func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) {
346 return nil, common.ErrNotImplementedError
347 }
348
349 func getTableUintptr(family uint32, buf []byte) uintptr {
350 var (
351 pmibTCPTable pmibTCPTableOwnerPidAll
352 pmibTCP6Table pmibTCP6TableOwnerPidAll
353
354 p uintptr
355 )
356 switch family {
357 case kindTCP4.family:
358 if len(buf) > 0 {
359 pmibTCPTable = (*mibTCPTableOwnerPid)(unsafe.Pointer(&buf[0]))
360 p = uintptr(unsafe.Pointer(pmibTCPTable))
361 } else {
362 p = uintptr(unsafe.Pointer(pmibTCPTable))
363 }
364 case kindTCP6.family:
365 if len(buf) > 0 {
366 pmibTCP6Table = (*mibTCP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
367 p = uintptr(unsafe.Pointer(pmibTCP6Table))
368 } else {
369 p = uintptr(unsafe.Pointer(pmibTCP6Table))
370 }
371 }
372 return p
373 }
374
375 func getTableInfo(filename string, table interface{}) (index, step, length int) {
376 switch filename {
377 case kindTCP4.filename:
378 index = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).DwNumEntries))
379 step = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).Table))
380 length = int(table.(pmibTCPTableOwnerPidAll).DwNumEntries)
381 case kindTCP6.filename:
382 index = int(unsafe.Sizeof(table.(pmibTCP6TableOwnerPidAll).DwNumEntries))
383 step = int(unsafe.Sizeof(table.(pmibTCP6TableOwnerPidAll).Table))
384 length = int(table.(pmibTCP6TableOwnerPidAll).DwNumEntries)
385 case kindUDP4.filename:
386 index = int(unsafe.Sizeof(table.(pmibUDPTableOwnerPid).DwNumEntries))
387 step = int(unsafe.Sizeof(table.(pmibUDPTableOwnerPid).Table))
388 length = int(table.(pmibUDPTableOwnerPid).DwNumEntries)
389 case kindUDP6.filename:
390 index = int(unsafe.Sizeof(table.(pmibUDP6TableOwnerPid).DwNumEntries))
391 step = int(unsafe.Sizeof(table.(pmibUDP6TableOwnerPid).Table))
392 length = int(table.(pmibUDP6TableOwnerPid).DwNumEntries)
393 }
394
395 return
396 }
397
398 func getTCPConnections(family uint32) ([]ConnectionStat, error) {
399 var (
400 p uintptr
401 buf []byte
402 size uint32
403
404 pmibTCPTable pmibTCPTableOwnerPidAll
405 pmibTCP6Table pmibTCP6TableOwnerPidAll
406 )
407
408 if family == 0 {
409 return nil, fmt.Errorf("faimly must be required")
410 }
411
412 for {
413 switch family {
414 case kindTCP4.family:
415 if len(buf) > 0 {
416 pmibTCPTable = (*mibTCPTableOwnerPid)(unsafe.Pointer(&buf[0]))
417 p = uintptr(unsafe.Pointer(pmibTCPTable))
418 } else {
419 p = uintptr(unsafe.Pointer(pmibTCPTable))
420 }
421 case kindTCP6.family:
422 if len(buf) > 0 {
423 pmibTCP6Table = (*mibTCP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
424 p = uintptr(unsafe.Pointer(pmibTCP6Table))
425 } else {
426 p = uintptr(unsafe.Pointer(pmibTCP6Table))
427 }
428 }
429
430 err := getExtendedTcpTable(p,
431 &size,
432 true,
433 family,
434 tcpTableOwnerPidAll,
435 0)
436 if err == nil {
437 break
438 }
439 if err != windows.ERROR_INSUFFICIENT_BUFFER {
440 return nil, err
441 }
442 buf = make([]byte, size)
443 }
444
445 var (
446 index, step int
447 length int
448 )
449
450 stats := make([]ConnectionStat, 0)
451 switch family {
452 case kindTCP4.family:
453 index, step, length = getTableInfo(kindTCP4.filename, pmibTCPTable)
454 case kindTCP6.family:
455 index, step, length = getTableInfo(kindTCP6.filename, pmibTCP6Table)
456 }
457
458 if length == 0 {
459 return nil, nil
460 }
461
462 for i := 0; i < length; i++ {
463 switch family {
464 case kindTCP4.family:
465 mibs := (*mibTCPRowOwnerPid)(unsafe.Pointer(&buf[index]))
466 ns := mibs.convertToConnectionStat()
467 stats = append(stats, ns)
468 case kindTCP6.family:
469 mibs := (*mibTCP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
470 ns := mibs.convertToConnectionStat()
471 stats = append(stats, ns)
472 }
473
474 index += step
475 }
476 return stats, nil
477 }
478
479 func getUDPConnections(family uint32) ([]ConnectionStat, error) {
480 var (
481 p uintptr
482 buf []byte
483 size uint32
484
485 pmibUDPTable pmibUDPTableOwnerPid
486 pmibUDP6Table pmibUDP6TableOwnerPid
487 )
488
489 if family == 0 {
490 return nil, fmt.Errorf("faimly must be required")
491 }
492
493 for {
494 switch family {
495 case kindUDP4.family:
496 if len(buf) > 0 {
497 pmibUDPTable = (*mibUDPTableOwnerPid)(unsafe.Pointer(&buf[0]))
498 p = uintptr(unsafe.Pointer(pmibUDPTable))
499 } else {
500 p = uintptr(unsafe.Pointer(pmibUDPTable))
501 }
502 case kindUDP6.family:
503 if len(buf) > 0 {
504 pmibUDP6Table = (*mibUDP6TableOwnerPid)(unsafe.Pointer(&buf[0]))
505 p = uintptr(unsafe.Pointer(pmibUDP6Table))
506 } else {
507 p = uintptr(unsafe.Pointer(pmibUDP6Table))
508 }
509 }
510
511 err := getExtendedUdpTable(
512 p,
513 &size,
514 true,
515 family,
516 udpTableOwnerPid,
517 0,
518 )
519 if err == nil {
520 break
521 }
522 if err != windows.ERROR_INSUFFICIENT_BUFFER {
523 return nil, err
524 }
525 buf = make([]byte, size)
526 }
527
528 var (
529 index, step, length int
530 )
531
532 stats := make([]ConnectionStat, 0)
533 switch family {
534 case kindUDP4.family:
535 index, step, length = getTableInfo(kindUDP4.filename, pmibUDPTable)
536 case kindUDP6.family:
537 index, step, length = getTableInfo(kindUDP6.filename, pmibUDP6Table)
538 }
539
540 if length == 0 {
541 return nil, nil
542 }
543
544 for i := 0; i < length; i++ {
545 switch family {
546 case kindUDP4.family:
547 mibs := (*mibUDPRowOwnerPid)(unsafe.Pointer(&buf[index]))
548 ns := mibs.convertToConnectionStat()
549 stats = append(stats, ns)
550 case kindUDP6.family:
551 mibs := (*mibUDP6RowOwnerPid)(unsafe.Pointer(&buf[index]))
552 ns := mibs.convertToConnectionStat()
553 stats = append(stats, ns)
554 }
555
556 index += step
557 }
558 return stats, nil
559 }
560
561
562 var tcpStatuses = map[mibTCPState]string{
563 1: "CLOSED",
564 2: "LISTEN",
565 3: "SYN_SENT",
566 4: "SYN_RECEIVED",
567 5: "ESTABLISHED",
568 6: "FIN_WAIT_1",
569 7: "FIN_WAIT_2",
570 8: "CLOSE_WAIT",
571 9: "CLOSING",
572 10: "LAST_ACK",
573 11: "TIME_WAIT",
574 12: "DELETE",
575 }
576
577 func getExtendedTcpTable(pTcpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass tcpTableClass, reserved uint32) (errcode error) {
578 r1, _, _ := syscall.Syscall6(procGetExtendedTCPTable.Addr(), 6, pTcpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
579 if r1 != 0 {
580 errcode = syscall.Errno(r1)
581 }
582 return
583 }
584
585 func getExtendedUdpTable(pUdpTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass udpTableClass, reserved uint32) (errcode error) {
586 r1, _, _ := syscall.Syscall6(procGetExtendedUDPTable.Addr(), 6, pUdpTable, uintptr(unsafe.Pointer(pdwSize)), getUintptrFromBool(bOrder), uintptr(ulAf), uintptr(tableClass), uintptr(reserved))
587 if r1 != 0 {
588 errcode = syscall.Errno(r1)
589 }
590 return
591 }
592
593 func getUintptrFromBool(b bool) uintptr {
594 if b {
595 return 1
596 }
597 return 0
598 }
599
600 const anySize = 1
601
602
603 type mibTCPState int32
604
605 type tcpTableClass int32
606
607 const (
608 tcpTableBasicListener tcpTableClass = iota
609 tcpTableBasicConnections
610 tcpTableBasicAll
611 tcpTableOwnerPidListener
612 tcpTableOwnerPidConnections
613 tcpTableOwnerPidAll
614 tcpTableOwnerModuleListener
615 tcpTableOwnerModuleConnections
616 tcpTableOwnerModuleAll
617 )
618
619 type udpTableClass int32
620
621 const (
622 udpTableBasic udpTableClass = iota
623 udpTableOwnerPid
624 udpTableOwnerModule
625 )
626
627
628
629 type mibTCPRowOwnerPid struct {
630 DwState uint32
631 DwLocalAddr uint32
632 DwLocalPort uint32
633 DwRemoteAddr uint32
634 DwRemotePort uint32
635 DwOwningPid uint32
636 }
637
638 func (m *mibTCPRowOwnerPid) convertToConnectionStat() ConnectionStat {
639 ns := ConnectionStat{
640 Family: kindTCP4.family,
641 Type: kindTCP4.sockType,
642 Laddr: Addr{
643 IP: parseIPv4HexString(m.DwLocalAddr),
644 Port: uint32(decodePort(m.DwLocalPort)),
645 },
646 Raddr: Addr{
647 IP: parseIPv4HexString(m.DwRemoteAddr),
648 Port: uint32(decodePort(m.DwRemotePort)),
649 },
650 Pid: int32(m.DwOwningPid),
651 Status: tcpStatuses[mibTCPState(m.DwState)],
652 }
653
654 return ns
655 }
656
657 type mibTCPTableOwnerPid struct {
658 DwNumEntries uint32
659 Table [anySize]mibTCPRowOwnerPid
660 }
661
662 type mibTCP6RowOwnerPid struct {
663 UcLocalAddr [16]byte
664 DwLocalScopeId uint32
665 DwLocalPort uint32
666 UcRemoteAddr [16]byte
667 DwRemoteScopeId uint32
668 DwRemotePort uint32
669 DwState uint32
670 DwOwningPid uint32
671 }
672
673 func (m *mibTCP6RowOwnerPid) convertToConnectionStat() ConnectionStat {
674 ns := ConnectionStat{
675 Family: kindTCP6.family,
676 Type: kindTCP6.sockType,
677 Laddr: Addr{
678 IP: parseIPv6HexString(m.UcLocalAddr),
679 Port: uint32(decodePort(m.DwLocalPort)),
680 },
681 Raddr: Addr{
682 IP: parseIPv6HexString(m.UcRemoteAddr),
683 Port: uint32(decodePort(m.DwRemotePort)),
684 },
685 Pid: int32(m.DwOwningPid),
686 Status: tcpStatuses[mibTCPState(m.DwState)],
687 }
688
689 return ns
690 }
691
692 type mibTCP6TableOwnerPid struct {
693 DwNumEntries uint32
694 Table [anySize]mibTCP6RowOwnerPid
695 }
696
697 type pmibTCPTableOwnerPidAll *mibTCPTableOwnerPid
698 type pmibTCP6TableOwnerPidAll *mibTCP6TableOwnerPid
699
700
701
702 type mibUDPRowOwnerPid struct {
703 DwLocalAddr uint32
704 DwLocalPort uint32
705 DwOwningPid uint32
706 }
707
708 func (m *mibUDPRowOwnerPid) convertToConnectionStat() ConnectionStat {
709 ns := ConnectionStat{
710 Family: kindUDP4.family,
711 Type: kindUDP4.sockType,
712 Laddr: Addr{
713 IP: parseIPv4HexString(m.DwLocalAddr),
714 Port: uint32(decodePort(m.DwLocalPort)),
715 },
716 Pid: int32(m.DwOwningPid),
717 }
718
719 return ns
720 }
721
722 type mibUDPTableOwnerPid struct {
723 DwNumEntries uint32
724 Table [anySize]mibUDPRowOwnerPid
725 }
726
727 type mibUDP6RowOwnerPid struct {
728 UcLocalAddr [16]byte
729 DwLocalScopeId uint32
730 DwLocalPort uint32
731 DwOwningPid uint32
732 }
733
734 func (m *mibUDP6RowOwnerPid) convertToConnectionStat() ConnectionStat {
735 ns := ConnectionStat{
736 Family: kindUDP6.family,
737 Type: kindUDP6.sockType,
738 Laddr: Addr{
739 IP: parseIPv6HexString(m.UcLocalAddr),
740 Port: uint32(decodePort(m.DwLocalPort)),
741 },
742 Pid: int32(m.DwOwningPid),
743 }
744
745 return ns
746 }
747
748 type mibUDP6TableOwnerPid struct {
749 DwNumEntries uint32
750 Table [anySize]mibUDP6RowOwnerPid
751 }
752
753 type pmibUDPTableOwnerPid *mibUDPTableOwnerPid
754 type pmibUDP6TableOwnerPid *mibUDP6TableOwnerPid
755
756 func decodePort(port uint32) uint16 {
757 return syscall.Ntohs(uint16(port))
758 }
759
760 func parseIPv4HexString(addr uint32) string {
761 return fmt.Sprintf("%d.%d.%d.%d", addr&255, addr>>8&255, addr>>16&255, addr>>24&255)
762 }
763
764 func parseIPv6HexString(addr [16]byte) string {
765 var ret [16]byte
766 for i := 0; i < 16; i++ {
767 ret[i] = uint8(addr[i])
768 }
769
770
771 ip := net.IP(ret[:])
772 return ip.String()
773 }
774
View as plain text