xref: /freebsd/share/examples/netgraph/ngctl (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
1
2#
3# This is an example that shows how to send ASCII formatted control
4# messages to a node using ngctl(8).
5#
6# What we will do here create a divert(4) tap.  This simply dumps
7# out all packets diverted by some ipfw(8) divert rule to the console.
8#
9# Lines that begin with ``$'' (shell prompt) or ``+'' (ngctl prompt)
10# indicate user input
11#
12
13# First, start up ngctl in interactive mode:
14
15    $ ngctl
16    Available commands:
17      connect    Connects hook <peerhook> of the node at <relpath> to <hook>
18      debug      Get/set debugging verbosity level
19      help       Show command summary or get more help on a specific command
20      list       Show information about all nodes
21      mkpeer     Create and connect a new node to the node at "path"
22      msg        Send a netgraph control message to the node at "path"
23      name       Assign name <name> to the node at <path>
24      read       Read and execute commands from a file
25      rmhook     Disconnect hook "hook" of the node at "path"
26      show       Show information about the node at <path>
27      shutdown   Shutdown the node at <path>
28      status     Get human readable status information from the node at <path>
29      types      Show information about all installed node types
30      quit       Exit program
31    +
32
33# Now let's create a ng_ksocket(4) node, in the family PF_DIVERT,
34# of type SOCK_RAW:
35
36    + mkpeer ksocket foo divert/raw/0
37
38# Note that ``foo'' is the hook name on the socket node, which can be
39# anything.  The ``inet/raw/divert'' is the hook name on the ksocket
40# node, which tells it what kind of socket to create.
41
42# Lets give our ksocket node a global name.  How about ``fred'':
43
44    + name foo fred
45
46# Note that we used ngctl's ``name'' command to do this.  However,
47# the following manually constructed netgraph message would have
48# accomplished the exact same thing:
49
50    + msg foo name { name="fred" }
51
52# Here we are using the ASCII <-> binary control message conversion
53# routines.  ngctl does this for us automatically when we use the
54# ``msg'' command.
55
56# Now lets bind the socket associated with the ksocket node to a port
57# supplied by the system.  We do this by sending the ksocket node a
58# ``bind'' control message.  Again, ngctl does the conversion of the
59# control message from ASCII to binary behind the scenes.
60
61    + msg fred: bind inet/192.168.1.1
62
63# The ksocket accepts arbitrary sockaddr structures, but also has
64# special support for the PF_LOCAL and PF_INET protocol families.
65# That is why we can specify the struct sockaddr argument to the
66# ``bind'' command as ``inet/192.168.1.1'' (since we didn't specify
67# a port number, it's assumed to be zero).  We could have also
68# relied on the generic sockaddr syntax and instead said this:
69
70    + msg fred: bind { family=2 len=16 data=[ 2=192 168 1 1 ] }
71
72# This is what you would have to do for protocol families other
73# that PF_INET and PF_LOCAL, at least until special handling for
74# new ones is added.
75
76# The reason for the ``2=192'' is to skip the two byte IP port number,
77# which causes it to be set to zero, the default value for integral
78# types when parsing.  Now since we didn't ask for a specific port
79# number, we need to do a ``getname'' to see what port number we got:
80
81    + msg fred: getname
82    Rec'd response "getname" (5) from "fred:":
83    Args:   inet/192.168.1.1:1029
84
85# As soon as we sent the message, we got back a response.  Here
86# ngctl is telling us that it received a control message with the
87# NGF_RESP (response) flag set, the response was to a prior ``getname''
88# control message, that the originator was the node addressable
89# as ``fred:''.  The message arguments field is then displayed to
90# us in its ASCII form.  In this case, what we get back is a struct
91# sockaddr, and there we see that our port number is 1029.
92
93# So now let's add the ipfw divert rule for whatever packets we
94# want to see.  How about anything from 192.168.1.129.
95
96    + ^Z
97    Suspended
98    $ ipfw add 100 divert 1029 ip from 192.168.1.129 to any
99    00100 divert 1029 ip from 192.168.1.129 to any
100    $ fg
101
102# Now watch what happens when we try to ping from that machine:
103
104    +
105    Rec'd data packet on hook "foo":
106    0000:  45 00 00 3c 57 00 00 00 20 01 bf ee c0 a8 01 81  E..<W... .......
107    0010:  c0 a8 01 01 08 00 49 5c 03 00 01 00 61 62 63 64  ......I\....abcd
108    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
109    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
110    +
111    Rec'd data packet on hook "foo":
112    0000:  45 00 00 3c 58 00 00 00 20 01 be ee c0 a8 01 81  E..<X... .......
113    0010:  c0 a8 01 01 08 00 48 5c 03 00 02 00 61 62 63 64  ......H\....abcd
114    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
115    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
116    +
117    Rec'd data packet on hook "foo":
118    0000:  45 00 00 3c 59 00 00 00 20 01 bd ee c0 a8 01 81  E..<Y... .......
119    0010:  c0 a8 01 01 08 00 47 5c 03 00 03 00 61 62 63 64  ......G\....abcd
120    0020:  65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74  efghijklmnopqrst
121    0030:  75 76 77 61 62 63 64 65 66 67 68 69              uvwabcdefghi
122    +
123
124# So we're seeing the output from the ksocket socket appear on the ``foo''
125# hook of ngctl's socket node.  Since the packets are getting diverted,
126# the 192.168.1.129 machine doesn't see any response from us.
127
128# Of course, any type of socket can be used, even TCP:
129
130    + mkpeer ksocket bar inet/stream/tcp
131    + msg bar connect inet/192.168.1.33:13
132    ngctl: send msg: Operation now in progress
133    +
134    Rec'd data packet on hook "foo":
135    0000:  4d 6f 6e 20 4e 6f 76 20 32 39 20 31 37 3a 34 38  Mon Nov 29 17:48
136    0010:  3a 33 37 20 31 39 39 39 0d 0a                    :37 1999..
137    +
138
139# Or, UNIX domain:
140
141    + mkpeer ksocket bar local/stream/0
142    + msg bar bind local/"/tmp/bar.socket"
143    +
144
145# Here's an example of a more complicated ASCII control message argument.
146# If you look in /sys/netgraph/ng_message.h, you will see that a node
147# responds to a NGM_LISTHOOKS with a struct hooklist, which contains
148# an array of struct linkinfo:
149#
150#     /* Structure used for NGM_LISTHOOKS */
151#     struct linkinfo {
152#             char            ourhook[NG_HOOKSIZ];        /* hook name */
153#             char            peerhook[NG_HOOKSIZ];       /* peer hook */
154#             struct nodeinfo nodeinfo;
155#     };
156#
157#     struct hooklist {
158#             struct nodeinfo nodeinfo;               /* node information */
159#             struct linkinfo link[0];                /* info about each hook */
160#     };
161#
162# By sending a node the ``listhooks'' command using ngctl, we can see
163# this structure in ASCII form (lines wrapped for readability):
164
165    + msg bar bind local/"/tmp/bar.socket"
166    + msg bar listhooks
167    Rec'd response "listhooks" (7) from "bar":
168    Args:   { nodeinfo={ type="ksocket" id=9 hooks=1 }
169	    linkinfo=[ { ourhook="local/stream/0" peerhook="bar"
170	    nodeinfo={ name="ngctl1327" type="socket" id=8 hooks=1 } } ] }
171
172
173