Getting essid via ioctl

Hello.

To avoid relying on the wireless tools I want to get the essid directly from the device with ioctl, in C
this wouldn't be a problem, but in Ruby it's quite different.

The problem is following struct from wireless.h that is used as input/reply of ioctl:

struct iw_point
{
void __user *pointer; /* Pointer to the data (in user space) */
__u16 length; /* number of fields or size in bytes */
__u16 flags; /* Optional params */
};

The pointer part must be a valid address of a memory area, followed by the length in bytes,
followed by a flag field. I tried with Array#pack and the bit-struct gem, but haven't found a solution yet.

Is there a way to bypass this memory pointer problem?

Wbr

Christoph

Christoph Kappel wrote:

Hello.

To avoid relying on the wireless tools I want to get the essid directly from the device with ioctl, in C this wouldn't be a problem, but in Ruby it's quite different.

The problem is following struct from wireless.h that is used as input/reply of ioctl:

struct iw_point
{
  void __user *pointer; /* Pointer to the data (in user space) */
  __u16 length; /* number of fields or size in bytes */
  __u16 flags; /* Optional params */
};

The pointer part must be a valid address of a memory area, followed by the length in bytes, followed by a flag field. I tried with Array#pack and the bit-struct gem, but haven't found a solution yet.

Is there a way to bypass this memory pointer problem?

Christoph,

How are you calling ioctl() ? If you're using FFI, then googling for FFI::Pointer should help. If you're calling it in some other way and are trying to access the binary data in ruby, does the P specifier in pack/unpack work?

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hey Joel,

thanks for both hints - FFI looks interesting but I don't want to wrap a library.
Funny that I missed the 'p' of pack - it's working now:

require "socket"

# Copied from wireless.h
SIOCGIWESSID = 0x8B1B
IW_ESSID_MAX_SIZE = 32

iwreq = [ "wlan0", " " * IW_ESSID_MAX_SIZE, IW_ESSID_MAX_SIZE, 0 ].pack("a16pII")

sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)

sock.ioctl(SIOCGIWESSID, iwreq)

interface, essid, len, flags = iwreq.unpack("a16pII")

puts essid

Now I can check if I can fetch the max. link quality via ioctl too.

Wbr, Christoph

···

---- On Tue, 22 Sep 2009 16:58:46 -0700 Joel VanderWerf <vjoel@path.berkeley.edu> wrote ----

> Christoph Kappel wrote:
> > Hello.
> >
> > To avoid relying on the wireless tools I want to get the essid directly from the device with ioctl, in C
> > this wouldn't be a problem, but in Ruby it's quite different.
> >
> > The problem is following struct from wireless.h that is used as input/reply of ioctl:
> >
> > struct iw_point
> > {
> > void __user *pointer; /* Pointer to the data (in user space) */
> > __u16 length; /* number of fields or size in bytes */
> > __u16 flags; /* Optional params */
> > };
> >
> > The pointer part must be a valid address of a memory area, followed by the length in bytes,
> > followed by a flag field. I tried with Array#pack and the bit-struct gem, but haven't found a solution yet.
> >
> > Is there a way to bypass this memory pointer problem?
>
> Christoph,
>
> How are you calling ioctl() ? If you're using FFI, then googling for
> FFI::Pointer should help. If you're calling it in some other way and are
> trying to access the binary data in ruby, does the P specifier in
> pack/unpack work?
>
> --
> vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
>