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