func main() { sk := nlgo.NlSocketAlloc() if err := nlgo.GenlConnect(sk); err != nil { panic(err) } else if err := nlgo.GenlSendSimple(sk, nlgo.GENL_ID_CTRL, nlgo.CTRL_CMD_GETFAMILY, nlgo.CTRL_VERSION, syscall.NLM_F_DUMP); err != nil { panic(err) } nl80211 := nlgo.NlSocketAlloc() if err := nlgo.GenlConnect(nl80211); err != nil { panic(err) } data := make([]byte, syscall.Getpagesize()) if n, _, _, _, err := syscall.Recvmsg(sk.Fd, data, nil, 0); err != nil { panic(err) } else if msgs, err := syscall.ParseNetlinkMessage(data[:n]); err != nil { log.Print("X", err) } else { for _, msg := range msgs { genl := *(*nlgo.GenlMsghdr)(unsafe.Pointer(&msg.Data[0])) if msg.Header.Type == nlgo.GENL_ID_CTRL && genl.Cmd == nlgo.CTRL_CMD_NEWFAMILY { if attr, err := nlgo.CtrlPolicy.Parse(msg.Data[nlgo.GENL_HDRLEN:]); err != nil { log.Print(err) } else if amap, ok := attr.(nlgo.AttrMap); !ok { log.Print(attr) } else if value := amap.Get(nlgo.CTRL_ATTR_FAMILY_NAME).(nlgo.NulString); string(value) == "nl80211" { log.Printf("%v", attr) for _, g := range amap.Get(nlgo.CTRL_ATTR_MCAST_GROUPS).(nlgo.AttrSlice).Slice() { group := g.Value.(nlgo.AttrMap) pid := group.Get(nlgo.CTRL_ATTR_MCAST_GRP_ID).(nlgo.U32) if err := nlgo.NlSocketAddMembership(nl80211, int(pid)); err != nil { log.Print(err) } } } } else { log.Print("UNKNOWN") } } } nlgo.NlSocketFree(sk) for { if n, _, _, _, err := syscall.Recvmsg(nl80211.Fd, data, nil, 0); err != nil { panic(err) } else if msgs, err := syscall.ParseNetlinkMessage(data[:n]); err != nil { log.Print("Y", err) } else { for _, msg := range msgs { genl := (*nlgo.GenlMsghdr)(unsafe.Pointer(&msg.Data[0])) if attr, err := nlgo.Nl80211Policy.Parse(msg.Data[nlgo.GENL_HDRLEN:]); err != nil { log.Print("Z", err) } else { log.Printf("NL80211_CMD_%s attrs=%s", nlgo.NL80211_CMD_itoa[genl.Cmd], attr) } } } } }
func getConnection(local *os.File) (int, error) { var data [4]byte control := make([]byte, 4*256) // n, oobn, recvflags, from, errno - todo: error checking. _, oobn, _, _, err := syscall.Recvmsg( int(local.Fd()), data[:], control[:], 0) if err != nil { return 0, err } message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0])) fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr)) if message.Type != 1 { return 0, fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type) } if oobn <= syscall.SizeofCmsghdr { return 0, fmt.Errorf("getConnection: too short control message. Length: %d", oobn) } if fd < 0 { return 0, fmt.Errorf("getConnection: fd < 0: %d", fd) } return int(fd), nil }
func getFuseConn(local *os.File) (f *os.File, err os.Error) { var data [4]byte control := make([]byte, 4*256) // n, oobn, recvflags, from, errno - todo: error checking. _, oobn, _, _, errno := syscall.Recvmsg( local.Fd(), data[:], control[:], 0) if errno != 0 { return } message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0])) fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr)) if message.Type != 1 { err = os.NewError(fmt.Sprintf("getFuseConn: recvmsg returned wrong control type: %d", message.Type)) return } if oobn <= syscall.SizeofCmsghdr { err = os.NewError(fmt.Sprintf("getFuseConn: too short control message. Length: %d", oobn)) return } if fd < 0 { err = os.NewError(fmt.Sprintf("getFuseConn: fd < 0: %d", fd)) return } f = os.NewFile(int(fd), "<fuseConnection>") return }
func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { if err := fd.readLock(); err != nil { return 0, 0, 0, nil, err } defer fd.readUnlock() if err := fd.pd.prepareRead(); err != nil { return 0, 0, 0, nil, err } for { n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) if err != nil { // TODO(dfc) should n and oobn be set to 0 if err == syscall.EAGAIN { if err = fd.pd.waitRead(); err == nil { continue } } } err = fd.eofError(n, err) break } if _, ok := err.(syscall.Errno); ok { err = os.NewSyscallError("recvmsg", err) } return }
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { fd.rio.Lock() defer fd.rio.Unlock() if err := fd.incref(false); err != nil { return 0, 0, 0, nil, err } defer fd.decref() for { if fd.rdeadline.expired() { err = errTimeout break } n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) if err != nil { // TODO(dfc) should n and oobn be set to 0 if err == syscall.EAGAIN { if err = fd.pollServer.WaitRead(fd); err == nil { continue } } } err = chkReadErr(n, err, fd) break } if err != nil && err != io.EOF { err = &OpError{"read", fd.net, fd.laddr, err} } return }
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { fd.rio.Lock() defer fd.rio.Unlock() if err := fd.incref(false); err != nil { return 0, 0, 0, nil, err } defer fd.decref() for { n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) if err == syscall.EAGAIN { err = errTimeout if fd.rdeadline >= 0 { if err = fd.pollServer.WaitRead(fd); err == nil { continue } } } if err == nil && n == 0 { err = io.EOF } break } if err != nil && err != io.EOF { err = &OpError{"read", fd.net, fd.laddr, err} return } return }
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { if fd == nil || fd.sysfile == nil { return 0, 0, 0, nil, os.EINVAL } fd.rio.Lock() defer fd.rio.Unlock() fd.incref() defer fd.decref() if fd.rdeadline_delta > 0 { fd.rdeadline = pollserver.Now() + fd.rdeadline_delta } else { fd.rdeadline = 0 } var oserr error for { var errno int n, oobn, flags, sa, errno = syscall.Recvmsg(fd.sysfd, p, oob, 0) if errno == syscall.EAGAIN && fd.rdeadline >= 0 { pollserver.WaitRead(fd) continue } if errno != 0 { oserr = os.Errno(errno) } if n == 0 { oserr = io.EOF } break } if oserr != nil { err = &OpError{"read", fd.net, fd.laddr, oserr} return } return }
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { if fd == nil || fd.sysfile == nil { return 0, 0, 0, nil, os.EINVAL } fd.rio.Lock() defer fd.rio.Unlock() fd.incref() defer fd.decref() for { n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) if err == syscall.EAGAIN { if fd.rdeadline >= 0 { pollserver.WaitRead(fd) continue } err = errTimeout } if err == nil && n == 0 { err = io.EOF } break } if err != nil && err != io.EOF { err = &OpError{"read", fd.net, fd.laddr, err} return } return }
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { if err := fd.readLock(); err != nil { return 0, 0, 0, nil, err } defer fd.readUnlock() if err := fd.pd.PrepareRead(); err != nil { return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err} } for { n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) if err != nil { // TODO(dfc) should n and oobn be set to 0 if err == syscall.EAGAIN { if err = fd.pd.WaitRead(); err == nil { continue } } } err = chkReadErr(n, err, fd) break } if err != nil && err != io.EOF { err = &OpError{"read", fd.net, fd.laddr, err} } return }
func readMsg(file *os.File, p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { for { n, oobn, flags, sa, err = syscall.Recvmsg(int(file.Fd()), p, oob, 0) if err != nil { if err == syscall.EAGAIN { continue } } break } return }
func pfkeyReply() (spi uint32, err error) { buf := make([]byte, SADB_MSG_SIZE) if count, _, _, _, _ := syscall.Recvmsg(fd, buf, nil, syscall.MSG_PEEK); count != len(buf) { return spi, fmt.Errorf("incomplete sadbmsg %d %d", len(buf), count) } h := sadbMsg{} h.DecodeFromBytes(buf) if h.sadbMsgErrno != 0 { return spi, fmt.Errorf("sadb msg reply error %d", h.sadbMsgErrno) } if h.sadbMsgSeq != seq { return spi, fmt.Errorf("sadb msg sequence doesn't match %d %d", h.sadbMsgSeq, seq) } if h.sadbMsgPid != uint32(os.Getpid()) { return spi, fmt.Errorf("sadb msg pid doesn't match %d %d", h.sadbMsgPid, os.Getpid()) } buf = make([]byte, int(8*h.sadbMsgLen)) if count, _, _, _, _ := syscall.Recvmsg(fd, buf, nil, 0); count != len(buf) { return spi, fmt.Errorf("incomplete sadbmsg body %d %d", len(buf), count) } buf = buf[SADB_MSG_SIZE:] for len(buf) >= 4 { l := binary.LittleEndian.Uint16(buf[0:2]) * 8 t := binary.LittleEndian.Uint16(buf[2:4]) if t == SADB_EXT_SA { return binary.LittleEndian.Uint32(buf[4:8]), nil } if len(buf) <= int(l) { break } buf = buf[l:] } return spi, err }
// Get receives file descriptors from a Unix domain socket. // // Num specifies the expected number of file descriptors in one message. // Internal files' names to be assigned are specified via optional filenames // argument. // // You need to close all files in the returned slice. The slice can be // non-empty even if this function returns an error. // // Use net.FileConn() if you're receiving a network connection. func Get(via *net.UnixConn, num int, filenames []string) ([]*os.File, error) { if num < 1 { return nil, nil } // get the underlying socket viaf, err := via.File() if err != nil { return nil, err } socket := int(viaf.Fd()) defer viaf.Close() // recvmsg buf := make([]byte, syscall.CmsgSpace(num*4)) _, _, _, _, err = syscall.Recvmsg(socket, nil, buf, 0) if err != nil { return nil, err } // parse control msgs var msgs []syscall.SocketControlMessage msgs, err = syscall.ParseSocketControlMessage(buf) // convert fds to files res := make([]*os.File, 0, len(msgs)) for i := 0; i < len(msgs) && err == nil; i++ { var fds []int fds, err = syscall.ParseUnixRights(&msgs[i]) for fi, fd := range fds { var filename string if fi < len(filenames) { filename = filenames[fi] } res = append(res, os.NewFile(uintptr(fd), filename)) } } return res, err }
func handleConnection(c net.Conn, patterns []matcher) { var err error var d net.Conn buf := make([]byte, 4096, 4096) oobbuf := make([]byte, 512, 512) defer c.Close() conn := c.(*net.TCPConn) f, _ := conn.File() length, _, _, from, err := syscall.Recvmsg(int(f.Fd()), buf, oobbuf, syscall.MSG_PEEK) if err != nil { fmt.Println(from, err) return } f.Close() for n := 0; ; n += 1 { var host string var port int if len(patterns) == n { fmt.Println(c.RemoteAddr, "Protocol not recognized") return } host, port = patterns[n](buf, length) if port > 0 { d, err = net.Dial("tcp", fmt.Sprint(host, ":", port)) break } } if err != nil { fmt.Println(c.RemoteAddr, err) return } go copyAndClose(c, d) io.Copy(d, c) }
func Receive(fd int) (int, os.Error) { cmsglen := cmsgLen(int(unsafe.Sizeof(fd))) buf := make([]byte, cmsglen) _, _, _, _, errno := syscall.Recvmsg(fd, nil, buf, 0) if errno != 0 { return -1, fmt.Errorf("fdpass: Receive: %v", os.Errno(errno)) } cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&buf[0])) if uint64(cmsg.Len) != uint64(cmsglen) { return -1, fmt.Errorf("fdpass: Receive: bad length %v", cmsg.Len) } if cmsg.Level != syscall.SOL_SOCKET { return -1, fmt.Errorf("fdpass: Receive: bad level %v", cmsg.Level) } if cmsg.Type != syscall.SCM_RIGHTS { return -1, fmt.Errorf("fdpass: Receive: bad type %v", cmsg.Type) } sendfd := *(*int)(unsafe.Pointer(&buf[cmsgLen(0)])) return sendfd, nil }
// Up activates packet processing. // When the interface is down(IFF_UP is unset), opening the socket raise error. // This is because we have to call Up each time the state changed. func (self *NamedPort) Up() error { self.lock.Lock() defer self.lock.Unlock() if self.fd != -1 { return nil // already up } if self.flags&syscall.IFF_UP == 0 { return nil // not ready for up } if fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, 0); err != nil { panic(err) } else { self.fd = fd } if err := func() error { if err := syscall.SetsockoptInt(self.fd, syscall.SOL_PACKET, syscall2.PACKET_AUXDATA, 1); err != nil { return err } if err := syscall.Bind(self.fd, &syscall.SockaddrLinklayer{ Protocol: syscall2.ETH_P_ALL, Ifindex: int(self.ifIndex), }); err != nil { return err } if sa, err := syscall.Getsockname(self.fd); err != nil { return err } else { self.hatype = sa.(*syscall.SockaddrLinklayer).Hatype switch self.hatype { default: panic("unsupported ARPHRD") case syscall.ARPHRD_IEEE80211_RADIOTAP: // ok case syscall.ARPHRD_ETHER: // ok case syscall2.ARPHRD_6LOWPAN: // ok } } return nil }(); err != nil { self.Down() return err } go func() { defer self.Down() buf := make([]byte, 32*1024) // enough for jumbo frame oob := make([]byte, syscall.CmsgSpace(20)) // msg_control, 20 = sizeof(auxdata) for { var frame Frame if bufN, oobN, flags, _, err := syscall.Recvmsg(self.fd, buf, oob, syscall.MSG_TRUNC); err != nil { if e, ok := err.(syscall.Errno); ok && e.Temporary() { continue } else { log.Print("Recvmsg", err) break } } else if bufN == 0 { break } else if bufN > len(buf) { log.Print("MSG_TRUNC") } else if flags&syscall.MSG_CTRUNC != 0 { log.Print("MSG_CTRUNC") } else { haveVlan := false var vlanTpid uint16 = 0x8100 var vlanTci uint16 if cmsgs, err := syscall.ParseSocketControlMessage(oob[:oobN]); err != nil { log.Print(err) return } else { for _, cmsg := range cmsgs { switch cmsg.Header.Type { case syscall2.PACKET_AUXDATA: aux := (*syscall2.Auxdata)(unsafe.Pointer(&cmsg.Data[0])) switch len(cmsg.Data) { case 20: if aux.Status&syscall2.TP_STATUS_VLAN_TPID_VALID != 0 { vlanTpid = aux.VlanTpid } case 18: // old format. pass default: log.Print("unexpected PACKET_AUXDATA") return } if aux.Status&syscall2.TP_STATUS_VLAN_VALID != 0 { haveVlan = true vlanTci = aux.VlanTci } } } } switch self.hatype { case syscall.ARPHRD_ETHER: var pkt []byte if haveVlan { pkt = make([]byte, bufN+4) copy(pkt[:12], buf[:12]) binary.BigEndian.PutUint16(pkt[12:], vlanTpid) binary.BigEndian.PutUint16(pkt[14:], vlanTci) copy(pkt[16:], buf[12:bufN]) } else { pkt = make([]byte, bufN) copy(pkt, buf) } frame = Frame{ Data: pkt, } case syscall.ARPHRD_IEEE80211_RADIOTAP: // NOTE: 802.11 + PACKET_AUXDATA unsupported bpkt := gopacket.NewPacket(buf[:bufN], layers.LayerTypeRadioTap, gopacket.Lazy) if rtl := bpkt.Layer(layers.LayerTypeRadioTap); rtl == nil { log.Print("radiotap layer error") } else if rt, ok := rtl.(*layers.RadioTap); !ok { log.Print("radiotap layer type error") } else { if f, err := FrameFromRadiotap(rt); err != nil { log.Print(err) } else { frame = f } } case syscall2.ARPHRD_6LOWPAN: pkt := make([]byte, 14+bufN) binary.BigEndian.PutUint16(pkt[12:], 0x86DD) copy(pkt[14:], buf[:bufN]) bpkt := gopacket.NewPacket(buf[:bufN], layers.LayerTypeIPv6, gopacket.Lazy) ip6 := bpkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6) if ip6.DstIP.IsMulticast() { copy(pkt, []byte{0x33, 0x33}) copy(pkt[2:6], []byte(ip6.DstIP.To16())[12:16]) copy(pkt[6:], self.get6lowpanMac(ip6.SrcIP)) } else { copy(pkt[6:], self.get6lowpanMac(ip6.SrcIP)) copy(pkt, self.get6lowpanMac(ip6.DstIP)) } frame = Frame{ Data: pkt, } } if len(frame.Data) != 0 { func() { defer func() { if r := recover(); r != nil { // this may happen in socket race condition(rtnetlink and pf_packet). fmt.Println("dropping packet on closed ingress.") } }() self.ingress <- frame }() } } } }() return nil }
func NewRtHub() (*RtHub, error) { self := &RtHub{ sock: NlSocketAlloc(), lock: &sync.Mutex{}, unicast: make(map[uint32]chan RtMessage), multicast: make(map[uint32][]RtListener), } if err := NlConnect(self.sock, syscall.NETLINK_ROUTE); err != nil { NlSocketFree(self.sock) return nil, err } go func() { for { var merr error var messages []syscall.NetlinkMessage var controls []syscall.SocketControlMessage buf := make([]byte, syscall.Getpagesize()) oob := make([]byte, syscall.Getpagesize()) if bufN, oobN, _, _, err := syscall.Recvmsg(self.sock.Fd, buf, oob, syscall.MSG_TRUNC); err != nil { if e, ok := err.(syscall.Errno); ok && e.Temporary() { continue } merr = err } else if bufN == 0 { break } else if bufN > len(buf) { merr = err } else if oobN > len(oob) { merr = err } else if msgs, err := syscall.ParseNetlinkMessage(buf[:bufN]); err != nil { merr = err } else if ctrls, err := syscall.ParseSocketControlMessage(oob[:oobN]); err != nil { merr = err } else { messages = msgs controls = ctrls } for _, message := range messages { msg := RtMessage{ Message: message, Controls: controls, Error: merr, } seq := message.Header.Seq mtype := message.Header.Type if seq == 0 { var listeners []RtListener self.lock.Lock() for _, s := range self.multicast { listeners = append(listeners, s...) } self.lock.Unlock() for _, listener := range listeners { listener.RtListen(msg) } } else { self.lock.Lock() listener := self.unicast[seq] self.lock.Unlock() if listener != nil { listener <- msg if mtype == syscall.NLMSG_DONE || mtype == syscall.NLMSG_ERROR { delete(self.unicast, seq) close(listener) } } } } } }() return self, nil }
func (self HciDev) Request(opcode OpCode, params ...Parameter) (Parameters, error) { req := make([]byte, 4) req[0] = HCI_COMMAND_PKT binary.LittleEndian.PutUint16(req[1:], uint16(opcode)) if pbuf, err := Parameters(params).MarshalBinary(); err != nil { return nil, err } else { req[3] = uint8(len(pbuf)) req = append(req, pbuf...) } if filter, err := GetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER); err != nil { return nil, err } else { defer SetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER, filter) } filter := &HciFilter{ Type_mask: 1 << HCI_EVENT_PKT, Event_mask: FilterEventMask(EVT_CMD_STATUS, EVT_CMD_COMPLETE), Opcode: opcode.Native(), } if opcode.Ogf() == OGF_LE_CTL { filter.Event_mask = FilterEventMask(EVT_CMD_STATUS, EVT_CMD_COMPLETE, EVT_LE_META_EVENT) } if err := SetsockoptHciFilter(int(self), SOL_HCI, HCI_FILTER, filter); err != nil { return nil, err } if n, err := self.Write(req); err != nil { return nil, err } else if n != len(req) { return nil, fmt.Errorf("write incomplete") } if efd, err := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil { return nil, err } else { defer syscall.Close(efd) var events [1]syscall.EpollEvent syscall.EpollCtl(efd, syscall.EPOLL_CTL_ADD, int(self), &syscall.EpollEvent{ Events: syscall.EPOLLIN, Fd: int32(self), }) capture := make([]byte, 0, 258) buf := make([]byte, 258) for { if n, err := syscall.EpollWait(efd, events[:], 100); err != nil { return nil, err } else if n == 0 { continue } // todo: operation timeout if n, _, _, _, err := syscall.Recvmsg(int(self), buf, nil, syscall.MSG_DONTWAIT); err != nil { if errno, ok := err.(syscall.Errno); ok && errno.Temporary() { continue } return nil, err } else if n == 0 { continue } else { capture = append(capture, buf[:n]...) } if pkt, step := Parse(capture); step == 0 { continue } else if p, err := pkt.(EventPkt).Parse(); err != nil { continue } else { switch ev := p.(type) { case EvtCmdComplete: if ev.OpCode == uint16(opcode) { return opcode.Response(ev.Params) } case EvtCmdStatus: if ev.OpCode == uint16(opcode) && ev.Status != 0 { return nil, HciError(ev.Status) } case EvtLeMetaEvent: // todo: OGF_LE_CTL opcode expects this } capture = capture[step:] } } return nil, fmt.Errorf("should not reach") } }