Skip to content

Commit

Permalink
Merge branch 'netlink'
Browse files Browse the repository at this point in the history
  • Loading branch information
hmgle committed Jul 29, 2024
2 parents 75169e7 + 1639b01 commit f690a85
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 188 deletions.
3 changes: 2 additions & 1 deletion local/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ go 1.16
require (
github.com/jedisct1/dlog v0.0.0-20210101122416-354ffe815216
github.com/kardianos/service v1.2.0
github.com/mdlayher/netlink v1.7.2
github.com/pborman/getopt/v2 v2.1.0
github.com/vishvananda/netlink v1.1.0
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
golang.org/x/net v0.23.0
)
19 changes: 7 additions & 12 deletions local/go.sum
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/jedisct1/dlog v0.0.0-20210101122416-354ffe815216 h1:31uZUKhZFZGKTg8GsKXBNIcK9TxjXEk2hg+rSKgGDI4=
github.com/jedisct1/dlog v0.0.0-20210101122416-354ffe815216/go.mod h1:CIy7i6SX94LqHB4I4V8JTHovTxZJoQfH1DH31XYNfcs=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g=
github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/pborman/getopt/v2 v2.1.0 h1:eNfR+r+dWLdWmV8g5OlpyrTYHkhVNxHBdN2cCrJmOEA=
github.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
Expand All @@ -25,32 +22,30 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
Expand Down
7 changes: 3 additions & 4 deletions local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ func (l *Local) Start() {
l.StartService(ln)
}

func getPidByAddr(localAddr, remoteAddr *net.TCPAddr, isTCP6 bool) (pid string, destAddr string) {
inode, err := getInodeByAddrs(localAddr, remoteAddr, isTCP6)
func getPidByAddr(localAddr, remoteAddr *net.TCPAddr) (pid string, destAddr string) {
inode, err := getInodeByAddrs(localAddr, remoteAddr)
if err != nil {
log.Errorf("getInodeByAddrs(%s, %s) err: %s", localAddr, remoteAddr, err.Error())
return "", ""
Expand Down Expand Up @@ -214,8 +214,7 @@ func getPidByAddr(localAddr, remoteAddr *net.TCPAddr, isTCP6 bool) (pid string,
// HandleConn handle conn.
func (l *Local) HandleConn(conn *net.TCPConn) error {
raddr, laddr := conn.RemoteAddr().(*net.TCPAddr), conn.LocalAddr().(*net.TCPAddr)
isTCP6 := strings.Contains(conn.LocalAddr().String(), "[")
pid, destAddr := getPidByAddr(raddr, laddr, isTCP6)
pid, destAddr := getPidByAddr(raddr, laddr)
if pid == "" || destAddr == "" {
log.Errorf("getPidByAddr(%s, %s) failed", raddr.String(), conn.LocalAddr().String())
conn.Close()
Expand Down
175 changes: 4 additions & 171 deletions local/util.go
Original file line number Diff line number Diff line change
@@ -1,188 +1,21 @@
package local

import (
"encoding/binary"
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"strings"
"syscall"
"unsafe"

"github.com/mdlayher/netlink"
"github.com/mdlayher/netlink/nlenc"
"github.com/vishvananda/netlink"
)

// See https://man7.org/linux/man-pages/man7/sock_diag.7.html
// IPv4 and IPv6 sockets
//
// For IPv4 and IPv6 sockets, the request is represented in the
// following structure:
//
// struct inet_diag_req_v2 {
// __u8 sdiag_family;
// __u8 sdiag_protocol;
// __u8 idiag_ext;
// __u8 pad;
// __u32 idiag_states;
// struct inet_diag_sockid id;
// };
//
// where struct inet_diag_sockid is defined as follows:
//
// struct inet_diag_sockid {
// __be16 idiag_sport;
// __be16 idiag_dport;
// __be32 idiag_src[4];
// __be32 idiag_dst[4];
// __u32 idiag_if;
// __u32 idiag_cookie[2];
// };
//
// The response to a query for IPv4 or IPv6 sockets is represented
// as an array of
//
// struct inet_diag_msg {
// __u8 idiag_family;
// __u8 idiag_state;
// __u8 idiag_timer;
// __u8 idiag_retrans;
//
// struct inet_diag_sockid id;
//
// __u32 idiag_expires;
// __u32 idiag_rqueue;
// __u32 idiag_wqueue;
// __u32 idiag_uid;
// __u32 idiag_inode;
// };
type (
inetDiagReqV2 struct {
SdiagFamily uint8
SdiagProtocol uint8
IdiagExt uint8
Pad uint8
IdiagStates uint32

IdiagSport uint16
IdiagDport uint16
IdiagSrc net.IP
IdiagDst net.IP
IdiagIf uint32
IdiagCookie [2]uint32
}
inetDiagMSG struct {
Family byte
State byte
Timer byte
ReTrans byte

SrcPort [2]byte
DstPort [2]byte
Src [16]byte
Dst [16]byte
If uint32
Cookie [2]uint32

Expires uint32
RQueue uint32
WQueue uint32
UID uint32
INode uint32
}
)

// socket diags related
const (
SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */
TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/
sizeofInetDiagMSG = 0x38
)

type writeBuffer struct {
Bytes []byte
pos int
}

func (b *writeBuffer) Next(n int) []byte {
s := b.Bytes[b.pos : b.pos+n]
b.pos += n
return s
}

func (req inetDiagReqV2) marshal() []byte {
b := writeBuffer{Bytes: make([]byte, sizeofInetDiagMSG)}

nlenc.PutUint8(b.Next(1), req.SdiagFamily)
nlenc.PutUint8(b.Next(1), req.SdiagProtocol)
nlenc.PutUint8(b.Next(1), req.IdiagExt)
nlenc.PutUint8(b.Next(1), req.Pad)
nlenc.PutUint32(b.Next(4), req.IdiagStates)

binary.BigEndian.PutUint16(b.Next(2), req.IdiagSport)
binary.BigEndian.PutUint16(b.Next(2), req.IdiagDport)

copy(b.Next(16), req.IdiagSrc[:])
copy(b.Next(16), req.IdiagDst[:])
nlenc.PutUint32(b.Next(4), req.IdiagIf)
nlenc.PutUint32(b.Next(4), req.IdiagCookie[0])
nlenc.PutUint32(b.Next(4), req.IdiagCookie[1])

return b.Bytes
}

func getInodeByAddrs(localAddr, remoteAddr *net.TCPAddr, isTCP6 bool) (inode string, err error) {
var (
family uint8
localIP net.IP
remoteIP net.IP
)
if isTCP6 {
family = syscall.AF_INET6
localIP = localAddr.IP.To16()
remoteIP = remoteAddr.IP.To16()
} else {
family = syscall.AF_INET
localIP = localAddr.IP.To4()
remoteIP = remoteAddr.IP.To4()
}
req := &inetDiagReqV2{
SdiagFamily: family,
SdiagProtocol: syscall.IPPROTO_TCP,
IdiagStates: 0xffffffff,
IdiagSport: uint16(localAddr.Port),
IdiagDport: uint16(remoteAddr.Port),
IdiagSrc: localIP,
IdiagDst: remoteIP,
IdiagIf: 0,
IdiagCookie: [2]uint32{TCPDIAG_NOCOOKIE, TCPDIAG_NOCOOKIE},
}
reqMsg := netlink.Message{
Header: netlink.Header{
Type: SOCK_DIAG_BY_FAMILY,
Flags: netlink.Request | netlink.Dump,
},
Data: req.marshal(),
}
c, err := netlink.Dial(syscall.NETLINK_INET_DIAG, nil)
if err != nil {
return
}
defer c.Close()
respMsg, err := c.Execute(reqMsg)
func getInodeByAddrs(localAddr, remoteAddr *net.TCPAddr) (inode string, err error) {
s, err := netlink.SocketGet(localAddr, remoteAddr)
if err != nil {
return
}
for _, msg := range respMsg {
if len(msg.Data) < sizeofInetDiagMSG {
continue
}
response := (*inetDiagMSG)(unsafe.Pointer(&msg.Data[0]))
return strconv.FormatUint(uint64(response.INode), 10), nil
}
return "", fmt.Errorf("no inode for [%s %s]", localAddr.String(), remoteAddr.String())
return strconv.FormatUint(uint64(s.INode), 10), nil
}

func hasIncludeInode(pid, inode string) bool {
Expand Down

0 comments on commit f690a85

Please sign in to comment.