Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wip add nl commands #1

Merged
merged 2 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}
79 changes: 78 additions & 1 deletion client_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"os"
"time"
"unicode/utf8"

"github.com/mdlayher/genetlink"
"github.com/mdlayher/netlink"
"github.com/mdlayher/netlink/nlenc"
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions client_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 }