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