Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: help me parse this?

From: pierce:athenasecurity at: 5-Nov-2000 11:24

Is there anything in particular you want to parse? I've spent the last week or so working with parse, below are some of the things I've been working on: This is the Solaris output of 'ifconfig -a' on one of my machines, I needed to write a script to parse the information below looking for the broadcast address for each interface (more later on why). lo0: flags=849<UP,LOOPBACK,RUNNING,MULTICAST> mtu 8232 inet 127.0.0.1 netmask ff000000 hme0: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 192.168.10.139 netmask ffffff00 broadcast 192.168.10.255 ether 8:0:20:c6:ac:a9 qfe0: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 192.168.11.254 netmask ffffff00 broadcast 192.168.11.255 ether 8:0:20:c6:ac:a9 qfe1: flags=863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST> mtu 1500 inet 10.0.0.254 netmask ffff0000 broadcast 10.0.255.255 ether 8:0:20:c6:ac:a9 I did this using REBOL/Command, with the follwoing: First I created a file with some pre-defined variable names, where each instance can be configured without changing the code. For this part the file had an entry called 'interface-arp-check' where the user enteres a string of interfaces to check. Let's say they put in "hme0 qfe0". The first thing I would need to do is get the information from the file: var: read %file.conf var: parse var none The first line reads the config file into var, then the second puts everything into a block at the spaces. For example the file might look like this: email "[Pierce--AthenaSecurity--Com]" interface-arp-check "hme0 qfe0" percent-disk-space "75" I use the 'none' option if I just want to break on the whitespace and put the resulting value into the variable at the front, in this case 'var'. The second line will create a block, stored in var, that looks like this: ["email" "[Pierce--AthenaSecurity--Com]" "interface-arp-check" "hme0 qfe0" percent-disk-space "75"] I find this helpful when I don't know how many times I'll need to loop through the block, I can now use 'while [length? var]' with a 'disarm try[]' around it (see below). The next thing I would do is set the variables, based upon the items in the config file: disarm try [ forall var [ set to-word first var second var ] ] This will go through and set the first item as the variable and the second item as the value, so the variables are now set as: email: "[Pierce--AthenaSecurity--Com]" interface-arp-check: "hme0 qfe0" percent-disk-space: "75" All of these are strings, it's important to remember that...it bit me hard when doing the disk space checking. If I left off the quotes in the config file the email would be of type email and the percent-disk-space would be integer. However, I don't what to keep reminding people when to use quotes and when not to, so I'll tell them everything needs quotes and deal with it later. Now that I know what interfaces to look at I need to parse the information. The purpose of this part of the script is to monitor the ARPs outside each interface. This program is installed on our firewalls to alert the administrator when someone bypasses the firewall. If they place a machine outside the firewall then it will be seen by the firewall, we can then compare the firewalls ARP table against a list of accepted machines for each interface. If anything is odd we send an email. ;I want to toss out any errors, since when I get to the end there will be an error signifying the end of the block. disarm try [ ;Read the 'interface-arp-check' variable and compare the results to the entries found in the '<interface>.ignore' file. interface-arp-check: parse interface-arp-check none {The line above takes the values in 'interface-arp-check', in the case above "hme0 qfe0" and splits them on the space. Now interface-arp-check is a block with two items ["hme0" "qfe0"].} while [length? interface-arp-check] [ interface: first interface-arp-check call/wait "/usr/sbin/ifconfig -a > if.aas" {The line above gets the ifconfig information (shown at the top of this email).} parse/case/all read %if.aas [thru interface copy dev-null thru broadcast copy broadcast to #"^/" copy ifconfig to end] {This line parses the information looking for the word "broadcast" in lowercase letters. The parsing is case sensitive because of the /case option. The /all option tells parse not to split on whitespace. {Notice that there isn't a variable before the parse command. If you use anything other than 'none' for the word rules parse will only return true or false which would overwrite the variable I would want to store. To get the variable, we use 'copy'. So a re-cap: parse/case/all This will parse but lower and uppercase will make a difference and it won't care about whitespace. read %if.aas This will use the text in if.aas to parse on, the 'call/wait' above creates this information. [thru interface copy dev-null thru "broadcast" copy broadcast to #"^/" copy ifconfig to end] This line is your 'word rules' or how the parsing will be done. In this case we are going to read 'thru' interface. Interface is the first item in interface-arp-check (see above), which in this case is "hme0". Once we have something that matches, we copy everything into a variable called 'dev-null' until we find the term "broadcast". Because we used the /case option broadcase MUST be lowercase, there are both an uppercase and lowercase broadcast in the ifconfig -a output...so this is required to get the right one. Once we find the right broadcast we copy it to a variable called broadcast. Everything is copied until the end of the line (#"^/" represents an end of line character) and finally we copy the rest of the text to a variable called ifconfig to the end. If we don't copy everything to the end we'll get a 'false' response back. If we do copy everything to the end we get a 'true' response back. We could also use the | to give multiple word rules. But that wasn't needed in this case. So now we have three variables set from this parse line: dev-null is the stuff I throw away, but it contains the beginning of the text upto and including the term broadcast. If we use thru it will put the term broadcast into dev-null. If we used 'to' then dev-null would stop right before the term broadcast. Since we don't care for the term broadcast, we only want what comes right after it we'll let dev-null claim it. broadcast has everything from right after the term broadcast (in lowercase letters) to the end of the line. This will be the broadcast address of the interface. ifconfig has everything after that. Since we may have to loop through the remaining interfaces we store this for future reference. Although each interface (in this script) starts over from scratch since we don't know what order thy put the interfaces in the config file.} call/wait "rm tmp.aas if.aas" tmp: call/wait/output join "/usr/sbin/ping " broadcast dev-null {This line takes the IP address we got from the parsing above and pings it. This will ping the entire network, each machine on the network will respond unless ping has been disabled. We do this to fill up the firewall's ARP table with all the hosts it can find. The results are put in the scratch variable, dev-null.} file: join interface ".ignore" if/else exists? to-file file: join interface ".ignore" [ call/wait join "/usr/sbin/arp -a | grep " join interface join " | grep -v ' S' | fgrep -v -f /rebol/" join interface ".ignore > tmp.aas" ] [ call/wait join "/usr/sbin/arp -a | grep " join interface " | grep -v ' S' > tmp.aas" ] {The lines above check to see if there is a local file called <interface>.ignore, such as hme0.ignore or qfe0.ignore. These files would contain the IP address of hosts that are expected to be seen on that interface, such as the POP router for the external interface.} if greater? length? read %tmp.aas 0 [ ifconfig: read %tmp.aas append msg join "The following machines were found outside interface " join interface join ": " join #"^/" ifconfig ] remove head interface-arp-check ] ] {Next we check to see if anything was found by testing the size of tmp.aas, if it's greater than 0 there were machines found. If machines were found we append them to msg (this is the body of an email message that gets sent if there are any critical alerts).} Questions? Wayne --- Wayne Pierce Director of Service Development Athena Security