github.com/vishvananda/netlink@v1.3.0/socket_linux.go (about) 1 package netlink 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "syscall" 8 9 "github.com/vishvananda/netlink/nl" 10 "golang.org/x/sys/unix" 11 ) 12 13 const ( 14 sizeofSocketID = 0x30 15 sizeofSocketRequest = sizeofSocketID + 0x8 16 sizeofSocket = sizeofSocketID + 0x18 17 sizeofUnixSocketRequest = 0x18 // 24 byte 18 sizeofUnixSocket = 0x10 // 16 byte 19 ) 20 21 type socketRequest struct { 22 Family uint8 23 Protocol uint8 24 Ext uint8 25 pad uint8 26 States uint32 27 ID SocketID 28 } 29 30 type writeBuffer struct { 31 Bytes []byte 32 pos int 33 } 34 35 func (b *writeBuffer) Write(c byte) { 36 b.Bytes[b.pos] = c 37 b.pos++ 38 } 39 40 func (b *writeBuffer) Next(n int) []byte { 41 s := b.Bytes[b.pos : b.pos+n] 42 b.pos += n 43 return s 44 } 45 46 func (r *socketRequest) Serialize() []byte { 47 b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)} 48 b.Write(r.Family) 49 b.Write(r.Protocol) 50 b.Write(r.Ext) 51 b.Write(r.pad) 52 native.PutUint32(b.Next(4), r.States) 53 networkOrder.PutUint16(b.Next(2), r.ID.SourcePort) 54 networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort) 55 if r.Family == unix.AF_INET6 { 56 copy(b.Next(16), r.ID.Source) 57 copy(b.Next(16), r.ID.Destination) 58 } else { 59 copy(b.Next(16), r.ID.Source.To4()) 60 copy(b.Next(16), r.ID.Destination.To4()) 61 } 62 native.PutUint32(b.Next(4), r.ID.Interface) 63 native.PutUint32(b.Next(4), r.ID.Cookie[0]) 64 native.PutUint32(b.Next(4), r.ID.Cookie[1]) 65 return b.Bytes 66 } 67 68 func (r *socketRequest) Len() int { return sizeofSocketRequest } 69 70 // According to linux/include/uapi/linux/unix_diag.h 71 type unixSocketRequest struct { 72 Family uint8 73 Protocol uint8 74 pad uint16 75 States uint32 76 INode uint32 77 Show uint32 78 Cookie [2]uint32 79 } 80 81 func (r *unixSocketRequest) Serialize() []byte { 82 b := writeBuffer{Bytes: make([]byte, sizeofUnixSocketRequest)} 83 b.Write(r.Family) 84 b.Write(r.Protocol) 85 native.PutUint16(b.Next(2), r.pad) 86 native.PutUint32(b.Next(4), r.States) 87 native.PutUint32(b.Next(4), r.INode) 88 native.PutUint32(b.Next(4), r.Show) 89 native.PutUint32(b.Next(4), r.Cookie[0]) 90 native.PutUint32(b.Next(4), r.Cookie[1]) 91 return b.Bytes 92 } 93 94 func (r *unixSocketRequest) Len() int { return sizeofUnixSocketRequest } 95 96 type readBuffer struct { 97 Bytes []byte 98 pos int 99 } 100 101 func (b *readBuffer) Read() byte { 102 c := b.Bytes[b.pos] 103 b.pos++ 104 return c 105 } 106 107 func (b *readBuffer) Next(n int) []byte { 108 s := b.Bytes[b.pos : b.pos+n] 109 b.pos += n 110 return s 111 } 112 113 func (s *Socket) deserialize(b []byte) error { 114 if len(b) < sizeofSocket { 115 return fmt.Errorf("socket data short read (%d); want %d", len(b), sizeofSocket) 116 } 117 rb := readBuffer{Bytes: b} 118 s.Family = rb.Read() 119 s.State = rb.Read() 120 s.Timer = rb.Read() 121 s.Retrans = rb.Read() 122 s.ID.SourcePort = networkOrder.Uint16(rb.Next(2)) 123 s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2)) 124 if s.Family == unix.AF_INET6 { 125 s.ID.Source = net.IP(rb.Next(16)) 126 s.ID.Destination = net.IP(rb.Next(16)) 127 } else { 128 s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) 129 rb.Next(12) 130 s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) 131 rb.Next(12) 132 } 133 s.ID.Interface = native.Uint32(rb.Next(4)) 134 s.ID.Cookie[0] = native.Uint32(rb.Next(4)) 135 s.ID.Cookie[1] = native.Uint32(rb.Next(4)) 136 s.Expires = native.Uint32(rb.Next(4)) 137 s.RQueue = native.Uint32(rb.Next(4)) 138 s.WQueue = native.Uint32(rb.Next(4)) 139 s.UID = native.Uint32(rb.Next(4)) 140 s.INode = native.Uint32(rb.Next(4)) 141 return nil 142 } 143 144 func (u *UnixSocket) deserialize(b []byte) error { 145 if len(b) < sizeofUnixSocket { 146 return fmt.Errorf("unix diag data short read (%d); want %d", len(b), sizeofUnixSocket) 147 } 148 rb := readBuffer{Bytes: b} 149 u.Type = rb.Read() 150 u.Family = rb.Read() 151 u.State = rb.Read() 152 u.pad = rb.Read() 153 u.INode = native.Uint32(rb.Next(4)) 154 u.Cookie[0] = native.Uint32(rb.Next(4)) 155 u.Cookie[1] = native.Uint32(rb.Next(4)) 156 return nil 157 } 158 159 // SocketGet returns the Socket identified by its local and remote addresses. 160 func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) { 161 var protocol uint8 162 var localIP, remoteIP net.IP 163 var localPort, remotePort uint16 164 switch l := local.(type) { 165 case *net.TCPAddr: 166 r, ok := remote.(*net.TCPAddr) 167 if !ok { 168 return nil, ErrNotImplemented 169 } 170 localIP = l.IP 171 localPort = uint16(l.Port) 172 remoteIP = r.IP 173 remotePort = uint16(r.Port) 174 protocol = unix.IPPROTO_TCP 175 case *net.UDPAddr: 176 r, ok := remote.(*net.UDPAddr) 177 if !ok { 178 return nil, ErrNotImplemented 179 } 180 localIP = l.IP 181 localPort = uint16(l.Port) 182 remoteIP = r.IP 183 remotePort = uint16(r.Port) 184 protocol = unix.IPPROTO_UDP 185 default: 186 return nil, ErrNotImplemented 187 } 188 189 var family uint8 190 if localIP.To4() != nil && remoteIP.To4() != nil { 191 family = unix.AF_INET 192 } 193 194 if family == 0 && localIP.To16() != nil && remoteIP.To16() != nil { 195 family = unix.AF_INET6 196 } 197 198 if family == 0 { 199 return nil, ErrNotImplemented 200 } 201 202 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 203 req.AddData(&socketRequest{ 204 Family: family, 205 Protocol: protocol, 206 States: 0xffffffff, 207 ID: SocketID{ 208 SourcePort: localPort, 209 DestinationPort: remotePort, 210 Source: localIP, 211 Destination: remoteIP, 212 Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, 213 }, 214 }) 215 216 msgs, err := req.Execute(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY) 217 if err != nil { 218 return nil, err 219 } 220 if len(msgs) == 0 { 221 return nil, errors.New("no message nor error from netlink") 222 } 223 if len(msgs) > 2 { 224 return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) 225 } 226 227 sock := &Socket{} 228 if err := sock.deserialize(msgs[0]); err != nil { 229 return nil, err 230 } 231 return sock, nil 232 } 233 234 // SocketGet returns the Socket identified by its local and remote addresses. 235 func SocketGet(local, remote net.Addr) (*Socket, error) { 236 return pkgHandle.SocketGet(local, remote) 237 } 238 239 // SocketDestroy kills the Socket identified by its local and remote addresses. 240 func (h *Handle) SocketDestroy(local, remote net.Addr) error { 241 localTCP, ok := local.(*net.TCPAddr) 242 if !ok { 243 return ErrNotImplemented 244 } 245 remoteTCP, ok := remote.(*net.TCPAddr) 246 if !ok { 247 return ErrNotImplemented 248 } 249 localIP := localTCP.IP.To4() 250 if localIP == nil { 251 return ErrNotImplemented 252 } 253 remoteIP := remoteTCP.IP.To4() 254 if remoteIP == nil { 255 return ErrNotImplemented 256 } 257 258 s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) 259 if err != nil { 260 return err 261 } 262 defer s.Close() 263 req := h.newNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK) 264 req.AddData(&socketRequest{ 265 Family: unix.AF_INET, 266 Protocol: unix.IPPROTO_TCP, 267 ID: SocketID{ 268 SourcePort: uint16(localTCP.Port), 269 DestinationPort: uint16(remoteTCP.Port), 270 Source: localIP, 271 Destination: remoteIP, 272 Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, 273 }, 274 }) 275 276 _, err = req.Execute(unix.NETLINK_INET_DIAG, 0) 277 return err 278 } 279 280 // SocketDestroy kills the Socket identified by its local and remote addresses. 281 func SocketDestroy(local, remote net.Addr) error { 282 return pkgHandle.SocketDestroy(local, remote) 283 } 284 285 // SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info. 286 func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { 287 // Construct the request 288 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 289 req.AddData(&socketRequest{ 290 Family: family, 291 Protocol: unix.IPPROTO_TCP, 292 Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), 293 States: uint32(0xfff), // all states 294 }) 295 296 // Do the query and parse the result 297 var result []*InetDiagTCPInfoResp 298 var err error 299 err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { 300 sockInfo := &Socket{} 301 if err = sockInfo.deserialize(msg); err != nil { 302 return false 303 } 304 var attrs []syscall.NetlinkRouteAttr 305 if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { 306 return false 307 } 308 309 var res *InetDiagTCPInfoResp 310 if res, err = attrsToInetDiagTCPInfoResp(attrs, sockInfo); err != nil { 311 return false 312 } 313 314 result = append(result, res) 315 return true 316 }) 317 318 if err != nil { 319 return nil, err 320 } 321 return result, nil 322 } 323 324 // SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info. 325 func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { 326 return pkgHandle.SocketDiagTCPInfo(family) 327 } 328 329 // SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket. 330 func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) { 331 // Construct the request 332 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 333 req.AddData(&socketRequest{ 334 Family: family, 335 Protocol: unix.IPPROTO_TCP, 336 Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), 337 States: uint32(0xfff), // all states 338 }) 339 340 // Do the query and parse the result 341 var result []*Socket 342 var err error 343 err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { 344 sockInfo := &Socket{} 345 if err = sockInfo.deserialize(msg); err != nil { 346 return false 347 } 348 result = append(result, sockInfo) 349 return true 350 }) 351 if err != nil { 352 return nil, err 353 } 354 return result, nil 355 } 356 357 // SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket. 358 func SocketDiagTCP(family uint8) ([]*Socket, error) { 359 return pkgHandle.SocketDiagTCP(family) 360 } 361 362 // SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info. 363 func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) { 364 // Construct the request 365 var extensions uint8 366 extensions = 1 << (INET_DIAG_VEGASINFO - 1) 367 extensions |= 1 << (INET_DIAG_INFO - 1) 368 extensions |= 1 << (INET_DIAG_MEMINFO - 1) 369 370 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 371 req.AddData(&socketRequest{ 372 Family: family, 373 Protocol: unix.IPPROTO_UDP, 374 Ext: extensions, 375 States: uint32(0xfff), // all states 376 }) 377 378 // Do the query and parse the result 379 var result []*InetDiagUDPInfoResp 380 var err error 381 err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { 382 sockInfo := &Socket{} 383 if err = sockInfo.deserialize(msg); err != nil { 384 return false 385 } 386 387 var attrs []syscall.NetlinkRouteAttr 388 if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { 389 return false 390 } 391 392 var res *InetDiagUDPInfoResp 393 if res, err = attrsToInetDiagUDPInfoResp(attrs, sockInfo); err != nil { 394 return false 395 } 396 397 result = append(result, res) 398 return true 399 }) 400 if err != nil { 401 return nil, err 402 } 403 return result, nil 404 } 405 406 // SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info. 407 func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) { 408 return pkgHandle.SocketDiagUDPInfo(family) 409 } 410 411 // SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket. 412 func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) { 413 // Construct the request 414 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 415 req.AddData(&socketRequest{ 416 Family: family, 417 Protocol: unix.IPPROTO_UDP, 418 Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), 419 States: uint32(0xfff), // all states 420 }) 421 422 // Do the query and parse the result 423 var result []*Socket 424 var err error 425 err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { 426 sockInfo := &Socket{} 427 if err = sockInfo.deserialize(msg); err != nil { 428 return false 429 } 430 result = append(result, sockInfo) 431 return true 432 }) 433 if err != nil { 434 return nil, err 435 } 436 return result, nil 437 } 438 439 // SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket. 440 func SocketDiagUDP(family uint8) ([]*Socket, error) { 441 return pkgHandle.SocketDiagUDP(family) 442 } 443 444 // UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info. 445 func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { 446 // Construct the request 447 var extensions uint8 448 extensions = 1 << UNIX_DIAG_NAME 449 extensions |= 1 << UNIX_DIAG_PEER 450 extensions |= 1 << UNIX_DIAG_RQLEN 451 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 452 req.AddData(&unixSocketRequest{ 453 Family: unix.AF_UNIX, 454 States: ^uint32(0), // all states 455 Show: uint32(extensions), 456 }) 457 458 var result []*UnixDiagInfoResp 459 var err error 460 err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { 461 sockInfo := &UnixSocket{} 462 if err = sockInfo.deserialize(msg); err != nil { 463 return false 464 } 465 466 // Diagnosis also delivers sockets with AF_INET family, filter those 467 if sockInfo.Family != unix.AF_UNIX { 468 return false 469 } 470 471 var attrs []syscall.NetlinkRouteAttr 472 if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { 473 return false 474 } 475 476 var res *UnixDiagInfoResp 477 if res, err = attrsToUnixDiagInfoResp(attrs, sockInfo); err != nil { 478 return false 479 } 480 result = append(result, res) 481 return true 482 }) 483 if err != nil { 484 return nil, err 485 } 486 return result, nil 487 } 488 489 // UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info. 490 func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { 491 return pkgHandle.UnixSocketDiagInfo() 492 } 493 494 // UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets. 495 func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) { 496 // Construct the request 497 req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) 498 req.AddData(&unixSocketRequest{ 499 Family: unix.AF_UNIX, 500 States: ^uint32(0), // all states 501 }) 502 503 var result []*UnixSocket 504 var err error 505 err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { 506 sockInfo := &UnixSocket{} 507 if err = sockInfo.deserialize(msg); err != nil { 508 return false 509 } 510 511 // Diagnosis also delivers sockets with AF_INET family, filter those 512 if sockInfo.Family == unix.AF_UNIX { 513 result = append(result, sockInfo) 514 } 515 return true 516 }) 517 if err != nil { 518 return nil, err 519 } 520 return result, nil 521 } 522 523 // UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets. 524 func UnixSocketDiag() ([]*UnixSocket, error) { 525 return pkgHandle.UnixSocketDiag() 526 } 527 528 func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) { 529 info := &InetDiagTCPInfoResp{ 530 InetDiagMsg: sockInfo, 531 } 532 for _, a := range attrs { 533 switch a.Attr.Type { 534 case INET_DIAG_INFO: 535 info.TCPInfo = &TCPInfo{} 536 if err := info.TCPInfo.deserialize(a.Value); err != nil { 537 return nil, err 538 } 539 case INET_DIAG_BBRINFO: 540 info.TCPBBRInfo = &TCPBBRInfo{} 541 if err := info.TCPBBRInfo.deserialize(a.Value); err != nil { 542 return nil, err 543 } 544 } 545 } 546 547 return info, nil 548 } 549 550 func attrsToInetDiagUDPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagUDPInfoResp, error) { 551 info := &InetDiagUDPInfoResp{ 552 InetDiagMsg: sockInfo, 553 } 554 for _, a := range attrs { 555 switch a.Attr.Type { 556 case INET_DIAG_MEMINFO: 557 info.Memory = &MemInfo{} 558 if err := info.Memory.deserialize(a.Value); err != nil { 559 return nil, err 560 } 561 } 562 } 563 564 return info, nil 565 } 566 567 func attrsToUnixDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *UnixSocket) (*UnixDiagInfoResp, error) { 568 info := &UnixDiagInfoResp{ 569 DiagMsg: sockInfo, 570 } 571 for _, a := range attrs { 572 switch a.Attr.Type { 573 case UNIX_DIAG_NAME: 574 name := string(a.Value[:a.Attr.Len]) 575 info.Name = &name 576 case UNIX_DIAG_PEER: 577 peer := native.Uint32(a.Value) 578 info.Peer = &peer 579 case UNIX_DIAG_RQLEN: 580 info.Queue = &QueueInfo{ 581 RQueue: native.Uint32(a.Value[:4]), 582 WQueue: native.Uint32(a.Value[4:]), 583 } 584 // default: 585 // fmt.Println("unknown unix attribute type", a.Attr.Type, "with data", a.Value) 586 } 587 } 588 589 return info, nil 590 }