github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/rawsock/rawsock.go (about) 1 // Copyright 2019-2022 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 package rawsock 16 17 import ( 18 "encoding/binary" 19 "runtime" 20 "syscall" 21 "unsafe" 22 23 "github.com/vishvananda/netns" 24 25 "github.com/inspektor-gadget/inspektor-gadget/pkg/utils/host" 26 netnsig "github.com/inspektor-gadget/inspektor-gadget/pkg/utils/netns" 27 ) 28 29 // Both openRawSock and htons are from github.com/cilium/ebpf: 30 // MIT License 31 // https://github.com/cilium/ebpf/blob/eaa1fe7482d837490c22d9d96a788f669b9e3843/example_sock_elf_test.go#L146-L166 32 33 // htons converts an unsigned short integer from host byte order to network byte order. 34 func htons(i uint16) uint16 { 35 b := make([]byte, 2) 36 binary.BigEndian.PutUint16(b, i) 37 return *(*uint16)(unsafe.Pointer(&b[0])) 38 } 39 40 // OpenRawSock opens a raw socket in the network namespace used by the pid 41 // passed as parameter. 42 // Returns the sock fd and an error. 43 func OpenRawSock(pid uint32) (int, error) { 44 if pid != 0 { 45 // Lock the OS Thread so we don't accidentally switch namespaces 46 runtime.LockOSThread() 47 defer runtime.UnlockOSThread() 48 49 // Save the current network namespace 50 origns, _ := netns.Get() 51 defer origns.Close() 52 53 netnsHandle, err := netnsig.GetFromPidWithAltProcfs(int(pid), host.HostProcFs) 54 if err != nil { 55 return -1, err 56 } 57 defer netnsHandle.Close() 58 err = netns.Set(netnsHandle) 59 if err != nil { 60 return -1, err 61 } 62 63 // Switch back to the original namespace 64 defer netns.Set(origns) 65 } 66 67 sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, int(htons(syscall.ETH_P_ALL))) 68 if err != nil { 69 return -1, err 70 } 71 sll := syscall.SockaddrLinklayer{ 72 Ifindex: 0, // 0 matches any interface 73 Protocol: htons(syscall.ETH_P_ALL), 74 } 75 if err := syscall.Bind(sock, &sll); err != nil { 76 return -1, err 77 } 78 return sock, nil 79 }