diff --git a/client.go b/client.go index 3c5630e..49bf8ba 100644 --- a/client.go +++ b/client.go @@ -1,5 +1,7 @@ package wifi +import "fmt" + // A Client is a type which can access WiFi device actions and statistics // using operating system-specific operations. type Client struct { @@ -43,6 +45,12 @@ func (c *Client) Interfaces() ([]*Interface, error) { return c.c.Interfaces() } +// InterfaceByName calls Interfaces() and returns one interface or nil +// if the requested interface doesn't exist. +func (c *Client) InterfaceByName(name string) (*Interface, error) { + return c.c.InterfaceByName(name) +} + // BSS retrieves the BSS associated with a WiFi interface. func (c *Client) BSS(ifi *Interface) (*BSS, error) { return c.c.BSS(ifi) @@ -52,3 +60,19 @@ func (c *Client) BSS(ifi *Interface) (*BSS, error) { func (c *Client) StationInfo(ifi *Interface) ([]*StationInfo, error) { return c.c.StationInfo(ifi) } + +// SetFrequency sets the frequency of a wireless interface. +func (c *Client) SetFrequency(ifi *Interface, freq int) error { + return c.c.SetFrequency(ifi, freq) +} + +//SetModeMonitor sets a wireless interface iftype to MONITOR. +func (c *Client) SetModeMonitor(ifi *Interface) error { + fmt.Printf("Setting monitor mode on interface %v\n", ifi) + return c.c.SetModeMonitor(ifi) +} + +//SetModeStation sets a wireless interface iftype to Station. +func (c *Client) SetModeStation(ifi *Interface) error { + return c.c.SetModeStation(ifi) +} \ No newline at end of file diff --git a/client_linux.go b/client_linux.go index 805d091..a518c58 100644 --- a/client_linux.go +++ b/client_linux.go @@ -10,7 +10,7 @@ import ( "os" "time" "unicode/utf8" - + "github.com/mdlayher/genetlink" "github.com/mdlayher/netlink" "github.com/mdlayher/netlink/nlenc" @@ -85,6 +85,18 @@ func (c *client) Interfaces() ([]*Interface, error) { return parseInterfaces(msgs) } +// InterfaceByName calls Interfaces() and returns one interface or nil +// if the requested interface doesn't exist. +func (c *client) InterfaceByName(name string) (*Interface, error) { + interfaces, err := c.Interfaces() + if err != nil { return nil, err } + + for _, i := range interfaces { + if i.Name == name { return i, nil } + } + return nil, nil +} + // Connect starts connecting the interface to the specified ssid. func (c *client) Connect(ifi *Interface, ssid string) error { // Ask nl80211 to connect to the specified SSID. @@ -198,6 +210,71 @@ func (c *client) StationInfo(ifi *Interface) ([]*StationInfo, error) { return stations, nil } +// SetFrequency sets the frequency of a wireless interface. +// Does nothing if frequency is already passed in value. +func (c *client) SetFrequency(ifi *Interface, freq int) error { + if ifi.Frequency == freq { return nil } + _, err := c.get( + unix.NL80211_CMD_SET_WIPHY, + netlink.Acknowledge, + ifi, + func(ae *netlink.AttributeEncoder) { + ae.Int32(unix.NL80211_ATTR_WIPHY_FREQ, int32(freq)) + }, + ) + if err == nil { ifi.Frequency = freq } + return err +} + +// SetChannelWidth sets the channel of a wireless interface. +func (c *client) SetChannelWidth(ifi *Interface, width int) error { + _, err := c.get( + unix.NL80211_CMD_SET_WIPHY, + netlink.Acknowledge, + ifi, + func(ae *netlink.AttributeEncoder) { + ae.Int32(unix.NL80211_ATTR_CHANNEL_WIDTH, int32(width)) + }, + ) + return err +} + +// SetModeMonitor sets the interface iftype to InterfaceTypeMonitor. +// Does nothing if interface type is already InterfaceTypeMonitor. +func (c *client) SetModeMonitor(ifi *Interface) error { + if ifi.Type == InterfaceTypeMonitor { return nil } + _, err := c.setInterface(ifi, InterfaceTypeMonitor) + return err +} + +// SetModeStation sets the interface iftype to InterfaceTypeStation. +// Does nothing if the interface type is already InterfaceTypeStation. +func (c *client) SetModeStation(ifi *Interface) error { + if ifi.Type == InterfaceTypeStation { return nil } + _, err := c.setInterface(ifi, InterfaceTypeStation) + return err +} + +// setInterface sets the interface iftype +func (c *client) setInterface(ifi *Interface, iftype InterfaceType) ([]genetlink.Message, error) { + msgs, err := c.get( + unix.NL80211_CMD_SET_INTERFACE, + netlink.Acknowledge, + ifi, + func(ae *netlink.AttributeEncoder) { + ae.Int32(unix.NL80211_ATTR_IFTYPE, int32(iftype)) + }, + ) + if err != nil { + return nil, err + } + ifi.Type = iftype + if len(msgs) == 0 { + return nil, os.ErrNotExist + } + return msgs, nil +} + // get performs a request/response interaction with nl80211. func (c *client) get( cmd uint8, diff --git a/client_others.go b/client_others.go index 769902a..603ab21 100644 --- a/client_others.go +++ b/client_others.go @@ -24,3 +24,8 @@ func (*client) StationInfo(_ *Interface) ([]*StationInfo, error) { return nil, e func (*client) Connect(_ *Interface, _ string) error { return errUnimplemented } func (*client) Disconnect(_ *Interface) error { return errUnimplemented } func (*client) ConnectWPAPSK(_ *Interface, _, _ string) error { return errUnimplemented } + +func (*client) SetFrequency(_ *Interface, _ int) { return errUnimplemented } +func (*client) SetChannelWidth(_ *Interface, _ int) { return errUnimplemented } +func (*client) SetModeMonitor(_ *Interface) { return errUnimplemented } +func (*client) SetModeStation(_ *Interface) { return errUnimplemented } \ No newline at end of file