153913Sarchie# $FreeBSD: releng/10.2/share/examples/netgraph/ngctl 222179 2011-05-22 14:23:48Z uqs $
253913Sarchie
353913Sarchie#
453913Sarchie# This is an example that shows how to send ASCII formatted control
553913Sarchie# messages to a node using ngctl(8).
653913Sarchie#
753913Sarchie# What we will do here create a divert(4) tap.  This simply dumps
853913Sarchie# out all packets diverted by some ipfw(8) divert rule to the console.
953913Sarchie#
1053913Sarchie# Lines that begin with ``$'' (shell prompt) or ``+'' (ngctl prompt)
1153913Sarchie# indicate user input
1253913Sarchie#
1353913Sarchie
1453913Sarchie# First, start up ngctl in interactive mode:
1553913Sarchie
1653913Sarchie    $ ngctl
1753913Sarchie    Available commands:
1853913Sarchie      connect    Connects hook <peerhook> of the node at <relpath> to <hook>
1953913Sarchie      debug      Get/set debugging verbosity level
2053913Sarchie      help       Show command summary or get more help on a specific command
2153913Sarchie      list       Show information about all nodes
2253913Sarchie      mkpeer     Create and connect a new node to the node at "path"
2353913Sarchie      msg        Send a netgraph control message to the node at "path"
2453913Sarchie      name       Assign name <name> to the node at <path>
2553913Sarchie      read       Read and execute commands from a file
2653913Sarchie      rmhook     Disconnect hook "hook" of the node at "path"
2753913Sarchie      show       Show information about the node at <path>
2853913Sarchie      shutdown   Shutdown the node at <path>
2953913Sarchie      status     Get human readable status information from the node at <path>
3053913Sarchie      types      Show information about all installed node types
3153913Sarchie      quit       Exit program
3253913Sarchie    +
3353913Sarchie
34120612Sjulian# Now let's create a ng_ksocket(4) node, in the family PF_INET,
3553913Sarchie# of type SOCK_RAW, and protocol IPPROTO_DIVERT:
3653913Sarchie
3753913Sarchie    + mkpeer ksocket foo inet/raw/divert
3853913Sarchie
3953913Sarchie# Note that ``foo'' is the hook name on the socket node, which can be
4053913Sarchie# anything.  The ``inet/raw/divert'' is the hook name on the ksocket
4153913Sarchie# node, which tells it what kind of socket to create.
4253913Sarchie
4353913Sarchie# Lets give our ksocket node a global name.  How about ``fred'':
4453913Sarchie
4553913Sarchie    + name foo fred
4653913Sarchie
4753913Sarchie# Note that we used ngctl's ``name'' command to do this.  However,
4853913Sarchie# the following manually constructed netgraph message would have
49222179Suqs# accomplished the exact same thing:
5053913Sarchie
5153913Sarchie    + msg foo name { name="fred" }
5253913Sarchie
5353913Sarchie# Here we are using the ASCII <-> binary control message conversion
5453913Sarchie# routines.  ngctl does this for us automatically when we use the
5553913Sarchie# ``msg'' command.
5653913Sarchie
5753913Sarchie# Now lets bind the socket associated with the ksocket node to a port
5853913Sarchie# supplied by the system.  We do this by sending the ksocket node a
5953913Sarchie# ``bind'' control message.  Again, ngctl does the conversion of the
6053913Sarchie# control message from ASCII to binary behind the scenes.
6153913Sarchie
6253913Sarchie    + msg fred: bind inet/192.168.1.1
6353913Sarchie
6453913Sarchie# The ksocket accepts arbitrary sockaddr structures, but also has
6553913Sarchie# special support for the PF_LOCAL and PF_INET protocol families.
6653913Sarchie# That is why we can specify the struct sockaddr argument to the
6753913Sarchie# ``bind'' command as ``inet/192.168.1.1'' (since we didn't specify
6853913Sarchie# a port number, it's assumed to be zero).  We could have also
6953913Sarchie# relied on the generic sockaddr syntax and instead said this:
7053913Sarchie
7153913Sarchie    + msg fred: bind { family=2 len=16 data=[ 2=192 168 1 1 ] }
7253913Sarchie
7353913Sarchie# This is what you would have to do for protocol families other
7453913Sarchie# that PF_INET and PF_LOCAL, at least until special handling for
7553913Sarchie# new ones is added.
7653913Sarchie
7753913Sarchie# The reason for the ``2=192'' is to skip the two byte IP port number,
7853913Sarchie# which causes it to be set to zero, the default value for integral
7953913Sarchie# types when parsing.  Now since we didn't ask for a specific port
8053913Sarchie# number, we need to do a ``getname'' to see what port number we got:
8153913Sarchie
8253913Sarchie    + msg fred: getname
8353913Sarchie    Rec'd response "getname" (5) from "fred:":
8453913Sarchie    Args:   inet/192.168.1.1:1029
8553913Sarchie
8653913Sarchie# As soon as we sent the message, we got back a response.  Here
8753913Sarchie# ngctl is telling us that it received a control message with the
88222179Suqs# NGF_RESP (response) flag set, the response was to a prior ``getname''
8953913Sarchie# control message, that the originator was the node addressable
9053913Sarchie# as ``fred:''.  The message arguments field is then displayed to
9153913Sarchie# us in its ASCII form.  In this case, what we get back is a struct
9253913Sarchie# sockaddr, and there we see that our port number is 1029.
9353913Sarchie
9453913Sarchie# So now let's add the ipfw divert rule for whatever packets we
9553913Sarchie# want to see.  How about anything from 192.168.1.129.
9653913Sarchie
9753913Sarchie    + ^Z
9853913Sarchie    Suspended
9953913Sarchie    $ ipfw add 100 divert 1029 ip from 192.168.1.129 to any
10053913Sarchie    00100 divert 1029 ip from 192.168.1.129 to any
10153913Sarchie    $ fg
10253913Sarchie
10353913Sarchie# Now watch what happens when we try to ping from that machine:
10453913Sarchie
10553913Sarchie    + 
10653913Sarchie    Rec'd data packet on hook "foo":
10753913Sarchie    0000:  45 00 00 3c 57 00 00 00 20 01 bf ee c0 a8 01 81  E..<W... .......
10853913Sarchie    0010:  c0 a8 01 01 08 00 49 5c 03 00 01 00 61 62 63 64  ......I\....abcd
10953913Sarchie    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
11053913Sarchie    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
11153913Sarchie    + 
11253913Sarchie    Rec'd data packet on hook "foo":
11353913Sarchie    0000:  45 00 00 3c 58 00 00 00 20 01 be ee c0 a8 01 81  E..<X... .......
11453913Sarchie    0010:  c0 a8 01 01 08 00 48 5c 03 00 02 00 61 62 63 64  ......H\....abcd
11553913Sarchie    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
11653913Sarchie    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
11753913Sarchie    + 
11853913Sarchie    Rec'd data packet on hook "foo":
11953913Sarchie    0000:  45 00 00 3c 59 00 00 00 20 01 bd ee c0 a8 01 81  E..<Y... .......
12053913Sarchie    0010:  c0 a8 01 01 08 00 47 5c 03 00 03 00 61 62 63 64  ......G\....abcd
12153913Sarchie    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
12253913Sarchie    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
12353913Sarchie    +
12453913Sarchie
12553913Sarchie# So we're seeing the output from the ksocket socket appear on the ``foo''
12653913Sarchie# hook of ngctl's socket node.  Since the packets are getting diverted,
12753913Sarchie# the 192.168.1.129 machine doesn't see any response from us.
12853913Sarchie
12953913Sarchie# Of course, any type of socket can be used, even TCP:
13053913Sarchie
13153913Sarchie    + mkpeer ksocket bar inet/stream/tcp
13253913Sarchie    + msg bar connect inet/192.168.1.33:13
13353913Sarchie    ngctl: send msg: Operation now in progress
13453913Sarchie    + 
13553913Sarchie    Rec'd data packet on hook "foo":
13653913Sarchie    0000:  4d 6f 6e 20 4e 6f 76 20 32 39 20 31 37 3a 34 38  Mon Nov 29 17:48
13753913Sarchie    0010:  3a 33 37 20 31 39 39 39 0d 0a                    :37 1999..
13853913Sarchie    +
13953913Sarchie
14053913Sarchie# Or, UNIX domain:
14153913Sarchie
14253913Sarchie    + mkpeer ksocket bar local/stream/0
14353913Sarchie    + msg bar bind local/"/tmp/bar.socket"
14453913Sarchie    + 
14553913Sarchie
14653913Sarchie# Here's an example of a more complicated ASCII control message argument.
14753913Sarchie# If you look in /sys/netgraph/ng_message.h, you will see that a node
14853913Sarchie# responds to a NGM_LISTHOOKS with a struct hooklist, which contains
14953913Sarchie# an array of struct linkinfo:
15053913Sarchie#
15153913Sarchie#     /* Structure used for NGM_LISTHOOKS */
15253913Sarchie#     struct linkinfo {
153122758Sharti#             char            ourhook[NG_HOOKSIZ];        /* hook name */
154122758Sharti#             char            peerhook[NG_HOOKSIZ];       /* peer hook */
15553913Sarchie#             struct nodeinfo nodeinfo;
15653913Sarchie#     };
15753913Sarchie#
15853913Sarchie#     struct hooklist {
15953913Sarchie#             struct nodeinfo nodeinfo;               /* node information */
16053913Sarchie#             struct linkinfo link[0];                /* info about each hook */
16153913Sarchie#     };
16253913Sarchie#
16353913Sarchie# By sending a node the ``listhooks'' command using ngctl, we can see
16453913Sarchie# this structure in ASCII form (lines wrapped for readability):
16553913Sarchie
16653913Sarchie    + msg bar bind local/"/tmp/bar.socket"
16753913Sarchie    + msg bar listhooks
16853913Sarchie    Rec'd response "listhooks" (7) from "bar":
16953913Sarchie    Args:   { nodeinfo={ type="ksocket" id=9 hooks=1 }
17053913Sarchie	    linkinfo=[ { ourhook="local/stream/0" peerhook="bar"
17153913Sarchie	    nodeinfo={ name="ngctl1327" type="socket" id=8 hooks=1 } } ] }
17253913Sarchie
17353913Sarchie
174