Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Record your dynamic WAN IP addresses

A launchd + shell script exercise to record your DSL router's dynamic WAN IP addresses. Requires some customization on your part. Use at your own risk.

1. create the laund item in /Library/LaunchDaemons

# yourname=$(/usr/bin/logname)
/usr/bin/sudo /usr/bin/nano /Library/LaunchDaemons/net.$(/usr/bin/logname).wanip.update.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Disabled</key>
	<true/>
	<key>GroupName</key>
	<string>yourname</string>
	<key>Label</key>
	<string>net.yourname.wanip.update</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Users/yourname/Library/wanip.sh</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>StartInterval</key>
	<integer>20</integer>
	<key>UserName</key>
	<string>yourname</string>
</dict>
</plist>


#-------------------------


/usr/bin/groups
/usr/bin/sudo /usr/sbin/chown root:wheel /Library/LaunchDaemons/net.yourname.wanip.update.plist
#/usr/bin/sudo /usr/sbin/chown root:admin /Library/LaunchDaemons/net.yourname.wanip.update.plist
/usr/bin/sudo /bin/chmod 0644 /Library/LaunchDaemons/net.yourname.wanip.update.plist

# after creating ~/Library/wanip.sh below
/usr/bin/sudo /bin/launchctl load -w /Library/LaunchDaemons/net.yourname.wanip.update.plist 2>/dev/null
#/usr/bin/sudo /bin/launchctl unload -w /Library/LaunchDaemons/net.yourname.wanip.update.plist 2>/dev/null

/usr/bin/sudo /bin/launchctl list
/usr/bin/sudo /usr/bin/fs_usage  | /usr/bin/egrep -i wanip


2. create a shell script that will be run by the launchd item at the specified intervals in seconds (here: every 20 seconds)

#!/bin/sh

# cat ~/Library/wanip.sh   (/Users/yourname/Library/wanip.sh)
# /usr/sbin/chown $(/usr/bin/logname):$(/usr/bin/logname) ~/Library/wanip.sh
# /bin/chmod 0744 ~/Library/wanip.sh

# write stdout & stderr to console.log in /Library/Logs/Console/
exec >/dev/console 2>&1   

declare last_line_closed last_line_offline newfile old_wanip time wanip

declare IF='en0'
declare wanip_record_file="${HOME}/Library/wanip_record.txt"

# try to find your router_wanip_site by surfing to the IP addresses returned by the following commands:
# route -n get default | egrep interface | awk '{print $NF}'
# ipconfig getoption en0 router
# ipconfig getoption en0 domain_name_server

declare router_wanip_site='http://xxxx.xx/xxx.htm'
#declare router_wanip_site='http://checkip.dyndns.org'   # alternative


/bin/sleep 3

/usr/sbin/ipconfig waitall

if [[ "$(/sbin/route -n get default | /usr/bin/egrep interface | /usr/bin/awk '{print $NF}')" == "${IF}" ]]; then

   /usr/bin/curl -I -L -s --max-time 10 "${router_wanip_site}" 1>/dev/null
   if [[ $? -ne 0 ]]; then exit 0; fi

   # match first IP address with egrep
   wanip="$(/usr/bin/curl -L -s --max-time 10 "${router_wanip_site}" | \
              /usr/bin/egrep -o -m 1 ' ([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}')"
   if [[ $? -ne 0 ]]; then exit 0; fi   
   wanip="${wanip// /}"

   # alternative with sed for matching a line with a characteristic string plus IP address
   #wanip="$(/usr/bin/curl -L -s --max-time 10 "${router_wanip_site}" | \
              #/usr/bin/sed -E -n -e '/STRING: /{s/^.+ ([[:digit:]\.]+).*$/\1/p;q;}')"
   #if [[ $? -ne 0 ]]; then exit 0; fi   


   time="$(/bin/date +%Y-%m-%d-%H.%M.%S-%Z)"

   if [[ -n "${wanip}" ]]; then 
      old_wanip="$(/usr/bin/sed -E -n -e '$,$s/^.+ ([[:digit:]\.]+).*$/\1/p' "${wanip_record_file}")"
      if [[ "${wanip}" == "${old_wanip}" ]]; then exit 0; fi
      echo "${time}          ${wanip}" >> "${wanip_record_file}"
   else
      last_line_closed="$(/usr/bin/sed -E -n -e '$,$s/^.+ (closed).*$/\1/p' "${wanip_record_file}")"
      if [[ -n "${last_line_closed}" ]]; then exit 0; fi
      echo "${time}          connection closed" >> "${wanip_record_file}"
   fi

else

   last_line_offline="$(/usr/bin/sed -E -n -e '$,$s/^.+ (offline).*$/\1/p' "${wanip_record_file}")"
   if [[ -n "$last_line_offline" ]]; then exit 0; fi
   time="$(/bin/date +%Y-%m-%d-%H.%M.%S-%Z)"
   echo "${time}          offline" >> "${wanip_record_file}"

fi

if [[ $(/usr/bin/stat -f %z "${wanip_record_file}") -gt 31457280 ]]; then
   newfile="${wanip_record_file}-$(/bin/date +%Y-%m-%d-%H.%M.%S-%Z)"
   /bin/mv "${wanip_record_file}" "${newfile}"
fi

exit 0

File upload with curl & AppleScript

upload a file by using curl + AppleScript
man curl 2>/dev/null | less -p '-T/--upload-file'
tell application "Finder" to do shell script "curl -T ~/resume.doc ftp://username:password@ftp.myserver.com/resume.doc"

Ping a port with hping3

# cf. http://trac.macports.org/wiki/InstallingMacPorts
/opt/local/bin/port info hping3
/usr/bin/sudo /opt/local/bin/port install hping3

hping3 --help


# Terminal window 1
alias sudo=/usr/bin/sudo
alias tcpdump=/usr/sbin/tcpdump
#sudo tcpdump -s0 -xX -i lo0 port 4678 and host localhost
sudo tcpdump -s0 -vvv -i lo0 port 4678 and host localhost


# Terminal window 2
alias sudo=/usr/bin/sudo
alias hping3=/opt/local/sbin/hping3
sudo hping3 -I lo0 -s 4678 -c 1 localhost -p 4678
sudo hping3 -S -I lo0 -d 995 -s 4678 -c 1 localhost -p 4678
sudo hping3 -SA -I lo0 -d 995 -w 200 -s 4678 -c 1 localhost -p 4678
sudo hping3 -SA -M 3000 -I lo0 -d 995 -w 65 -s 4678 -c 1 localhost -p 4678
sudo hping3 -DV -SA -I lo0 -s 4678 -a 192.168.1.100 -c 1 localhost -p 4678


#----------------------------------------


# some corresponding ipfw rules for testing purposes 
# (just place them at the beginning of your ipfw rule set)

# not me to me & me to not me
/sbin/ipfw -q add count log all from not me to me 4678 in
/sbin/ipfw -q add count log all from me to not me 4678 out

# any to me & me to any
/sbin/ipfw -q add count log all from any to me 4678 in
/sbin/ipfw -q add count log all from me to any 4678 out
    
# any to any
/sbin/ipfw -q add count log all from any to any 4678

Analyze internet traffic volume with dynamic ipfw rules

# cf. Example ipfw ruleset, http://codesnippets.joyent.com/posts/show/1267
# cf. also http://codesnippets.joyent.com/posts/show/1729

man ipfw 2>/dev/null | less -p "If the ruleset"
man ipfw 2>/dev/null | less -p "These dynamic rules"
man ipfw 2>/dev/null | less -p "All rules"

man ipfw 2>/dev/null | less -p "STATEFUL FIREWALL"     # press [n]
man ipfw 2>/dev/null | less -p "SYSCTL VARIABLES"
man ipfw 2>/dev/null | less -p "EXAMPLES"
man ipfw 2>/dev/null | less -p "DYNAMIC RULES"

/usr/bin/sudo /sbin/ipfw -d -e -t list
/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/sed -E -n -e '1,/^## Dynamic rules/p'
/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/sed -E -n -e '/^## Dynamic rules/,$p'
/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/awk '/^## Dynamic rules/,/^$/ {print $0}'
/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/awk '/<->/ {print $0}'
/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/awk '{ if ( $0 ~ /<->/ ) {print $0}}'

/usr/bin/sudo /sbin/ipfw -d -e -t list | grep RULENUM
/usr/bin/sudo /sbin/ipfw -d -e -t list | grep IPADDR

/usr/sbin/sysctl -a | egrep 'tcp'
/usr/sbin/sysctl -a | egrep 'net.inet'
/usr/sbin/sysctl -a | egrep '\.fw'
/usr/sbin/sysctl -a | egrep 'ip.fw'
/usr/sbin/sysctl -a | egrep 'li[fv]e'
/usr/sbin/sysctl -a | egrep 'ip.fw.+life'

/usr/sbin/sysctl -n net.inet.tcp.always_keepalive
/usr/sbin/sysctl -n net.inet.ip.fw.dyn_keepalive
/usr/sbin/sysctl -n net.inet.ip.fw.dyn_buckets
/usr/sbin/sysctl -n net.inet.ip.fw.dyn_count
/usr/sbin/sysctl -n net.inet.ip.fw.dyn_max


# list all dynamic ipfw rules

function ipfwtraffic() {

   declare args argsregex bytes megabytes

   if [[ $# -eq 0 ]]; then

      /usr/bin/sudo /sbin/ipfw -d -e -t list | \
         /usr/bin/awk '/<->/ {printf "%-10s %-10s %-20s %-10s %-20s %-10s %-10s\n", $3, $6, $7, $8, $10, $11, $1}' | \
         /usr/bin/sort -bu | while IFS=" " read  bytes proto ipnum1 port1 ipnum2 port2 rulenum; do

      # byte
      #bytes=$(printf "%s\n" "${bytes}" | /usr/bin/awk '{ total = total + $1 } END { print total }')
      #printf "\e[1mbytes\e[m: %-17s %-10s %-40s \e[1mrule\e[m: %-15s \e[1mports\e[m: %-15s\n" \
           #"${bytes}" "${proto}" "${ipnum1}  ::  ${ipnum2}" "${rulenum}" "${port1}  ${port2}"

      # mega byte
      megabytes=$(printf "%s\n" "${bytes}" | /usr/bin/awk '{ total = (total + $1) / (1024*1024.0) } END { print total }')
      printf "\e[1mmbytes\e[m: %-17s %-10s %-40s \e[1mrule\e[m: %-15s \e[1mports\e[m: %-15s\n" \
           "${megabytes}" "${proto}" "${ipnum1}  ::  ${ipnum2}" "${rulenum}" "${port1}  ${port2}"

      #done | /usr/bin/sort -rn -k 2,2
      done | /usr/bin/sort -rn -k 2,2 | egrep -v '^[^ ]+ +[^ ]+e[^ ]+'

   else

      args="${@}"
      if [[ "${args}" != "${args//[^. [:digit:]]/}" ]]; then 
         printf "%s\n" 'Found at least one invalid rule number or IP address!'
         return 1
      fi

      if [[ "${args//[ [:digit:]]/}" == '' ]]; then 
         argsregex="^0*(${args// /|})"    #  ipfw rule numbers 
      else
         argsregex="(${args// /|})"    #  IP addresses
      fi
    
      #echo $argsregex

      /usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
         /usr/bin/awk '/<->/ {printf "%-10s %-10s %-20s %-10s %-20s %-10s %-10s\n", $3, $6, $7, $8, $10, $11, $1}' | \
         /usr/bin/sort -bu | while IFS=" " read  bytes proto ipnum1 port1 ipnum2 port2 rulenum; do

      # byte
      #bytes=$(printf "%s\n" "${bytes}" | /usr/bin/awk '{ total = total + $1 } END { print total }')
      #printf "\e[1mbytes\e[m: %-17s %-10s %-40s \e[1mrule\e[m: %-15s \e[1mports\e[m: %-15s\n" \
           #"${bytes}" "${proto}" "${ipnum1}  ::  ${ipnum2}" "${rulenum}" "${port1}  ${port2}"

      # mega byte
      megabytes=$(printf "%s\n" "${bytes}" | /usr/bin/awk '{ total = (total + $1) / (1024*1024.0) } END { print total }')
      printf "\e[1mmbytes\e[m: %-17s %-10s %-40s \e[1mrule\e[m: %-15s \e[1mports\e[m: %-15s\n" \
           "${megabytes}" "${proto}" "${ipnum1}  ::  ${ipnum2}" "${rulenum}" "${port1}  ${port2}"

      #done | /usr/bin/sort -rn -k 2,2
      done | /usr/bin/sort -rn -k 2,2 | egrep -v '^[^ ]+ +[^ ]+e[^ ]+'

   fi

   return 0
}



# usage:
# ipfwtraffic
# ipfwtraffic [rulenum1] [rulenum2] [rulenum3] ...
# ipfwtraffic [ipaddr1] [ipaddr2] [ipaddr3] ...


ipfwtraffic
ipfwtraffic  9600 10600 11000
ipfwtraffic xx.xxx.xx.xxx xx.xxx.xx.xx

ipfwtraffic | grep 'xx.xxx.xx.xx'



#------------------------------------------------------------------------------



# summarize pairs of IP addresses

function ipfwdynstats() {

   declare args argsregex dynrules ipaddr_pairs

   OIFS=${IFS}
   IFS=$'\n'

   if [[ $# -eq 0 ]]; then

      ipaddr_pairs=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/awk '/<->/ {print $7, $10}' | /usr/bin/sort -bu))
      dynrules=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/awk '/<->/ {print $7, $8, $10, $11, $6, $2, $3, $1}' | /usr/bin/sort -bu))

   else

      args="${@}"
      if [[ "${args}" != "${args//[^. [:digit:]]/}" ]]; then 
         printf "%s\n" 'Found at least one invalid rule number or IP address!'
         return 1
      fi

      if [[ "${args//[ [:digit:]]/}" == '' ]]; then 
         argsregex="^0*(${args// /|})"    #  ipfw rule numbers 
      else
         argsregex="(${args// /|})"    #  IP addresses
      fi
    
      #echo $argsregex

      ipaddr_pairs=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
           /usr/bin/awk '/<->/ {print $7, $10}' | /usr/bin/sort -bu))
      dynrules=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
           /usr/bin/awk '/<->/ {print $7, $8, $10, $11, $6, $2, $3, $1}' | /usr/bin/sort -bu))

   fi


for ((i=0; i < "${#ipaddr_pairs[@]}"; i++)); do 

   # byte
   #bytesum=$(printf "%s\n" "${dynrules[@]}" | \
        #/usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$7 }" | \
        #/usr/bin/awk '{ total = total + $1 } END { print total }')

   # mega byte
   bytesum=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$7 }" | \
        /usr/bin/awk '{ total = (total + $1) / (1024*1024.0) } END { print total }')

   proto=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$5 }" | \
        /usr/bin/sort -bu)

   rule=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$NF }" | \
        /usr/bin/sort -bu)

   ports=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$2, \$4 }" | \
        /usr/bin/sort -bu)

   # byte
   #printf "%-15s %-10s %-40s %-30s \e[1m%-30s\e[m\n" \
        #"bytes: ${bytesum}" "${proto//[[:cntrl:]]/, }" "${ipaddr_pairs[${i}]% *}  ::  ${ipaddr_pairs[${i}]#* }" \
        #"rules: ${rule//[[:cntrl:]]/, }" "ports: ${ports//[[:cntrl:]]/, }"

   # mega byte
   printf "\e[1mmbytes\e[m: %-15s %-10s %-40s \e[1mrules\e[m: %-25s \e[1mports\e[m: %-30s\n" \
        "${bytesum}" "${proto//[[:cntrl:]]/, }" "${ipaddr_pairs[${i}]% *}  ::  ${ipaddr_pairs[${i}]#* }" \
        "${rule//[[:cntrl:]]/, }" "${ports//[[:cntrl:]]/, }"

#done | /usr/bin/sort -rn -k 2,2
done | /usr/bin/sort -rn -k 2,2 | /usr/bin/egrep -v '^[^ ]+ +[^ ]+e[^ ]+'

   export IFS=${OIFS}
   return 0
}

# usage:
# ipfwdynstats
# ipfwdynstats [rulenum1] [rulenum2] [rulenum3] ...
# ipfwdynstats [ipaddr1] [ipaddr2] [ipaddr3] ...


ipfwdynstats
ipfwdynstats  5200 12700
ipfwdynstats xx.xxx.xx.xxx xxx.xxx.xx.xxx



#------------------------------------------------------------------------------



# list port-specific internet traffic

function porttraffic() {

   declare args argsregex dynrules ipaddr_pairs

   OIFS=${IFS}
   IFS=$'\n'

   if [[ $# -eq 0 ]]; then
   
      printf "%s\n" 'No port number given!'
      return 1
   
   elif [[ $# -eq 1 ]]; then

      ipaddr_pairs=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && ( \$8 == "${1}" || \$11 == "${1}" ) ) {print \$7, \$10 }}" | /usr/bin/sort -bu))

      dynrules=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && ( \$8 == "${1}" || \$11 == "${1}" ) ) {print \$7, \$8, \$10, \$11, \$6, \$2, \$3, \$1} }" | \
         /usr/bin/sort -bu))

   else

      args="${@:2}"   # all arguments starting with the second
      if [[ "${args}" != "${args//[^. [:digit:]]/}" ]]; then 
         printf "%s\n" 'Found at least one invalid rule number or IP address!'
         return 1
      fi

      if [[ "${args//[ [:digit:]]/}" == '' ]]; then 
         argsregex="^0*(${args// /|})"    #  ipfw rule numbers 
      else
         argsregex="(${args// /|})"    #  IP addresses
      fi
    
      #echo $argsregex

      ipaddr_pairs=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && ( \$8 == "${1}" || \$11 == "${1}" ) ) {print \$7, \$10 }}" | /usr/bin/sort -bu))


      dynrules=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && ( \$8 == "${1}" || \$11 == "${1}" ) ) {print \$7, \$8, \$10, \$11, \$6, \$2, \$3, \$1}}" | \
         /usr/bin/sort -bu))

   fi


for ((i=0; i < "${#ipaddr_pairs[@]}"; i++)); do 

   # byte
   #bytesum=$(printf "%s\n" "${dynrules[@]}" | \
        #/usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$7 }" | \
        #/usr/bin/awk '{ total = total + $1 } END { print total }')

   # mega byte
   bytesum=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$7 }" | \
        /usr/bin/awk '{ total = (total + $1) / (1024*1024.0) } END { print total }')

   proto=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$5 }" | \
        /usr/bin/sort -bu)

   rule=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$NF }" | \
        /usr/bin/sort -bu)

   ports=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$2, \$4 }" | \
        /usr/bin/sort -bu)

   # byte
   #printf "%-15s %-10s %-40s %-30s \e[1m%-30s\e[m\n" \
        #"bytes: ${bytesum}" "${proto//[[:cntrl:]]/, }" "${ipaddr_pairs[${i}]% *}  ::  ${ipaddr_pairs[${i}]#* }" \
        #"rules: ${rule//[[:cntrl:]]/, }" "ports: ${ports//[[:cntrl:]]/, }"

   # mega byte
   printf "\e[1mmbytes\e[m: %-15s %-10s %-40s \e[1mrules\e[m: %-25s \e[1mports\e[m: %-30s\n" \
        "${bytesum}" "${proto//[[:cntrl:]]/, }" "${ipaddr_pairs[${i}]% *}  ::  ${ipaddr_pairs[${i}]#* }" \
        "${rule//[[:cntrl:]]/, }" "${ports//[[:cntrl:]]/, }"

#done | /usr/bin/sort -rn -k 2,2
done | /usr/bin/sort -rn -k 2,2 | /usr/bin/egrep -v '^[^ ]+ +[^ ]+e[^ ]+'

   export IFS=${OIFS}
   return 0
}


# usage:
# porttraffic [portnum]
# porttraffic [portnum] [rulenum1] [rulenum2] [rulenum3] ...
# porttraffic [portnum] [ipaddr1] [ipaddr2] [ipaddr3] ...


porttraffic 80
porttraffic 80 5200 12700 7100
porttraffic 80 xx.xxx.xx.xxx xxx.xxx.xx.xxx



#------------------------------------------------------------------------------



# list rule-specific internet traffic

function ruletraffic() {

   declare args argsregex dynrules ipaddr_pairs

   OIFS=${IFS}
   IFS=$'\n'

   if [[ $# -eq 0 ]]; then
   
      printf "%s\n" 'No rule number given!'
      return 1
   
   elif [[ $# -eq 1 ]]; then

      ipaddr_pairs=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && \$1 == "${1}" ) {print \$7, \$10 }}" | /usr/bin/sort -bu))

      dynrules=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && \$1 == "${1}" ) {print \$7, \$8, \$10, \$11, \$6, \$2, \$3, \$1} }" | \
         /usr/bin/sort -bu))

   else

      args="${@:2}"   # all arguments starting with the second
      if [[ "${args}" != "${args//[^. [:digit:]]/}" ]]; then 
         printf "%s\n" 'Found at least one invalid rule number or IP address!'
         return 1
      fi

      if [[ "${args//[ [:digit:]]/}" == '' ]]; then 
         argsregex="^0*(${args// /|})"    #  ipfw rule numbers 
      else
         argsregex="(${args// /|})"    #  IP addresses
      fi
    
      #echo $argsregex

      ipaddr_pairs=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && \$1 == "${1}" ) {print \$7, \$10 }}" | /usr/bin/sort -bu))


      dynrules=($(/usr/bin/sudo /sbin/ipfw -d -e -t list | /usr/bin/egrep "${argsregex}" | \
         /usr/bin/awk "{ if ( \$0 ~ /<->/ && \$1 == "${1}" ) {print \$7, \$8, \$10, \$11, \$6, \$2, \$3, \$1}}" | \
         /usr/bin/sort -bu))

   fi


for ((i=0; i < "${#ipaddr_pairs[@]}"; i++)); do 

   # byte
   #bytesum=$(printf "%s\n" "${dynrules[@]}" | \
        #/usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$7 }" | \
        #/usr/bin/awk '{ total = total + $1 } END { print total }')

   # mega byte
   bytesum=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$7 }" | \
        /usr/bin/awk '{ total = (total + $1) / (1024*1024.0) } END { print total }')

   proto=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$5 }" | \
        /usr/bin/sort -bu)

   rule=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$NF }" | \
        /usr/bin/sort -bu)

   ports=$(printf "%s\n" "${dynrules[@]}" | \
        /usr/bin/awk "{ if ( \$1 == \"${ipaddr_pairs[${i}]% *}\" && \$3 == \"${ipaddr_pairs[${i}]#* }\" ) print \$2, \$4 }" | \
        /usr/bin/sort -bu)

   # byte
   #printf "%-15s %-10s %-40s %-30s \e[1m%-30s\e[m\n" \
        #"bytes: ${bytesum}" "${proto//[[:cntrl:]]/, }" "${ipaddr_pairs[${i}]% *}  ::  ${ipaddr_pairs[${i}]#* }" \
        #"rules: ${rule//[[:cntrl:]]/, }" "ports: ${ports//[[:cntrl:]]/, }"

   # mega byte
   printf "\e[1mmbytes\e[m: %-15s %-10s %-40s \e[1mrules\e[m: %-25s \e[1mports\e[m: %-30s\n" \
        "${bytesum}" "${proto//[[:cntrl:]]/, }" "${ipaddr_pairs[${i}]% *}  ::  ${ipaddr_pairs[${i}]#* }" \
        "${rule//[[:cntrl:]]/, }" "${ports//[[:cntrl:]]/, }"

#done | /usr/bin/sort -rn -k 2,2
done | /usr/bin/sort -rn -k 2,2 | /usr/bin/egrep -v '^[^ ]+ +[^ ]+e[^ ]+'

   export IFS=${OIFS}
   return 0
}


# usage:
# ruletraffic [rulenum]
# ruletraffic [rulenum1] [rulenum2] [rulenum3] ...

ruletraffic 5200
ruletraffic 5200 12700 7100

Block internet traffic to specified web sites on the fly

man 8 route
/sbin/route -n get default
/sbin/route -n get default | grep -w gateway
/sbin/route -n get default | grep interface | awk '{print $NF}'

/usr/bin/dig +short www.web_site.com                                 # get IPNUM
/usr/bin/sudo /sbin/route -n add -host IPNUM 127.0.0.1 -blackhole    # block IPNUM
/usr/sbin/netstat -rn | grep IPNUM                                   # show routing table
/usr/bin/sudo /sbin/route delete IPNUM 127.0.0.1                     # undo blocking


function blocksite() {
   declare ipaddr ipnum
   if [[ "${1//localhost/}" == '' ]] || [[ "${1//127.0.0.1/}" == '' ]]; then 
      printf "%s\n" 'Argument "localhost" is not permitted!'
      return 1
   fi
   ipnum=$(/usr/bin/dig +short "${1}" | /usr/bin/sed -E -n -e 's/^(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3})$/\1/p'; exit ${PIPESTATUS[0]})
   if [[ $? -ne 0 ]] || [[ -z "${ipnum}" ]]; then 
      printf "%s\n%s\n" "Are you connected to the internet?" "man dig could not find the IP address of: ${1}"
      return 1
   fi
   OIFS=${IFS}
   IFS=$' \t\n'
   for ipaddr in ${ipnum//[[:cntrl:]]/ }; do
      /usr/bin/sudo /sbin/route -n add -host ${ipaddr} 127.0.0.1 -blackhole >/dev/null 2>&1
   done
   export IFS=${OIFS}
   printf "%s\n" "... blocking internet access to site: ${1} with IP address: ${ipnum//[[:cntrl:]]/, }"
   return 0
}


function unblocksite() {
   declare ipaddr ipnum
   if [[ "${1//localhost/}" == '' ]] || [[ "${1//127.0.0.1/}" == '' ]]; then 
      printf "%s\n" 'Argument "localhost" is not permitted!'
      return 1
   fi
   ipnum=$(/usr/bin/dig +short "${1}" | /usr/bin/sed -E -n -e 's/^(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3})$/\1/p'; exit ${PIPESTATUS[0]})
   if [[ $? -ne 0 ]] || [[ -z "${ipnum}" ]]; then 
      printf "%s\n%s\n" "Are you connected to the internet?" "man dig could not find the IP address of: ${1}"
      return 1
   fi
   OIFS=${IFS}
   IFS=$' \t\n'
   for ipaddr in ${ipnum//[[:cntrl:]]/ }; do
      /usr/bin/sudo /sbin/route delete ${ipaddr} 127.0.0.1 >/dev/null 2>&1
   done
   export IFS=${OIFS}
   printf "%s\n" "... unblocking internet access to site: ${1} with IP address: ${ipnum//[[:cntrl:]]/ }"
   return 0
}


function unblockall() {
   declare ipaddr ipnums
   ipnums=$(/usr/sbin/netstat -rnf inet | /usr/bin/awk '{ if ( $2 == "127.0.0.1" && $3 == "UGHSB" ) print $1 }'; exit ${PIPESTATUS[0]})
   if [[ $? -ne 0 ]] || [[ -z "${ipnums}" ]]; then 
      printf "%s\x21\n" "No IP addresses to unblock"
      return 1
   fi
   OIFS=${IFS}
   IFS=$' \t\n'
   for ipaddr in ${ipnums//[[:cntrl:]]/ }; do
      /usr/bin/sudo /sbin/route delete ${ipaddr} 127.0.0.1 >/dev/null 2>&1
   done
   export IFS=${OIFS}
   printf "%s\n" "... unblocking internet access to IP addresses: ${ipnums//[[:cntrl:]]/ }"
   return 0
}


function showblocked() {
   ipnums=$(/usr/sbin/netstat -rnf inet | /usr/bin/awk '{ if ( $2 == "127.0.0.1" && $3 == "UGHSB" ) print $1 }'; exit ${PIPESTATUS[0]})
   printf "%s\n" "Blocked IP addresses: ${ipnums//[[:cntrl:]]/, }"
   return 0
}



blocksite codesnippets.joyent.com
netstat -rnf inet | grep UGHSB
showblocked
open http://codesnippets.joyent.com
unblocksite codesnippets.joyent.com

blocksite codesnippets.joyent.com
blocksite www.google.com
netstat -rnf inet | grep UGHSB
showblocked
open http://www.google.com
unblockall

Enable internet traffic via specified ports through ipfw

# cf. Example ipfw ruleset, http://codesnippets.joyent.com/posts/show/1267

# choose appropriate numbers for num1 & num2 according to your ipfw ruleset

/usr/bin/sudo /sbin/ipfw list
/usr/sbin/sysctl -n net.inet.ip.fw.autoinc_step

function free_ipfw_rule_num() {
   declare -i num1=6701 num2=6799 lastipfwnum
   if [[ $(/usr/sbin/sysctl -n net.inet.ip.fw.autoinc_step) -ne 100 ]]; then 
      printf "%s\x21\n" "sysctl -n net.inet.ip.fw.autoinc_step is not set to 100"
      return 1
   fi
   lastipfwnum=$(/usr/bin/sudo /sbin/ipfw list | /usr/bin/tail -n 2 | /usr/bin/head -n 1 | /usr/bin/awk '{print $1}')
   if [[ $num2 -ge $lastipfwnum ]]; then 
      printf "%s\x21\n" "${num2} is greater than or equal to ${lastipfwnum}"
      return 1
   fi
   while $(/usr/bin/sudo /sbin/ipfw show ${num1} &>/dev/null) ; do
      let "num1 += 1"
      if [[ $num1 -gt $num2 ]]; then num1=; break; return 1; fi
   done
   printf "%s\n" "${num1}"
   return 0
}


function openport() {
   declare portnum rulenum
   if [[ $# -ne 1 ]]; then printf "%s\n" "Wrong number of arguments: $#"; return 1; fi
   portnum="${1//[^[:digit:]]/}"
   if [[ -z $portnum ]]; then printf "%s\n" "No valid port number given: ${1}"; return 1; fi
   if [[ $portnum -gt 65535 ]]; then printf "%s\n" "Given port number is greater than 65535: ${portnum}"; return 1; fi
   rulenum=$(free_ipfw_rule_num)
   /usr/bin/sudo /sbin/ipfw -q add ${rulenum} allow all from any to any dst-port ${portnum} keep-state
   printf "%s\n" "... opening ipfw rule no. ${rulenum} for internet access via port ${portnum}"
   return 0
}


function closeport() {
   declare portnum rulenum
   if [[ $# -ne 1 ]]; then printf "%s\n" "Wrong number of arguments: $#"; return 1; fi
   portnum="${1//[^[:digit:]]/}"
   if [[ -z $portnum ]]; then printf "%s\n" "No valid port number given: ${1}"; return 1; fi
   if [[ $portnum -gt 65535 ]]; then printf "%s\n" "Given port number is greater than 65535: ${portnum}"; return 1; fi
   rulenum=$(/usr/bin/sudo /sbin/ipfw list | /usr/bin/awk "/from +any +to +any +dst-port +${portnum} +keep-state[[:space:]]*$/ {print \$1