Unexpected behavior after altering inetsw[] switch table

Shaun Colley shaun at rsc.cx
Sun Jun 11 00:36:40 UTC 2006


Hi list.

My system is:
---
FreeBSD  6.0-RELEASE FreeBSD 6.0-RELEASE #0: Thu Nov  3 09:36:13 UTC 2005 
   root at x64.samsco.home:/usr/obj/usr/src/sys/GENERIC  i386
---

I'm writing a kernel module whose job is to modify the inetsw[] switch
table for the IPPROTO_TCP protocol.  The pr_output hook for TCP needs to
be changed, such that my own custom tcp_output function will be called
when transmitting TCP packets.  The reason for doing this is so that I can
do some modification on TCP packets before they are transmitted, but the
semantics of this are not important.

The part of the module of interest is:

---
 switch (what) {
  case MOD_LOAD:                /* kldload */
    uprintf("Skeleton KLD loaded.\n");
    old_handler = inetsw[ip_protox[IPPROTO_TCP]].pr_output;
    inetsw[ip_protox[IPPROTO_TCP]].pr_output = (pr_output_t *)my_tcp_output;
    break;
  case MOD_UNLOAD:
    uprintf("Skeleton KLD unloaded.\n");
    inetsw[ip_protox[IPPROTO_TCP]].pr_output = old_handler;
    break;
  default:
    err = EINVAL;
    break;
  }
---

my_tcp_output is a hacked version of tcp_output.

When the module is built and loaded, the modification to the switch table
seems to have no effect whatsoever.  That is, my custom routine does not
seem to be called when outputting TCP packets.  This can be demonstrated
fully by changing the modification line to:
inetsw[ip_protox[IPPROTO_TCP]].pr_output = (pr_output_t *)0x0; - no kernel
panic occurs in this case.  This ultimately leads me to believe that the
hook is not being called, even though it should be (I am attempting to
send TCP packets, so my function should be getting called).

This is very odd, because when I instead modify the pr_input hook, my
custom function *does* get called (i.e. when incoming packets are passed
up).  For example, by inserting the line
'inetsw[ip_protox[IPPROTO_TCP]].pr_input = (pr_input_t
*)my_input_handler;', and then receiving TCP packets from below,
my_input_handler *is* entered, whereas if the corresponding TCP pr_output
hook is modified, that function does not get called (the regular
tcp_output() function seems to get used as normal).

I've attached a testcase module which demonstrates the behavior.  If the
hook replacement works correctly, you'll have a TCP output hook which
essentially does nothing (i.e. doesn't pass packet down to next layer),
hence your TCP stack shouldn't work properly (so to speak).  However, that
doesn't happen (at least on my system), as I've said.  A makefile is also
attached.

Note, I'm not saying this is a bug.  I'm just wondering what is going
wrong.  My information (i.e. the way I'm trying to do this) may be out of
date, for example.  I'm wondering if someone can cast some light on what
the problem might be.

Also attached is a kernel module that alters the pr_input hook of TCP to a
dummy function, similarly to the pr_input one.  Loading this one will
leave you with a dummy input function, rendering your TCP stack not able
to process packets until you unload the module.  Note that unloading both
of the modules will leave you good to go again.

cheers,
Shaun
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Makefile.1
Type: application/octet-stream
Size: 55 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20060611/2ca9212e/Makefile.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Makefile.2
Type: application/octet-stream
Size: 53 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20060611/2ca9212e/Makefile-0001.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pr_input.c
Type: application/octet-stream
Size: 1996 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20060611/2ca9212e/pr_input.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pr_output.c
Type: application/octet-stream
Size: 2000 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20060611/2ca9212e/pr_output.obj


More information about the freebsd-net mailing list