Compiling a network filter

I am trying to write an io-net filter.

I tried qcc -shared … and the code compiled but when I tried to mount
it I would get the errors outlined in an earlier post:

mount -Tio-net -overbose devn-oc.so

mount: Can’t mount / (type io-net)
mount: possible reason: No such device or address

I tried the solution of using the full path name but I still get the
same error. I am now wondering if I am even compiling the code properly?

How am I supposed to compile the code (Single file) for use as a network
filter?

Nick Lovejoy
nlovejoy@syscor.com

Nick Lovejoy <nlovejoy@syscor.com> wrote:

I am trying to write an io-net filter.

I tried qcc -shared … and the code compiled but when I tried to mount
it I would get the errors outlined in an earlier post:

mount -Tio-net -overbose devn-oc.so

mount: Can’t mount / (type io-net)
mount: possible reason: No such device or address

I tried the solution of using the full path name but I still get the
same error. I am now wondering if I am even compiling the code properly?

How am I supposed to compile the code (Single file) for use as a network
filter?

Have you tried putting printf()'s in your filter’s init function? Sounds
to me like you are returning ENODEV from your filter. :slight_smile:

chris

cdm@qnx.com > “The faster I go, the behinder I get.”

Chris McKillop – Lewis Carroll –
Software Engineer, QSSL
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Chris McKillop <cdm@qnx.com> wrote:
: Nick Lovejoy <nlovejoy@syscor.com> wrote:
:>
:> I am trying to write an io-net filter.
:>
:> I tried qcc -shared … and the code compiled but when I tried to mount
:> it I would get the errors outlined in an earlier post:
:>
:>># mount -Tio-net -overbose devn-oc.so
:>>mount: Can’t mount / (type io-net)
:>>mount: possible reason: No such device or address
:>
:> I tried the solution of using the full path name but I still get the
:> same error. I am now wondering if I am even compiling the code properly?
:>
:> How am I supposed to compile the code (Single file) for use as a network
:> filter?
:>

: Have you tried putting printf()'s in your filter’s init function? Sounds
: to me like you are returning ENODEV from your filter. :slight_smile:

try passing the fullpath to your filter as well:

mount -Tio-net -overbose /home/nick/devn-oc.so

-seanb

Sean Boudreau wrote:

I thank everyone for their help but my actual question was never

answered.

How do I compile? Is “qcc -shared filename” all I need to do.

Also, could someone provide some boiler plate for an io-net filter or
some code that is more relavent than the device driver code that is
provided with the DDK. I’m making best guesses as to what I need and
don’t need and the errors that are being returned when I try to mount
are not what I would call informative eg…

mount -Tio-net /home/router/NickStuff/devf-test.so

mount: Can’t mount / (type io-net)
mount: Possible reason: Invalid argument

Here is the code I am working with. At this point I don’t want it to do
anything other than mount and not do anything with the packets. All the
code makes sense to me except the advertisement function which I would
think does not even belong in a filter but I don’t know one way or the
other.

I thank you for helping.
Nick Lovejoy


CODE--------------------

#include <sys/io-net.h>
#include <net/if_types.h>
#include <net/if.h>
#include <stdio.h>
#include <errno.h>

void *test_dll_hdl; //An internal handle used by io-net.
//You’ll need to hold onto this
handle for future
//calls into the io-net
framework.
io_net_self_t *test_ion; //A pointer to a data structure of the io-net
//functions that your
driver can call.

int test_reg_hdl;
uint16_t test_cell;
uint16_t test_lan;

//-----------------------------------------------------------

// Forward declarations
int my_init (void *dll_hdl,
dispatch_t *dpp,
io_net_self_t *ion,
char *options);

static int register_device (void);

//int test_receive_packets (npkt_t *npkt,
// void *func_hdl,
// int off,
// int framlen_sub,
// uint16_t cell,
// uint16_t
endpoint,
// uint16_t iface);
int test_send_packets (npkt_t *npkt, void *func_hdl);
int test_receive_complete (npkt_t *npkt, void *done_hdl, void
*func_hdl);
int test_shutdown1 (int registrant_hdl, void *func_hdl);
int test_shutdown2 (int registrant_hdl, void *func_hdl);
int test_advertise (int registrant_hdl, void *func_hdl);
int test_flush (int registrant_hdl, void *func_hdl);

//-----------------------------------------------------------

// functions that we supply
io_net_registrant_funcs_t test_funcs =
{
10, // nfuncs
NULL, // rx_up()
test_send_packets, // rx_down()
test_receive_complete, // tx_done()
test_shutdown1, // shutdown1()
test_shutdown2, // shutdown2()
test_advertise, // dl_advert()
NULL, // devctl()
test_flush, // flush()
NULL, // raw_open()
NULL // raw_umount_ok()
};




// a description of our driver
io_net_registrant_t test_entry =
{
_REG_FILTER_BELOW, // filter packets before they hit the
converter
“devn-test.so”, // our name
“ip”, // our top type (TCP/IP stack)
“en”, // our bottom type (Ethernet converter)
NULL, // function handle (see the note below)
&test_funcs, // pointer to our functions
0 // #dependencies
};


//------------------------------------------------------------------

// This is the function the io-net searches for when this module is
mounted.
io_net_dll_entry_t io_net_dll_entry =
{
2, // Number of functions
my_init, // init()
NULL // “master” shutdown()
};

//------------------------------------------------------------------
/*

  • Initialization function
    */

int
my_init (void *dll_hdl,
dispatch_t *dpp,
io_net_self_t *ion,
char *options)
{
test_dll_hdl = dll_hdl;
test_ion = ion;

printf(“Starting Registration”);

if (!register_device ()) {
printf(“Registration error”);
return (-1); // couldn’t register, fail;
// errno says why
}

// Advertise our driver’s capabilities
if (!test_advertise (test_reg_hdl, test_entry.func_hdl)) {
printf(“Advertisement Failure”);
return (-1);
}

return (0); // success
}

//---------------------------------------------------------------

/**

  • Device registration
    */
    static int
    register_device (void)
    {
    if ((*test_ion → reg)
    (test_dll_hdl,
    &test_entry,
    &test_reg_hdl,
    &test_cell,
    &test_lan) < 0) {

return (0); // failed
}
return (1); // success
}

//---------------------------------------------------------------

#define MTUSIZE 1514

int
test_advertise (int reg_hdl, void func_hdl)
{/

npkt_t *npkt;
net_buf_t *nb;
net_iov_t *iov;
io_net_msg_dl_advert_t *ap;

// 1) Allocate a packet; we’ll use this for communications
// with io-net.
if ((npkt = test_ion->alloc_up_npkt (sizeof (*nb) + sizeof
(*iov),
(void **) &nb)) == NULL) {
return (0);
}

// 2) Allocate room for the advertisement message.
if ((ap = test_ion->alloc (sizeof (*ap), 0)) == NULL) {
test_ion->free (npkt);
return (0);
}

// 3) Set up the packet into the queue.
TAILQ_INSERT_HEAD (&npkt → buffers, nb, ptrs);
iov = (net_iov_t *) (nb + 1);
nb → niov = 1;
nb → net_iov = iov;
iov → iov_base = ap;
iov → iov_len = sizeof (*ap);

// 4) Generate the info for the advertisement message.
memset (ap, 0x00, sizeof (*ap));
ap → type = _IO_NET_MSG_DL_ADVERT;
ap → iflags = (IFF_SIMPLEX | IFF_BROADCAST |
IFF_MULTICAST |
IFF_RUNNING);
ap → mtu_min = 0;
ap → mtu_max = MTUSIZE;
ap → mtu_preferred = MTUSIZE;
sprintf (ap → up_type, “en%d”, test_lan);
strcpy (ap → dl.sdl_data, ap → up_type);
ap → dl.sdl_len = sizeof (struct sockaddr_dl);
ap → dl.sdl_family = AF_LINK;
ap → dl.sdl_index = test_lan;
ap → dl.sdl_type = IFT_ETHER;

// Not terminated:
ap → dl.sdl_nlen = strlen (ap → dl.sdl_data);
ap → dl.sdl_alen = 6;
memcpy (ap → dl.sdl_data + ap → dl.sdl_nlen,
“\x12\x34\x56\x78\x9a\xbc”, 6);

// 5) Bind the advertisement message to the packet; note
// the use of the _NPKT_MSG flag to indicate to the
// upper modules that this is a message intended for
// them. It isn’t just a “regular” packet.
npkt → org_data = ap;
npkt → flags |= _NPKT_MSG;
npkt → iface = 0;
npkt → framelen = sizeof (*ap);

if (test_ion->reg_tx_done (test_reg_hdl, npkt, NULL) == -1) {
test_ion->free (ap);
test_ion->free (npkt);
return (0);
}

// 6) Complete the transaction.
if(test_ion->tx_up (test_reg_hdl, npkt, 0, 0, test_cell,
test_lan, 0) == 0) {
test_ion->tx_done (test_reg_hdl, npkt);
}*/
return (0);
}


//--------------------------------------------------------------------

int test_send_packets (npkt_t *npkt, void *func_hdl) {
return TX_DOWN_OK;
}

//--------------------------------------------------------------------


int test_receive_complete (npkt_t *npkt, void *done_hdl, void *func_hdl)
{
return 0;

}

//--------------------------------------------------------------------


int test_shutdown1 (int registrant_hdl, void *func_hdl)
{
return EOK;
}

//---------------------------------------------------------------------


int test_shutdown2 (int registrant_hdl, void *func_hdl)
{
return 0;
}

//---------------------------------------------------------------------

int test_flush (int registrant_hdl, void *func_hdl)
{
return 0;
}

Nick Lovejoy <nlovejoy@syscor.com> wrote:

Sean Boudreau wrote:

I thank everyone for their help but my actual question was never
answered.

How do I compile? Is “qcc -shared filename” all I need to do.

Also, could someone provide some boiler plate for an io-net filter or
some code that is more relavent than the device driver code that is
provided with the DDK. I’m making best guesses as to what I need and
don’t need and the errors that are being returned when I try to mount
are not what I would call informative eg…

Take a look at http://staff.qnx.com/~xtang/. I belive that the
binaries and source to bpf/tcpdump can be found there.

chris

cdm@qnx.com > “The faster I go, the behinder I get.”

Chris McKillop – Lewis Carroll –
Software Engineer, QSSL
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<