Example #1
1
File: main.go Project: qmsk/nlgo
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)
				}
			}
		}
	}
}
Example #2
0
func getDefaultRoute() (*syscall.NetlinkMessage, error) {
	dat, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
	if err != nil {
		return nil, err
	}

	msgs, msgErr := syscall.ParseNetlinkMessage(dat)
	if msgErr != nil {
		return nil, msgErr
	}

	rtmsg := syscall.RtMsg{}
	for _, m := range msgs {
		if m.Header.Type != syscall.RTM_NEWROUTE {
			continue
		}
		buf := bytes.NewBuffer(m.Data[:syscall.SizeofRtMsg])
		if rerr := binary.Read(buf, binary.LittleEndian, &rtmsg); rerr != nil {
			continue
		}
		if rtmsg.Dst_len == 0 {
			// zero-length Dst_len implies default route
			return &m, nil
		}
	}

	return nil, errNoDefaultRoute
}
Example #3
0
func TestParseNetlinkMessage(t *testing.T) {
	for i, b := range [][]byte{
		{103, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 5, 8, 0, 3,
			0, 8, 0, 6, 0, 0, 0, 0, 1, 63, 0, 10, 0, 69, 16, 0, 59, 39, 82, 64, 0, 64, 6, 21, 89, 127, 0, 0,
			1, 127, 0, 0, 1, 230, 228, 31, 144, 32, 186, 155, 211, 185, 151, 209, 179, 128, 24, 1, 86,
			53, 119, 0, 0, 1, 1, 8, 10, 0, 17, 234, 12, 0, 17, 189, 126, 107, 106, 108, 107, 106, 13, 10,
		},
		{106, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 3, 8, 0, 3,
			0, 8, 0, 6, 0, 0, 0, 0, 1, 66, 0, 10, 0, 69, 0, 0, 62, 230, 255, 64, 0, 64, 6, 85, 184, 127, 0, 0,
			1, 127, 0, 0, 1, 237, 206, 31, 144, 73, 197, 128, 65, 250, 60, 192, 97, 128, 24, 1, 86, 253, 21, 0,
			0, 1, 1, 8, 10, 0, 51, 106, 89, 0, 51, 102, 198, 108, 104, 106, 108, 107, 104, 108, 107, 104, 10,
		},
		{102, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 1, 8, 0, 3, 0,
			8, 0, 6, 0, 0, 0, 0, 1, 62, 0, 10, 0, 69, 0, 0, 58, 231, 2, 64, 0, 64, 6, 85, 185, 127, 0, 0, 1, 127,
			0, 0, 1, 237, 206, 31, 144, 73, 197, 128, 86, 250, 60, 192, 97, 128, 24, 1, 86, 104, 64, 0, 0, 1, 1, 8,
			10, 0, 52, 198, 200, 0, 51, 135, 232, 101, 115, 97, 103, 103, 10,
		},
	} {
		m, err := syscall.ParseNetlinkMessage(b)
		if err != syscall.EINVAL {
			t.Errorf("#%d: got %v; want EINVAL", i, err)
		}
		if m != nil {
			t.Errorf("#%d: got %v; want nil", i, m)
		}
	}
}
Example #4
0
// getNeighbors sends a request to netlink to retrieve all neighbors using
// the specified address family.
func getNeighbors(family Family) ([]*Neighbor, error) {
	// Request neighbors belonging to a specific family from netlink
	tab, err := syscall.NetlinkRIB(syscall.RTM_GETNEIGH, int(family))
	if err != nil {
		return nil, os.NewSyscallError("netlink rib", err)
	}

	// Parse netlink information into individual messages
	msgs, err := syscall.ParseNetlinkMessage(tab)
	if err != nil {
		return nil, os.NewSyscallError("netlink message", err)
	}

	// Check messages for information
	var nn []*Neighbor
	for _, m := range msgs {
		// Ignore any messages which don't indicate a new neighbor
		if m.Header.Type != syscall.RTM_NEWNEIGH {
			continue
		}

		// Attempt to parse an individual neighbor from a message
		n, err := newNeighbor(&m)
		if err != nil {
			return nil, err
		}

		nn = append(nn, n)
	}

	return nn, nil
}
Example #5
0
func getIface(idx uint32) (*syscall.NetlinkMessage, error) {
	dat, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
	if err != nil {
		return nil, err
	}

	msgs, msgErr := syscall.ParseNetlinkMessage(dat)
	if msgErr != nil {
		return nil, msgErr
	}

	ifaddrmsg := syscall.IfAddrmsg{}
	for _, m := range msgs {
		if m.Header.Type != syscall.RTM_NEWADDR {
			continue
		}
		buf := bytes.NewBuffer(m.Data[:syscall.SizeofIfAddrmsg])
		if rerr := binary.Read(buf, binary.LittleEndian, &ifaddrmsg); rerr != nil {
			continue
		}
		if ifaddrmsg.Index == idx {
			return &m, nil
		}
	}

	return nil, errNoDefaultRoute
}
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces.  Otherwise it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) { // 如果ifindex为0,返回所有网络接口
	tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC) // 获得netlink rib
	if err != nil {
		return nil, os.NewSyscallError("netlinkrib", err)
	}
	msgs, err := syscall.ParseNetlinkMessage(tab) // 解析netlink信息
	if err != nil {
		return nil, os.NewSyscallError("parsenetlinkmessage", err)
	}
	var ift []Interface
loop:
	for _, m := range msgs { // 遍历获取的netlink信息
		switch m.Header.Type {
		case syscall.NLMSG_DONE:
			break loop
		case syscall.RTM_NEWLINK:
			ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
			if ifindex == 0 || ifindex == int(ifim.Index) {
				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
				if err != nil {
					return nil, os.NewSyscallError("parsenetlinkrouteattr", err)
				}
				ift = append(ift, *newLink(ifim, attrs)) // 加入到Interface Slice中
				if ifindex == int(ifim.Index) {
					break loop
				}
			}
		}
	}
	return ift, nil
}
Example #7
0
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces.  Otheriwse it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
	tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
	if err != nil {
		return nil, os.NewSyscallError("netlink rib", err)
	}

	msgs, err := syscall.ParseNetlinkMessage(tab)
	if err != nil {
		return nil, os.NewSyscallError("netlink message", err)
	}

	var ift []Interface
	for _, m := range msgs {
		switch m.Header.Type {
		case syscall.NLMSG_DONE:
			goto done
		case syscall.RTM_NEWLINK:
			ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
			if ifindex == 0 || ifindex == int(ifim.Index) {
				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
				if err != nil {
					return nil, os.NewSyscallError("netlink routeattr", err)
				}
				ifi := newLink(ifim, attrs)
				ift = append(ift, ifi)
			}
		}
	}
done:
	return ift, nil
}
Example #8
0
func (w *Watcher) readAllEvents() {
	buf := make([]byte, syscall.Getpagesize())

	listener, _ := w.listener.(*netlinkListener)

	for {
		if w.isDone() {
			return
		}

		nr, _, err := syscall.Recvfrom(listener.sock, buf, 0)

		if err != nil {
			w.Error <- err
			continue
		}
		if nr < syscall.NLMSG_HDRLEN {
			w.Error <- syscall.EINVAL
			continue
		}

		msgs, _ := syscall.ParseNetlinkMessage(buf[:nr])

		for _, m := range msgs {
			if m.Header.Type == syscall.NLMSG_DONE {
				w.handleEventAll(m.Data)
			}
		}
	}
}
Example #9
0
// If the ifindex is zero, interfaceAddrTable returns addresses
// for all network interfaces.  Otherwise it returns addresses
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
	var (
		tab  []byte
		e    int
		err  os.Error
		ifat []Addr
		msgs []syscall.NetlinkMessage
	)

	tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
	if e != 0 {
		return nil, os.NewSyscallError("netlink rib", e)
	}

	msgs, e = syscall.ParseNetlinkMessage(tab)
	if e != 0 {
		return nil, os.NewSyscallError("netlink message", e)
	}

	ifat, err = addrTable(msgs, ifindex)
	if err != nil {
		return nil, err
	}

	return ifat, nil
}
Example #10
0
func (nl *NetlinkSocket) RecvMessages(sz, sockflags int) ([]NetlinkMessage, error) {
	buf := make([]byte, sz)

	rsz, _, err := syscall.Recvfrom(nl.sfd, buf, sockflags)
	if err != nil {
		return nil, err
	}

	if rsz < syscall.NLMSG_HDRLEN {
		return nil, syscall.EINVAL
	}

	msgList, err := syscall.ParseNetlinkMessage(buf[:rsz])
	if err != nil {
		return nil, err
	}

	ret := []NetlinkMessage{}

	for _, msg := range msgList {
		msg := NetlinkMessage(msg)
		logf("received: %+v\n", msg)
		ret = append(ret, msg)
	}

	return ret, nil
}
Example #11
0
func TestSocketPacketConn(t *testing.T) {
	s, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_ROUTE)
	if err != nil {
		t.Fatal(err)
	}
	lsa := syscall.SockaddrNetlink{Family: syscall.AF_NETLINK}
	if err := syscall.Bind(s, &lsa); err != nil {
		syscall.Close(s)
		t.Fatal(err)
	}
	f := os.NewFile(uintptr(s), "netlink")
	c, err := SocketPacketConn(f, &netlinkAddr{})
	f.Close()
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	const N = 3
	var wg sync.WaitGroup
	wg.Add(2 * N)
	dst := &netlinkAddr{PID: 0}
	for i := 0; i < N; i++ {
		go func() {
			defer wg.Done()
			l := syscall.NLMSG_HDRLEN + syscall.SizeofRtGenmsg
			b := make([]byte, l)
			*(*uint32)(unsafe.Pointer(&b[0:4][0])) = uint32(l)
			*(*uint16)(unsafe.Pointer(&b[4:6][0])) = uint16(syscall.RTM_GETLINK)
			*(*uint16)(unsafe.Pointer(&b[6:8][0])) = uint16(syscall.NLM_F_DUMP | syscall.NLM_F_REQUEST)
			*(*uint32)(unsafe.Pointer(&b[8:12][0])) = uint32(1)
			*(*uint32)(unsafe.Pointer(&b[12:16][0])) = uint32(0)
			b[16] = byte(syscall.AF_UNSPEC)
			if _, err := c.WriteTo(b, dst); err != nil {
				t.Error(err)
				return
			}
		}()
	}
	for i := 0; i < N; i++ {
		go func() {
			defer wg.Done()
			b := make([]byte, os.Getpagesize())
			n, _, err := c.ReadFrom(b)
			if err != nil {
				t.Error(err)
				return
			}
			if _, err := syscall.ParseNetlinkMessage(b[:n]); err != nil {
				t.Error(err)
				return
			}
		}()
	}
	wg.Wait()
}
Example #12
0
func NewRtHub() (*RtHub, error) {
	self := &RtHub{
		sock:      NlSocketAlloc(),
		lock:      &sync.Mutex{},
		unilock:   &sync.Mutex{},
		multicast: make(map[uint32][]NetlinkListener),
	}
	if err := NlConnect(self.sock, syscall.NETLINK_ROUTE); err != nil {
		NlSocketFree(self.sock)
		return nil, err
	}
	go func() {
		for {
			buf := make([]byte, syscall.Getpagesize())
			if n, _, err := syscall.Recvfrom(self.sock.Fd, buf, syscall.MSG_TRUNC); err != nil {
				if e, ok := err.(syscall.Errno); ok && e.Temporary() {
					continue
				}
				break
			} else if msgs, err := syscall.ParseNetlinkMessage(buf[:n]); err != nil {
				break
			} else {
				for _, msg := range msgs {
					multi := func() []NetlinkListener {
						self.lock.Lock()
						defer self.lock.Unlock()

						var ret []NetlinkListener
						for _, s := range self.multicast {
							ret = append(ret, s...)
						}
						return ret
					}()
					if msg.Header.Seq == self.uniseq {
						if self.unicast != nil {
							self.unicast.NetlinkListen(msg)
						}
						switch msg.Header.Type {
						case syscall.NLMSG_DONE, syscall.NLMSG_ERROR:
							self.unilock.Unlock()
						}
					}
					if msg.Header.Seq == 0 {
						for _, proc := range multi {
							proc.NetlinkListen(msg)
						}
					}
				}
			}
		}
		log.Print("rt hub loop exit")
	}()
	return self, nil
}
Example #13
0
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
	rb := make([]byte, syscall.Getpagesize())
	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
	if err != nil {
		return nil, err
	}
	if nr < syscall.NLMSG_HDRLEN {
		return nil, ErrShortResponse
	}
	rb = rb[:nr]
	return syscall.ParseNetlinkMessage(rb)
}
Example #14
0
// If the ifindex is zero, interfaceAddrTable returns addresses
// for all network interfaces.  Otherwise it returns addresses
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
	var (
		tab   []byte
		e     int
		err   os.Error
		ifat4 []Addr
		ifat6 []Addr
		msgs4 []syscall.NetlinkMessage
		msgs6 []syscall.NetlinkMessage
	)

	tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET)
	if e != 0 {
		return nil, os.NewSyscallError("netlink rib", e)
	}
	msgs4, e = syscall.ParseNetlinkMessage(tab)
	if e != 0 {
		return nil, os.NewSyscallError("netlink message", e)
	}
	ifat4, err = addrTable(msgs4, ifindex)
	if err != nil {
		return nil, err
	}

	tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET6)
	if e != 0 {
		return nil, os.NewSyscallError("netlink rib", e)
	}
	msgs6, e = syscall.ParseNetlinkMessage(tab)
	if e != 0 {
		return nil, os.NewSyscallError("netlink message", e)
	}
	ifat6, err = addrTable(msgs6, ifindex)
	if err != nil {
		return nil, err
	}

	return append(ifat4, ifat6...), nil
}
Example #15
0
// genl_ctrl_probe_by_name is not exposed in the original libnl
func GenlCtrlProbeByName(sk *NlSock, name string) (AttrMap, error) {
	if err := GenlSendSimple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION, syscall.NLM_F_DUMP); err != nil {
		return AttrMap{}, err
	}
	var ret AttrMap
	err := func() error {
		for {
			buf := make([]byte, syscall.Getpagesize())
			if nn, _, err := syscall.Recvfrom(sk.Fd, buf, syscall.MSG_TRUNC); err != nil {
				return err
			} else if nn > len(buf) {
				return NLE_MSG_TRUNC
			} else {
				buf = buf[:nn]
			}
			if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil {
				return err
			} else {
				for _, msg := range msgs {
					switch msg.Header.Type {
					case GENL_ID_CTRL:
						genl := (*GenlMsghdr)(unsafe.Pointer(&msg.Data[0]))
						switch genl.Cmd {
						case CTRL_CMD_NEWFAMILY:
							if attrs, err := CtrlPolicy.Parse(msg.Data[GENL_HDRLEN:]); err != nil {
								return err
							} else if info, ok := attrs.(AttrMap); !ok {
								// shold not happen
							} else if value := info.Get(CTRL_ATTR_FAMILY_NAME); value == nil {
								// should not happen by kernel
							} else if string(value.(NulString)) == name {
								ret = info
							}
						default:
							return fmt.Errorf("unexpected command")
						}
					case syscall.NLMSG_DONE:
						return nil
					case syscall.NLMSG_ERROR:
						return fmt.Errorf("NlMsgerr=%s", (*syscall.NlMsgerr)(unsafe.Pointer(&msg.Data[0])))
					default:
						return fmt.Errorf("unexpected NlMsghdr=%s", msg.Header)
					}
				}
			}
		}
	}()
	return ret, err
}
Example #16
0
// Receive receives one or more Messages from netlink.
func (c *conn) Receive() ([]Message, error) {
	b := make([]byte, os.Getpagesize())
	for {
		// Peek at the buffer to see how many bytes are available
		n, _, err := c.s.Recvfrom(b, syscall.MSG_PEEK)
		if err != nil {
			return nil, err
		}

		// Break when we can read all messages
		if n < len(b) {
			break
		}

		// Double in size if not enough bytes
		b = make([]byte, len(b)*2)
	}

	// Read out all available messages
	n, from, err := c.s.Recvfrom(b, 0)
	if err != nil {
		return nil, err
	}

	addr, ok := from.(*syscall.SockaddrNetlink)
	if !ok {
		return nil, errInvalidSockaddr
	}
	if addr.Family != syscall.AF_NETLINK {
		return nil, errInvalidFamily
	}

	raw, err := syscall.ParseNetlinkMessage(b[:n])
	if err != nil {
		return nil, err
	}

	msgs := make([]Message, 0, len(raw))
	for _, r := range raw {
		m := Message{
			Header: sysToHeader(r.Header),
			Data:   r.Data,
		}

		msgs = append(msgs, m)
	}

	return msgs, nil
}
Example #17
0
// If the ifindex is zero, interfaceAddrTable returns addresses
// for all network interfaces.  Otherwise it returns addresses
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, error) {
	tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
	if err != nil {
		return nil, os.NewSyscallError("netlink rib", err)
	}
	msgs, err := syscall.ParseNetlinkMessage(tab)
	if err != nil {
		return nil, os.NewSyscallError("netlink message", err)
	}
	ifat, err := addrTable(msgs, ifindex)
	if err != nil {
		return nil, err
	}
	return ifat, nil
}
Example #18
0
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
	if s.fd < 0 {
		return nil, fmt.Errorf("Receive called on a closed socket")
	}
	rb := make([]byte, syscall.Getpagesize())
	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
	if err != nil {
		return nil, err
	}
	if nr < syscall.NLMSG_HDRLEN {
		return nil, fmt.Errorf("Got short response from netlink")
	}
	rb = rb[:nr]
	return syscall.ParseNetlinkMessage(rb)
}
Example #19
0
// This basic rtnetlink example lists up link interfaces.
func Example() {
	sock := NlSocketAlloc()
	defer NlSocketFree(sock)
	if err := NlConnect(sock, syscall.NETLINK_ROUTE); err != nil {
		panic(err)
	}
	req := make([]byte, NLMSG_ALIGN(syscall.SizeofIfInfomsg))
	if err := NlSendSimple(sock, syscall.RTM_GETLINK, syscall.NLM_F_DUMP, req); err != nil {
		panic(err)
	}
	func() {
		for {
			buf := make([]byte, syscall.Getpagesize())
			if nn, _, err := syscall.Recvfrom(sock.Fd, buf, syscall.MSG_TRUNC); err != nil {
				panic(err)
			} else if nn > len(buf) {
				panic("out of recv buf")
			} else {
				buf = buf[:nn]
			}
			if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil {
				panic(err)
			} else {
				for _, msg := range msgs {
					switch msg.Header.Type {
					case syscall.RTM_NEWLINK:
						ifinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&msg.Data[0]))
						if attrs, err := RouteLinkPolicy.Parse(msg.Data[NLA_ALIGN(syscall.SizeofIfInfomsg):]); err != nil {
							panic(err)
						} else {
							log.Print("ifinfomsg=", ifinfo, " attrs=", attrs)
						}
					case syscall.NLMSG_DONE:
						return
					default:
						log.Print("unhandled msg", msg.Header)
					}
				}
			}
		}
	}()
}
Example #20
0
// If the ifi is nil, interfaceAddrTable returns addresses for all
// network interfaces.  Otherwise it returns addresses for a specific
// interface.
func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
	tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
	if err != nil {
		return nil, os.NewSyscallError("netlinkrib", err)
	}
	msgs, err := syscall.ParseNetlinkMessage(tab)
	if err != nil {
		return nil, os.NewSyscallError("parsenetlinkmessage", err)
	}
	var ift []Interface
	if ifi == nil {
		var err error
		ift, err = interfaceTable(0)
		if err != nil {
			return nil, err
		}
	}
	ifat, err := addrTable(ift, ifi, msgs)
	if err != nil {
		return nil, err
	}
	return ifat, nil
}
Example #21
0
func find_gateway(ip_mask *net.IPNet) (ip net.IP, dev string, err error) {
	buf, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_INET)
	if err != nil {
		log.Println("Failed to open netlink:", err)
		return
	}
	msgs, err := syscall.ParseNetlinkMessage(buf)
	if err != nil {
		log.Println("Failed to parse nl msg:", err)
		return
	}
	var def route
	set := false
	var once sync.Once
loop:
	for _, m := range msgs {
		switch m.Header.Type {
		case syscall.NLMSG_DONE:
			break loop
		case syscall.RTM_NEWROUTE:
			// a route enrty
			var r route
			rtmsg := (*syscall.RtMsg)(unsafe.Pointer(&m.Data[0]))
			attrs, err := syscall.ParseNetlinkRouteAttr(&m)
			if err != nil {
				// err is shadowed
				log.Println("Failed to parse nl rtattr:", err)
				return ip, dev, err
			}
			// parse a route entry
			for _, a := range attrs {
				switch a.Attr.Type {
				case syscall.RTA_DST:
					addr := a.Value
					_, r.dst, err = net.ParseCIDR(fmt.Sprintf("%d.%d.%d.%d/%d", addr[0], addr[1], addr[2], addr[3], rtmsg.Dst_len))
					if err != nil {
						log.Println("Failed to parse ip addr:", err)
						return ip, dev, err
					}
				case syscall.RTA_GATEWAY:
					addr := a.Value
					r.gateway = net.IPv4(addr[0], addr[1], addr[2], addr[3])
				case syscall.RTA_OIF:
					r.if_index = int(a.Value[0])
				}
			}
			if r.dst == nil {
				once.Do(func() {
					def = r
					set = true
				})
			} else {
				if r.dst.Contains(ip_mask.IP) {
					ifce, err := net.InterfaceByIndex(r.if_index)
					if err != nil {
						log.Println("Failed to get interface by index:", err)
						return ip, dev, err
					}
					return r.gateway, ifce.Name, nil
				}

			}
		}
	}
	if set {
		ifce, err := net.InterfaceByIndex(def.if_index)
		if err != nil {
			log.Println("Failed to get interface by index:", err)
			return ip, dev, err
		}
		return def.gateway, ifce.Name, nil
	}
	err = fmt.Errorf("Route not found.")
	return
}
Example #22
0
// New creates a new router object.  The router returned by New currently does
// not update its routes after construction... care should be taken for
// long-running programs to call New() regularly to take into account any
// changes to the routing table which have occurred since the last New() call.
func New() (Router, error) {
	rtr := &router{}
	tab, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
	if err != nil {
		return nil, err
	}
	msgs, err := syscall.ParseNetlinkMessage(tab)
	if err != nil {
		return nil, err
	}
loop:
	for _, m := range msgs {
		switch m.Header.Type {
		case syscall.NLMSG_DONE:
			break loop
		case syscall.RTM_NEWROUTE:
			rt := (*routeInfoInMemory)(unsafe.Pointer(&m.Data[0]))
			routeInfo := rtInfo{}
			attrs, err := syscall.ParseNetlinkRouteAttr(&m)
			if err != nil {
				return nil, err
			}
			switch rt.Family {
			case syscall.AF_INET:
				rtr.v4 = append(rtr.v4, &routeInfo)
			case syscall.AF_INET6:
				rtr.v6 = append(rtr.v6, &routeInfo)
			default:
				continue loop
			}
			for _, attr := range attrs {
				switch attr.Attr.Type {
				case syscall.RTA_DST:
					routeInfo.Dst = &net.IPNet{
						IP:   net.IP(attr.Value),
						Mask: net.CIDRMask(int(rt.DstLen), len(attr.Value)*8),
					}
				case syscall.RTA_SRC:
					routeInfo.Src = &net.IPNet{
						IP:   net.IP(attr.Value),
						Mask: net.CIDRMask(int(rt.SrcLen), len(attr.Value)*8),
					}
				case syscall.RTA_GATEWAY:
					routeInfo.Gateway = net.IP(attr.Value)
				case syscall.RTA_PREFSRC:
					routeInfo.PrefSrc = net.IP(attr.Value)
				case syscall.RTA_IIF:
					routeInfo.InputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
				case syscall.RTA_OIF:
					routeInfo.OutputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
				case syscall.RTA_PRIORITY:
					routeInfo.Priority = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
				}
			}
		}
	}
	sort.Sort(rtr.v4)
	sort.Sort(rtr.v6)
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for i, iface := range ifaces {
		if i != iface.Index-1 {
			return nil, fmt.Errorf("out of order iface %d = %v", i, iface)
		}
		rtr.ifaces = append(rtr.ifaces, iface)
		var addrs ipAddrs
		ifaceAddrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range ifaceAddrs {
			if inet, ok := addr.(*net.IPNet); ok {
				// Go has a nasty habit of giving you IPv4s as ::ffff:1.2.3.4 instead of 1.2.3.4.
				// We want to use mapped v4 addresses as v4 preferred addresses, never as v6
				// preferred addresses.
				if v4 := inet.IP.To4(); v4 != nil {
					if addrs.v4 == nil {
						addrs.v4 = v4
					}
				} else if addrs.v6 == nil {
					addrs.v6 = inet.IP
				}
			}
		}
		rtr.addrs = append(rtr.addrs, addrs)
	}
	return rtr, nil
}
Example #23
0
func MonitorIP() {
	// Create a Unix socket to listen for NetLink changes
	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_ROUTE)
	if err != nil {
		fmt.Println("Error creating unix socket:", err)
		return
	}
	defer syscall.Close(fd)

	// Netlink options
	sn := syscall.SockaddrNetlink{
		Pid:    0,                                                  // Pid 0 == KERNEL messages
		Groups: syscall.RTNLGRP_LINK | syscall.RTNLGRP_IPV4_IFADDR, // Broadcast groups
	}

	// Bind to the Socket
	err = syscall.Bind(fd, &sn)
	if err != nil {
		fmt.Println("Binding fd to socket failed")
	}

	// Infinite loop to keep listening for changes
	buff := make([]byte, syscall.Getpagesize())
	for {
		n, _, err := syscall.Recvfrom(fd, buff, 0x00)

		if err != nil {
			fmt.Println("Error when receiving from the socket: ", err)
		}

		// Incorrect header length, ignore
		if n < syscall.NLMSG_HDRLEN {
			continue
		}

		msgs, err := syscall.ParseNetlinkMessage(buff[:n])
		if err != nil {
			fmt.Println("Parsing netlink message failed")
		}

		// Loop over parsed Netlink messages
		for _, msg := range msgs {

			if msg.Header.Type == syscall.NLMSG_ERROR {
				fmt.Println("Netlink message error!")
				continue
			}

			// Ignore multipart messages
			if msg.Header.Type == syscall.NLMSG_DONE {
				continue
			}

			// Ignore neighbor messages
			if msg.Header.Type == syscall.RTM_DELNEIGH || msg.Header.Type == syscall.RTM_NEWNEIGH {
				continue
			}

			fmt.Printf("RECEIVED : %+v \n", msg)

			if msg.Header.Type == syscall.RTM_NEWLINK {
				ifMsg := syscall.IfInfomsg{
					Family:     msg.Data[0], // AF_UNSPEC (always)
					X__ifi_pad: msg.Data[1], // Reserved
					Type:       binary.LittleEndian.Uint16(msg.Data[2:4]),
					Index:      int32(binary.LittleEndian.Uint32(msg.Data[4:8])),
					Flags:      binary.LittleEndian.Uint32(msg.Data[8:12]),
					Change:     binary.LittleEndian.Uint32(msg.Data[12:16]), // Reserved for future use
				}

				// Check if the interface is "administratively" up
				if ifMsg.Flags&syscall.IFF_UP == 0 {
					continue
				}

				// Check if the interface is operationally up
				if ifMsg.Flags&syscall.IFF_RUNNING == 0 {
					continue
				}

				//nlAttrs, _ := syscall.ParseNetlinkRouteAttr(&msg)
				iface, _ := net.InterfaceByIndex(int(ifMsg.Index))
				addrs, _ := iface.Addrs()

				//fmt.Printf("RTM_NEWLINK: %+v \n", ifMsg)
				//fmt.Printf("RTM_NEWLINK ATTRIBUTES: %+v \n", nlAttrs)
				//fmt.Printf("RTM_NEWLINK INTERFACE: %+v \n", iface)
				fmt.Printf("RTM_NEWLINK INTERFACE ADDRS: %+v \n", addrs)

				if len(addrs) > 0 {
					fmt.Printf("%s is now available at %s \n", iface.Name, addrs[0].(*net.IPNet).IP)
				} else {
					fmt.Printf("No address associated yet with %s \n", iface.Name)
				}
			} else {
				continue
			}

		}

	}
}
Example #24
0
func NewGenlHub() (*GenlHub, error) {
	self := &GenlHub{
		sock: NlSocketAlloc(),
		lock: &sync.Mutex{},
		familyIds: map[uint16]GenlFamily{
			GENL_ID_CTRL: GenlFamilyCtrl,
		},
		groupIds: map[uint32]GenlGroup{
			GENL_ID_CTRL: GenlGroup{
				Id:     GENL_ID_CTRL,
				Family: "nlctrl",
				Name:   "notify",
			},
		},
		unilock:   &sync.Mutex{},
		multicast: make(map[groupKey][]GenlListener),
	}
	if err := NlConnect(self.sock, syscall.NETLINK_GENERIC); err != nil {
		self.Close()
		return nil, err
	}
	if err := self.Add("nlctrl", "notify", self); err != nil {
		self.Close()
		return nil, err
	}
	if err := self.Async(GenlFamilyCtrl.DumpRequest(CTRL_CMD_GETFAMILY), self); err != nil {
		self.Close()
		return nil, err
	}
	go func() {
		for {
			buf := make([]byte, syscall.Getpagesize())
			if bufN, _, err := syscall.Recvfrom(self.sock.Fd, buf, syscall.MSG_TRUNC); err != nil {
				if e, ok := err.(syscall.Errno); ok && e.Temporary() {
					continue
				}
				break
			} else if msgs, err := syscall.ParseNetlinkMessage(buf[:bufN]); err != nil {
				break
			} else {
				for _, msg := range msgs {
					self.lock.Lock()
					family := self.familyIds[msg.Header.Type]
					var multi []GenlListener
					for gkey, s := range self.multicast {
						if family.Name == gkey.Family {
							for _, n := range s {
								if uniq := func() bool {
									for _, m := range multi {
										if m == n {
											return false
										}
									}
									return true
								}(); uniq {
									multi = append(multi, n)
								}
							}
						}
					}
					self.lock.Unlock()

					gmsg := GenlMessage{
						NetlinkMessage: msg,
						Family:         family,
					}
					if msg.Header.Seq == self.uniseq {
						if self.unicast != nil {
							self.unicast.GenlListen(gmsg)
						}
						switch msg.Header.Type {
						case syscall.NLMSG_DONE, syscall.NLMSG_ERROR:
							self.unilock.Unlock()
						}
					}
					if msg.Header.Seq == 0 {
						for _, proc := range multi {
							proc.GenlListen(gmsg)
						}
					}
				}
			}
		}
		log.Print("genl hub loop exit")
	}()
	return self, nil
}
Example #25
0
func GetTaskStats(nlsk *nlgo.NlSock, p int) (t *Taskstats) {
	nlsk.Flags |= nlgo.NL_NO_AUTO_ACK
	const familyID = 22
	m := &MSG{
		Len:  8,
		Type: TASKSTATS_CMD_ATTR_PID,
		Pid:  uint32(p),
	}

	hdr := (*[nlgo.SizeofGenlMsghdr]byte)(unsafe.Pointer(&nlgo.GenlMsghdr{
		Cmd:     TASKSTATS_CMD_GET,
		Version: 0,
	}))[:]
	req := ((*[8]byte)(unsafe.Pointer(m)))[:]
	length := 4
	pad := ((length + 4 - 1) & (^3)) - length
	for i := 0; i < pad; i++ {
		req = append(req, 0)
	}
	hdr = append(hdr, req...)
	nlgo.NlSendSimple(nlsk, familyID, 1, hdr[:])

	func() error {
		for {
			buf := make([]byte, 16384)
			if nn, _, err := syscall.Recvfrom(nlsk.Fd, buf, 0); err != nil {
				return err
			} else if nn > len(buf) {
				return nlgo.NLE_MSG_TRUNC
			} else {
				buf = buf[:nn]
			}
			if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil {
				return err
			} else {
				for _, msg := range msgs {

					switch msg.Header.Type {
					case syscall.NLMSG_DONE:
						return nil
					case syscall.NLMSG_ERROR:
						return fmt.Errorf("NlMsgerr=%s", nlgo.NlMsgerr(msg))
					case 22:
						genl := (*nlgo.GenlMsghdr)(unsafe.Pointer(&msg.Data[0]))
						_ = genl
						attrs := parse_attributes(msg.Data[nlgo.GENL_HDRLEN:])
						for _, attr := range attrs {
							if attr.Type == TASKSTATS_TYPE_AGGR_PID {
								attrs = parse_attributes(attr.Data)
								break
							}
						}
						for _, attr := range attrs {
							if attr.Type == TASKSTATS_TYPE_STATS {
								_ = uint32(*(*uint32)(unsafe.Pointer(&attr.Data[248])))
								t = (*Taskstats)(unsafe.Pointer(&attr.Data[0]))
								break
							}
						}
						return nil
					default:
						return fmt.Errorf("unexpected NlMsghdr=%s", msg.Header)
					}
				}
			}
		}
	}()
	//	if err != nil {
	//		fmt.Println(err, err.Error())
	//	}
	return
}
Example #26
0
// List all available routes on the system.
func Routes() ([]*Route, error) {
	var routes []*Route

	rib, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
	if err != nil {
		return nil, fmt.Errorf("Could not retrieve RIB: %s", err)
	}

	msgs, err := syscall.ParseNetlinkMessage(rib)
	if err != nil {
		return nil, fmt.Errorf("Could not parse messages: %s")
	}

	for _, m := range msgs {
		if m.Header.Type == syscall.NLMSG_DONE {
			break
		}

		if m.Header.Type != syscall.RTM_NEWROUTE {
			continue
		}

		route := &Route{Default: true}

		rtmsg := (*rtmsg)(unsafe.Pointer(&m.Data[0]))

		attrs, err := syscall.ParseNetlinkRouteAttr(&m)
		if err != nil {
			return nil, fmt.Errorf("Could not parse attr: %s", err)
		}

		for _, a := range attrs {
			switch a.Attr.Type {
			case syscall.RTA_SRC:
				route.SrcNet = &net.IPNet{
					IP: net.IP(a.Value),
					Mask: net.CIDRMask(
						int(rtmsg.src_len),
						len(a.Value)*8,
					),
				}

			case syscall.RTA_DST:
				route.DstNet = &net.IPNet{
					IP: net.IP(a.Value),
					Mask: net.CIDRMask(
						int(rtmsg.dst_len),
						len(a.Value)*8,
					),
				}

				route.Default = false

			case syscall.RTA_GATEWAY:
				route.Gateway = net.IP(a.Value)

			case syscall.RTA_OIF:
				oif := *(*uint32)(unsafe.Pointer(&a.Value[0]))
				iface, err := net.InterfaceByIndex(int(oif))
				if err != nil {
				}

				route.Iface = iface

			case syscall.RTA_PRIORITY:
			}
		}

		routes = append(routes, route)
	}

	return routes, nil
}
Example #27
0
func NewGenlHub() (*GenlHub, error) {
	self := &GenlHub{
		sock: NlSocketAlloc(),
		lock: &sync.Mutex{},
		familyIds: map[uint16]GenlFamily{
			GENL_ID_CTRL: GenlFamily{
				Id:      GENL_ID_CTRL,
				Name:    "nlctrl",
				Version: 1,
			},
		},
		groupIds: map[uint32]GenlGroup{
			GENL_ID_CTRL: GenlGroup{
				Id:     GENL_ID_CTRL,
				Family: "nlctrl",
				Name:   "notify",
			},
		},
		unicast:   make(map[uint32]chan GenlMessage),
		multicast: make(map[groupKey][]GenlListener),
	}
	if err := NlConnect(self.sock, syscall.NETLINK_GENERIC); err != nil {
		NlSocketFree(self.sock)
		return nil, err
	}
	go func() {
		feed := func(msg GenlMessage) {
			seq := msg.Header.Seq
			if seq == 0 { // multicast
				var listeners []GenlListener
				self.lock.Lock()
				if family, ok := self.familyIds[msg.Header.Type]; ok {
					for gkey, ls := range self.multicast {
						if gkey.Family == family.Name {
							for _, listener := range ls {
								if ok := func() bool { // remove duplicate
									for _, li := range listeners {
										if li == listener {
											return false
										}
									}
									return true
								}(); ok {
									listeners = append(listeners, listener)
								}
							}
						}
					}
				} else {
					log.Print("got unknown family message")
				}
				self.lock.Unlock()

				for _, listener := range listeners {
					listener.GenlListen(msg)
				}
			} else {
				self.lock.Lock()
				listener := self.unicast[seq]
				self.lock.Unlock()

				if listener != nil {
					listener <- msg
					mtype := msg.Header.Type
					if mtype == syscall.NLMSG_DONE || mtype == syscall.NLMSG_ERROR { // NlSock.Flags NL_NO_AUTO_ACK is 0 by default
						self.lock.Lock()
						delete(self.unicast, seq)
						self.lock.Unlock()

						close(listener)
					}
				}
			}
		}
		for {
			buf := make([]byte, syscall.Getpagesize())
			if bufN, _, err := syscall.Recvfrom(self.sock.Fd, buf, syscall.MSG_TRUNC); err != nil {
				if e, ok := err.(syscall.Errno); ok && e.Temporary() {
					continue
				}
				feed(GenlMessage{Error: err})
				return
			} else if bufN > len(buf) {
				feed(GenlMessage{Error: fmt.Errorf("msg trunc")})
				return
			} else if msgs, err := syscall.ParseNetlinkMessage(buf[:bufN]); err != nil {
				feed(GenlMessage{Error: err})
				return
			} else {
				for _, msg := range msgs {
					switch msg.Header.Type {
					default:
						feed(GenlMessage{
							Header:  msg.Header,
							Family:  self.familyIds[msg.Header.Type].Name,
							Genl:    (*GenlMsghdr)(unsafe.Pointer(&msg.Data[0])),
							Payload: msg.Data[GENL_HDRLEN:],
						})
					case syscall.NLMSG_ERROR:
						err := *(*syscall.NlMsgerr)(unsafe.Pointer(&msg.Data[0]))
						feed(GenlMessage{
							Header: msg.Header,
							Error:  MsgError{In: err},
						})
					case syscall.NLMSG_DONE:
						feed(GenlMessage{
							Header:  msg.Header,
							Genl:    nil,
							Payload: msg.Data,
						})
					}
				}
			}
		}
	}()

	self.Add("nlctrl", "notify", self)
	if res, err := self.Request("nlctrl", CTRL_VERSION, CTRL_CMD_GETFAMILY, syscall.NLM_F_DUMP, nil, nil); err != nil {
		return nil, err
	} else {
		for _, r := range res {
			self.GenlListen(r)
		}
	}
	return self, nil
}
Example #28
0
File: rt_hub.go Project: qmsk/nlgo
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
}