// NewTPacket returns a new TPacket object for reading packets off the wire. // Its behavior may be modified by passing in any/all of afpacket.Opt* to this // function. // If this function succeeds, the user should be sure to Close the returned // TPacket when finished with it. func NewTPacket(opts ...interface{}) (h *TPacket, err error) { h = &TPacket{} if h.opts, err = parseOptions(opts...); err != nil { return nil, err } fd, err := C.socket(C.AF_PACKET, C.int(h.opts.socktype), C.int(C.htons(C.ETH_P_ALL))) if err != nil { return nil, err } h.fd = fd if h.opts.iface != "" { if err = h.bindToInterface(h.opts.iface); err != nil { goto errlbl } } if err = h.setRequestedTPacketVersion(); err != nil { goto errlbl } if err = h.setUpRing(); err != nil { goto errlbl } // Clear stat counter from socket if err = h.InitSocketStats(); err != nil { goto errlbl } runtime.SetFinalizer(h, (*TPacket).Close) return h, nil errlbl: h.Close() return nil, err }
// bindToInterface binds the TPacket socket to a particular named interface. func (h *TPacket) bindToInterface(ifaceName string) error { iface, err := net.InterfaceByName(ifaceName) if err != nil { return fmt.Errorf("InterfaceByName: %v", err) } var ll C.struct_sockaddr_ll ll.sll_family = C.AF_PACKET ll.sll_protocol = C.__be16(C.htons(C.ETH_P_ALL)) ll.sll_ifindex = C.int(iface.Index) if _, err := C.bind(h.fd, (*C.struct_sockaddr)(unsafe.Pointer(&ll)), C.socklen_t(unsafe.Sizeof(ll))); err != nil { return fmt.Errorf("bindToInterface: %v", err) } return nil }