xref: /dflybsd-src/share/examples/netgraph/ngctl (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino# $FreeBSD: src/share/examples/netgraph/ngctl,v 1.1 1999/11/30 02:45:08 archie Exp $
286d7f5d3SJohn Marino# $DragonFly: src/share/examples/netgraph/ngctl,v 1.3 2007/06/04 00:40:31 swildner Exp $
386d7f5d3SJohn Marino
486d7f5d3SJohn Marino#
586d7f5d3SJohn Marino# This is an example that shows how to send ASCII formatted control
686d7f5d3SJohn Marino# messages to a node using ngctl(8).
786d7f5d3SJohn Marino#
886d7f5d3SJohn Marino# What we will do here create a divert(4) tap.  This simply dumps
986d7f5d3SJohn Marino# out all packets diverted by some ipfw(8) divert rule to the console.
1086d7f5d3SJohn Marino#
1186d7f5d3SJohn Marino# Lines that begin with ``$'' (shell prompt) or ``+'' (ngctl prompt)
1286d7f5d3SJohn Marino# indicate user input
1386d7f5d3SJohn Marino#
1486d7f5d3SJohn Marino
1586d7f5d3SJohn Marino# First, start up ngctl in interactive mode:
1686d7f5d3SJohn Marino
1786d7f5d3SJohn Marino    $ ngctl
1886d7f5d3SJohn Marino    Available commands:
1986d7f5d3SJohn Marino      connect    Connects hook <peerhook> of the node at <relpath> to <hook>
2086d7f5d3SJohn Marino      debug      Get/set debugging verbosity level
2186d7f5d3SJohn Marino      help       Show command summary or get more help on a specific command
2286d7f5d3SJohn Marino      list       Show information about all nodes
2386d7f5d3SJohn Marino      mkpeer     Create and connect a new node to the node at "path"
2486d7f5d3SJohn Marino      msg        Send a netgraph control message to the node at "path"
2586d7f5d3SJohn Marino      name       Assign name <name> to the node at <path>
2686d7f5d3SJohn Marino      read       Read and execute commands from a file
2786d7f5d3SJohn Marino      rmhook     Disconnect hook "hook" of the node at "path"
2886d7f5d3SJohn Marino      show       Show information about the node at <path>
2986d7f5d3SJohn Marino      shutdown   Shutdown the node at <path>
3086d7f5d3SJohn Marino      status     Get human readable status information from the node at <path>
3186d7f5d3SJohn Marino      types      Show information about all installed node types
3286d7f5d3SJohn Marino      quit       Exit program
3386d7f5d3SJohn Marino    +
3486d7f5d3SJohn Marino
3586d7f5d3SJohn Marino# Now let's create a ng_ksocket(8) node, in the family PF_INET,
3686d7f5d3SJohn Marino# of type SOCK_RAW, and protocol IPPROTO_DIVERT:
3786d7f5d3SJohn Marino
3886d7f5d3SJohn Marino    + mkpeer ksocket foo inet/raw/divert
3986d7f5d3SJohn Marino
4086d7f5d3SJohn Marino# Note that ``foo'' is the hook name on the socket node, which can be
4186d7f5d3SJohn Marino# anything.  The ``inet/raw/divert'' is the hook name on the ksocket
4286d7f5d3SJohn Marino# node, which tells it what kind of socket to create.
4386d7f5d3SJohn Marino
4486d7f5d3SJohn Marino# Lets give our ksocket node a global name.  How about ``fred'':
4586d7f5d3SJohn Marino
4686d7f5d3SJohn Marino    + name foo fred
4786d7f5d3SJohn Marino
4886d7f5d3SJohn Marino# Note that we used ngctl's ``name'' command to do this.  However,
4986d7f5d3SJohn Marino# the following manually constructed netgraph message would have
5086d7f5d3SJohn Marino# acomplished the exact same thing:
5186d7f5d3SJohn Marino
5286d7f5d3SJohn Marino    + msg foo name { name="fred" }
5386d7f5d3SJohn Marino
5486d7f5d3SJohn Marino# Here we are using the ASCII <-> binary control message conversion
5586d7f5d3SJohn Marino# routines.  ngctl does this for us automatically when we use the
5686d7f5d3SJohn Marino# ``msg'' command.
5786d7f5d3SJohn Marino
5886d7f5d3SJohn Marino# Now lets bind the socket associated with the ksocket node to a port
5986d7f5d3SJohn Marino# supplied by the system.  We do this by sending the ksocket node a
6086d7f5d3SJohn Marino# ``bind'' control message.  Again, ngctl does the conversion of the
6186d7f5d3SJohn Marino# control message from ASCII to binary behind the scenes.
6286d7f5d3SJohn Marino
6386d7f5d3SJohn Marino    + msg fred: bind inet/192.168.1.1
6486d7f5d3SJohn Marino
6586d7f5d3SJohn Marino# The ksocket accepts arbitrary sockaddr structures, but also has
6686d7f5d3SJohn Marino# special support for the PF_LOCAL and PF_INET protocol families.
6786d7f5d3SJohn Marino# That is why we can specify the struct sockaddr argument to the
6886d7f5d3SJohn Marino# ``bind'' command as ``inet/192.168.1.1'' (since we didn't specify
6986d7f5d3SJohn Marino# a port number, it's assumed to be zero).  We could have also
7086d7f5d3SJohn Marino# relied on the generic sockaddr syntax and instead said this:
7186d7f5d3SJohn Marino
7286d7f5d3SJohn Marino    + msg fred: bind { family=2 len=16 data=[ 2=192 168 1 1 ] }
7386d7f5d3SJohn Marino
7486d7f5d3SJohn Marino# This is what you would have to do for protocol families other
7586d7f5d3SJohn Marino# that PF_INET and PF_LOCAL, at least until special handling for
7686d7f5d3SJohn Marino# new ones is added.
7786d7f5d3SJohn Marino
7886d7f5d3SJohn Marino# The reason for the ``2=192'' is to skip the two byte IP port number,
7986d7f5d3SJohn Marino# which causes it to be set to zero, the default value for integral
8086d7f5d3SJohn Marino# types when parsing.  Now since we didn't ask for a specific port
8186d7f5d3SJohn Marino# number, we need to do a ``getname'' to see what port number we got:
8286d7f5d3SJohn Marino
8386d7f5d3SJohn Marino    + msg fred: getname
8486d7f5d3SJohn Marino    Rec'd response "getname" (5) from "fred:":
8586d7f5d3SJohn Marino    Args:   inet/192.168.1.1:1029
8686d7f5d3SJohn Marino
8786d7f5d3SJohn Marino# As soon as we sent the message, we got back a response.  Here
8886d7f5d3SJohn Marino# ngctl is telling us that it received a control message with the
8986d7f5d3SJohn Marino# NGF_RESP (response) flag set, the reponse was to a prior ``getname''
9086d7f5d3SJohn Marino# control message, that the originator was the node addressable
9186d7f5d3SJohn Marino# as ``fred:''.  The message arguments field is then displayed to
9286d7f5d3SJohn Marino# us in its ASCII form.  In this case, what we get back is a struct
9386d7f5d3SJohn Marino# sockaddr, and there we see that our port number is 1029.
9486d7f5d3SJohn Marino
9586d7f5d3SJohn Marino# So now let's add the ipfw divert rule for whatever packets we
9686d7f5d3SJohn Marino# want to see.  How about anything from 192.168.1.129.
9786d7f5d3SJohn Marino
9886d7f5d3SJohn Marino    + ^Z
9986d7f5d3SJohn Marino    Suspended
10086d7f5d3SJohn Marino    $ ipfw add 100 divert 1029 ip from 192.168.1.129 to any
10186d7f5d3SJohn Marino    00100 divert 1029 ip from 192.168.1.129 to any
10286d7f5d3SJohn Marino    $ fg
10386d7f5d3SJohn Marino
10486d7f5d3SJohn Marino# Now watch what happens when we try to ping from that machine:
10586d7f5d3SJohn Marino
10686d7f5d3SJohn Marino    +
10786d7f5d3SJohn Marino    Rec'd data packet on hook "foo":
10886d7f5d3SJohn Marino    0000:  45 00 00 3c 57 00 00 00 20 01 bf ee c0 a8 01 81  E..<W... .......
10986d7f5d3SJohn Marino    0010:  c0 a8 01 01 08 00 49 5c 03 00 01 00 61 62 63 64  ......I\....abcd
11086d7f5d3SJohn Marino    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
11186d7f5d3SJohn Marino    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
11286d7f5d3SJohn Marino    +
11386d7f5d3SJohn Marino    Rec'd data packet on hook "foo":
11486d7f5d3SJohn Marino    0000:  45 00 00 3c 58 00 00 00 20 01 be ee c0 a8 01 81  E..<X... .......
11586d7f5d3SJohn Marino    0010:  c0 a8 01 01 08 00 48 5c 03 00 02 00 61 62 63 64  ......H\....abcd
11686d7f5d3SJohn Marino    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
11786d7f5d3SJohn Marino    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
11886d7f5d3SJohn Marino    +
11986d7f5d3SJohn Marino    Rec'd data packet on hook "foo":
12086d7f5d3SJohn Marino    0000:  45 00 00 3c 59 00 00 00 20 01 bd ee c0 a8 01 81  E..<Y... .......
12186d7f5d3SJohn Marino    0010:  c0 a8 01 01 08 00 47 5c 03 00 03 00 61 62 63 64  ......G\....abcd
12286d7f5d3SJohn Marino    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
12386d7f5d3SJohn Marino    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
12486d7f5d3SJohn Marino    +
12586d7f5d3SJohn Marino
12686d7f5d3SJohn Marino# So we're seeing the output from the ksocket socket appear on the ``foo''
12786d7f5d3SJohn Marino# hook of ngctl's socket node.  Since the packets are getting diverted,
12886d7f5d3SJohn Marino# the 192.168.1.129 machine doesn't see any response from us.
12986d7f5d3SJohn Marino
13086d7f5d3SJohn Marino# Of course, any type of socket can be used, even TCP:
13186d7f5d3SJohn Marino
13286d7f5d3SJohn Marino    + mkpeer ksocket bar inet/stream/tcp
13386d7f5d3SJohn Marino    + msg bar connect inet/192.168.1.33:13
13486d7f5d3SJohn Marino    ngctl: send msg: Operation now in progress
13586d7f5d3SJohn Marino    +
13686d7f5d3SJohn Marino    Rec'd data packet on hook "foo":
13786d7f5d3SJohn Marino    0000:  4d 6f 6e 20 4e 6f 76 20 32 39 20 31 37 3a 34 38  Mon Nov 29 17:48
13886d7f5d3SJohn Marino    0010:  3a 33 37 20 31 39 39 39 0d 0a                    :37 1999..
13986d7f5d3SJohn Marino    +
14086d7f5d3SJohn Marino
14186d7f5d3SJohn Marino# Or, UNIX domain:
14286d7f5d3SJohn Marino
14386d7f5d3SJohn Marino    + mkpeer ksocket bar local/stream/0
14486d7f5d3SJohn Marino    + msg bar bind local/"/tmp/bar.socket"
14586d7f5d3SJohn Marino    +
14686d7f5d3SJohn Marino
14786d7f5d3SJohn Marino# Here's an example of a more complicated ASCII control message argument.
14886d7f5d3SJohn Marino# If you look in /sys/netgraph/ng_message.h, you will see that a node
14986d7f5d3SJohn Marino# responds to a NGM_LISTHOOKS with a struct hooklist, which contains
15086d7f5d3SJohn Marino# an array of struct linkinfo:
15186d7f5d3SJohn Marino#
15286d7f5d3SJohn Marino#     /* Structure used for NGM_LISTHOOKS */
15386d7f5d3SJohn Marino#     struct linkinfo {
15486d7f5d3SJohn Marino#             char            ourhook[NG_HOOKSIZ];	/* hook name */
15586d7f5d3SJohn Marino#             char            peerhook[NG_HOOSIZ];	/* peer hook */
15686d7f5d3SJohn Marino#             struct nodeinfo nodeinfo;
15786d7f5d3SJohn Marino#     };
15886d7f5d3SJohn Marino#
15986d7f5d3SJohn Marino#     struct hooklist {
16086d7f5d3SJohn Marino#             struct nodeinfo nodeinfo;               /* node information */
16186d7f5d3SJohn Marino#             struct linkinfo link[0];                /* info about each hook */
16286d7f5d3SJohn Marino#     };
16386d7f5d3SJohn Marino#
16486d7f5d3SJohn Marino# By sending a node the ``listhooks'' command using ngctl, we can see
16586d7f5d3SJohn Marino# this structure in ASCII form (lines wrapped for readability):
16686d7f5d3SJohn Marino
16786d7f5d3SJohn Marino    + msg bar bind local/"/tmp/bar.socket"
16886d7f5d3SJohn Marino    + msg bar listhooks
16986d7f5d3SJohn Marino    Rec'd response "listhooks" (7) from "bar":
17086d7f5d3SJohn Marino    Args:   { nodeinfo={ type="ksocket" id=9 hooks=1 }
17186d7f5d3SJohn Marino	    linkinfo=[ { ourhook="local/stream/0" peerhook="bar"
17286d7f5d3SJohn Marino	    nodeinfo={ name="ngctl1327" type="socket" id=8 hooks=1 } } ] }
17386d7f5d3SJohn Marino
17486d7f5d3SJohn Marino
175