TCP/OS Fingerprinting Tools – p0f and nmap

By | 2011/12/22

The particular way an operating system or device sends and receives TCP packets provides a unique fingerprint. TCP header information such as the window size, TTL, overall SYN packet size, MSS, MTU and so forth can help identify the OS. This is known as OS fingerprinting. The best known passive TCP fingerprint tool is p0f, while an example of an active fingerprinter is nmap.

I’ll show you some quick tips on using p0f and also nmap!


Fingerprinting with p0f

Note: p0f has unfortunately been abandoned. So it can be used to passively collect fingerprinting information, but it does not have a current database of operating systems or devices to resolve and identify.

Edit! ( p0f is back. The new version is a complete re-write. Updated blog post to come shortly.)

For p0f to work, you must either contact the outside host with a normal action such as web browsing, or have the outside host contact you. Alternatively, p0f can read from a pcap file as well.

Because of the use of inspecting and capturing packets, p0f needs to be run with sudo.

Step 1: In one terminal, issue the following command to start p0f listening, and leave that command running:

$ sudo p0f -A
[sudo] password for user: 
p0f - passive os fingerprinting utility, version 2.0.8
(C) M. Zalewski , W. Stearns 
p0f: listening (SYN+ACK) on 'eth0', 61 sigs (1 generic, cksum B253FA88), rule: 'all'.

Step 2: In another window, browse to a website as an example target.
Output looks like the following. Notice the ‘UNKNOWN’ results as this project has been unfortunately abandoned. You can however use the data provided as information gathered for TCP fingerprinting.

173.230.156.66:80 - UNKNOWN [S10:64:1:48:M1460,N,N,S:ZA:?:?] 
  -> 98.126.63.202:3037 (link: ethernet/modem)
206.12.19.7:80 - UNKNOWN [5792:55:1:60:M1460,S,T,N,W7:ZAT:?:?] (up: 4395 hrs) 
  -> 173.230.156.66:32928 (link: ethernet/modem)
128.31.0.51:80 - UNKNOWN [5792:52:1:60:M1460,S,T,N,W6:ZAT:?:?] (up: 1559 hrs) 
  -> 173.230.156.66:58958 (link: ethernet/modem)
173.230.156.66:80 - UNKNOWN [14480:64:1:60:M1460,S,T,N,W4:ZAT:?:?] (up: 5906 hrs) 
  -> 151.63.225.212:34013 (link: ethernet/modem)
173.230.156.66:80 - UNKNOWN [14480:64:1:60:M1460,S,T,N,W4:ZAT:?:?] (up: 5906 hrs) 
  -> 151.63.225.212:34014 (link: ethernet/modem)
173.230.156.66:80 - UNKNOWN [14480:64:1:60:M1460,S,T,N,W4:ZAT:?:?] (up: 5906 hrs) 
  -> 151.63.225.212:34015 (link: ethernet/modem)
173.230.156.66:80 - UNKNOWN [14480:64:1:60:M1460,S,T,N,W4:ZAT:?:?] (up: 5906 hrs) 
  -> 151.63.225.212:34016 (link: ethernet/modem)
173.230.156.66:80 - UNKNOWN [14480:64:1:60:M1460,S,T,N,W4:ZAT:?:?] (up: 5906 hrs) 
  -> 151.63.225.212:34017 (link: ethernet/modem)
173.230.156.66:80 - UNKNOWN [14480:64:1:60:M1460,S,T,N,W4:ZAT:?:?] (up: 5906 hrs) 
  -> 151.63.225.212:34018 (link: ethernet/modem)


Fingerprinting with nmap

nmap has fingerprinting capabilities but note this is an active tool which can potentially be detected by the target host or IDS/IPS. While this can get more accurate results, packet-altering devices such as firewalls or other devices can be problematic for active fingerprinting with nmap. Often results will say ‘OS: Cisco IOS’ or similar, where the firewall or network device is responding on behalf of the host you are trying to target.

As such, using nmap for fingerprinting is perhaps best for internal network troubleshooting and auditing with no firewalls in between you and the target host.

To detect the operating system with nmap, use tack capital O. (Note: nmap likewise requires sudo to run properly.)

$ sudo nmap -O targethost

Here is an example for scottlinux.com which is running Ubuntu Linux (unfortunately a poor example it appears):

$ sudo nmap -O 173.230.156.66
Password:

Starting Nmap 5.51 ( http://nmap.org ) at 2011-12-22 08:03 EST
Nmap scan report for li166-66.members.linode.com (173.230.156.66)
Host is up (0.033s latency).
Not shown: 996 filtered ports
PORT    STATE SERVICE
22/tcp  open  ssh
25/tcp  open  smtp
80/tcp  open  http
443/tcp open  https
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: IBM OS/400 V5R2M0 (93%), Linux 2.6.18 (92%), Raritan Dominion KX II KVM switch (92%), Bay Networks BayStack 450 switch (software version 3.1.0.22) (90%), Bay Networks BayStack 450 switch (software version 4.2.0.16) (90%), Apple iPhone 4 mobile phone (iOS 4.1) (90%), ASUS RT-N11 EZ or D-Link DI-524 WAP (89%), Dell Remote Access Controller (DRAC 5) (89%), Yamaha RX-V3900 audio receiver (89%), Canon PIXMA MP620, MX860, or MX870 printer (88%)
No exact OS matches for host (test conditions non-ideal).

OS detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.45 seconds

If desired, use tack v3 to increase verbosity:

$ sudo nmap -O -v3 173.230.156.66

Starting Nmap 5.51 ( http://nmap.org ) at 2011-12-22 08:16 EST
Initiating Ping Scan at 08:16
Scanning 173.230.156.66 [4 ports]
Completed Ping Scan at 08:16, 0.01s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 08:16
Completed Parallel DNS resolution of 1 host. at 08:16, 0.09s elapsed
DNS resolution of 1 IPs took 0.09s. Mode: Async [#: 2, OK: 1, NX: 0, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 08:16
Scanning li166-66.members.linode.com (173.230.156.66) [1000 ports]
Discovered open port 80/tcp on 173.230.156.66
Discovered open port 22/tcp on 173.230.156.66
Discovered open port 25/tcp on 173.230.156.66
Discovered open port 443/tcp on 173.230.156.66
Completed SYN Stealth Scan at 08:16, 13.52s elapsed (1000 total ports)
Initiating OS detection (try #1) against li166-66.members.linode.com (173.230.156.66)
Retrying OS detection (try #2) against li166-66.members.linode.com (173.230.156.66)
Nmap scan report for li166-66.members.linode.com (173.230.156.66)
Host is up (0.042s latency).
Scanned at 2011-12-22 08:16:12 EST for 22s
Not shown: 996 filtered ports
PORT    STATE SERVICE
22/tcp  open  ssh
25/tcp  open  smtp
80/tcp  open  http
443/tcp open  https
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
Aggressive OS guesses: IBM OS/400 V5R2M0 (94%), Linux 2.6.18 (93%), Raritan Dominion KX II KVM switch (93%), Bay Networks BayStack 450 switch (software version 3.1.0.22) (92%), Bay Networks BayStack 450 switch (software version 4.2.0.16) (92%), Apple iPhone 4 mobile phone (iOS 4.1) (91%), ASUS RT-N11 EZ or D-Link DI-524 WAP (91%), Sagem My du@l radio 700 Internet radio (91%), Dell Remote Access Controller (DRAC 5) (91%), Yamaha RX-V3900 audio receiver (90%)
No exact OS matches for host (test conditions non-ideal).
TCP/IP fingerprint:
SCAN(V=5.51%D=12/22%OT=22%CT=%CU=%PV=N%G=N%TM=4EF32DB2%P=x86_64-apple-darwin11.2.0)
SEQ(CI=RI)
ECN(R=N)
T1(R=N)
T1(R=Y%DF=N%TG=40%S=O%A=S+%F=AS%RD=0%Q=)
T2(R=Y%DF=N%TG=40%W=0%S=Z%A=S%F=AR%O=%RD=0%Q=)
T3(R=Y%DF=N%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
T4(R=Y%DF=N%TG=40%W=0%S=A%A=S%F=R%O=%RD=0%Q=)
T6(R=Y%DF=N%TG=40%W=0%S=A%A=S%F=R%O=%RD=0%Q=)
T7(R=Y%DF=N%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
U1(R=N)
IE(R=N)
IE(R=Y%DFI=N%TG=40%CD=S)


Read data files from: /opt/local/share/nmap
OS detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.66 seconds
           Raw packets sent: 3118 (142.366KB) | Rcvd: 50 (2.862KB)

Or I like to use the following options [sudo nmap -O -sV -T4 -d target] which provides the exact TCP/IP Fingerprint output at the bottom:

$ sudo nmap -O -sV -T4 -d 173.230.156.66
[sudo] password for user: 

Starting Nmap 5.00 ( http://nmap.org ) at 2011-12-22 05:38 PST
PORTS: Using top 1000 ports found open (TCP:1000, UDP:0, SCTP:0)
--------------- Timing report ---------------
  hostgroups: min 1, max 100000
  rtt-timeouts: init 500, min 100, max 1250
  max-scan-delay: TCP 10, UDP 1000, SCTP 10
  parallelism: min 0, max 0
  max-retries: 6, host-timeout: 0
  min-rate: 0, max-rate: 0
---------------------------------------------
NSE: Loaded 3 scripts for scanning.
mass_rdns: Using DNS server 74.207.242.5
mass_rdns: Using DNS server 74.207.241.5
Initiating SYN Stealth Scan at 05:38
Scanning li166-66.members.linode.com (173.230.156.66) [1000 ports]
Packet capture filter (device lo): dst host 173.230.156.66 and (icmp or ((tcp or udp or sctp) and (src host 173.230.156.66)))
Discovered open port 25/tcp on 173.230.156.66
Discovered open port 443/tcp on 173.230.156.66
Discovered open port 80/tcp on 173.230.156.66
Discovered open port 587/tcp on 173.230.156.66
Discovered open port 22/tcp on 173.230.156.66
Discovered open port 465/tcp on 173.230.156.66
Discovered open port 4242/tcp on 173.230.156.66
Completed SYN Stealth Scan at 05:38, 0.06s elapsed (1000 total ports)
Overall sending rates: 16963.24 packets / s, 746382.59 bytes / s.
Initiating Service scan at 05:38
Scanning 7 services on li166-66.members.linode.com (173.230.156.66)
Completed Service scan at 05:39, 44.57s elapsed (7 services on 1 host)
Packet capture filter (device lo): dst host 173.230.156.66 and (icmp or (tcp and (src host 173.230.156.66)))
Initiating OS detection (try #1) against li166-66.members.linode.com (173.230.156.66)
OS detection timingRatio() == (1324561142.611 - 1324561142.111) * 1000 / 500 == 1.000
Retrying OS detection (try #2) against li166-66.members.linode.com (173.230.156.66)
OS detection timingRatio() == (1324561144.862 - 1324561144.362) * 1000 / 500 == 1.000
Retrying OS detection (try #3) against li166-66.members.linode.com (173.230.156.66)
OS detection timingRatio() == (1324561147.119 - 1324561146.619) * 1000 / 500 == 1.002
Retrying OS detection (try #4) against li166-66.members.linode.com (173.230.156.66)
OS detection timingRatio() == (1324561150.851 - 1324561150.350) * 1000 / 500 == 1.000
Retrying OS detection (try #5) against li166-66.members.linode.com (173.230.156.66)
OS detection timingRatio() == (1324561153.087 - 1324561152.587) * 1000 / 500 == 1.002
Starting RPC scan against li166-66.members.linode.com (173.230.156.66)
NSE: Script scanning 173.230.156.66.
NSE: Starting runlevel 1 scan
Initiating NSE at 05:39
NSE: NSE Script Threads (1) running:
NSE: Starting skypev2-version against 173.230.156.66:4242.
NSE: Finished skypev2-version against 173.230.156.66:4242.
Completed NSE at 05:39, 0.01s elapsed
NSE: Script Scanning completed.
Host li166-66.members.linode.com (173.230.156.66) is up, received localhost-response (0.000048s latency).
Scanned at 2011-12-22 05:38:17 PST for 57s
Interesting ports on li166-66.members.linode.com (173.230.156.66):
Not shown: 993 closed ports
Reason: 993 resets
PORT     STATE SERVICE  REASON  VERSION
22/tcp   open  ssh      syn-ack OpenSSH 5.3p1 (protocol 2.0)
25/tcp   open  smtp     syn-ack Postfix smtpd
80/tcp   open  http     syn-ack Apache httpd
443/tcp  open  ssl/http syn-ack Apache httpd
465/tcp  open  ssl/smtp syn-ack Postfix smtpd
587/tcp  open  smtp     syn-ack Postfix smtpd
4242/tcp open  unknown  syn-ack
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port4242-TCP:V=5.00%I=7%D=12/22%Time=4EF332CF%P=i686-pc-linux-gnu%r(NUL
SF:L,124,"\x80c\0\0\x00622996\|com\.code42\.messaging\.security\.DHPublicK
SF:eyMessageY\xd4\0\0\0\xe20\x81\xdf0\x81\x97\x06\t\*\x86H\x86\xf7\r\x01\x
SF:03\x010\x81\x89\x02A\0\x91\xe9FAA\xd8G\xb6\xb5\x1fw#hmX\x12%\x90x\xda4\
SF:x9a5\x14EYk_KQ\xf5\x11s\\\xc8\x0b\xd5\xa6\x9e9EC\xc7\xeb\rM\x81\x12\xf8
SF:Th\x1c:\t\xba\xc1\xbe=\xaa\xec\xc0G\x17!\x02@Sf\xd0\x88\x91\"s\xafdY\x7
SF:f\xd5\^\x81\r%nB\x1e&_\x93\x82\xfc\xe3\xd9\x9fZ\x96<\xd0'T\x04\x13\xe5\
SF:$\xf5>\x7f\xbeud\xc2p\xae\x89U\xaa\xcf\x06ERm\xfa\xf6S\xd2\xf9\xaf\xe5\
SF:x02n\(\x02\x02\x01\xff\x03C\0\x02@\"\xc8\x81\x9c\x94&\x05i\xdf\x20\x89#
SF:w\xcd\xd0\[\xd7\xf0\xea\x1f`S\xd9B\xc6\x1d\r\xea\xad\)}\x02S\xd6ne\xa2\
SF:xd9\xe3\x88c\?aDk\xf3\xde\x17\x91\x11\xb7\\\x82'uvnA\xfa\xe5\xc2\xe2\xd
SF:8\xfe")%r(GenericLines,124,"\x80c\0\0\x00622996\|com\.code42\.messaging
SF:\.security\.DHPublicKeyMessageY\xd4\0\0\0\xe20\x81\xdf0\x81\x97\x06\t\*
SF:\x86H\x86\xf7\r\x01\x03\x010\x81\x89\x02A\0\x91\xe9FAA\xd8G\xb6\xb5\x1f
SF:w#hmX\x12%\x90x\xda4\x9a5\x14EYk_KQ\xf5\x11s\\\xc8\x0b\xd5\xa6\x9e9EC\x
SF:c7\xeb\rM\x81\x12\xf8Th\x1c:\t\xba\xc1\xbe=\xaa\xec\xc0G\x17!\x02@Sf\xd
SF:0\x88\x91\"s\xafdY\x7f\xd5\^\x81\r%nB\x1e&_\x93\x82\xfc\xe3\xd9\x9fZ\x9
SF:6<\xd0'T\x04\x13\xe5\$\xf5>\x7f\xbeud\xc2p\xae\x89U\xaa\xcf\x06ERm\xfa\
SF:xf6S\xd2\xf9\xaf\xe5\x02n\(\x02\x02\x01\xff\x03C\0\x02@\"\xc8\x81\x9c\x
SF:94&\x05i\xdf\x20\x89#w\xcd\xd0\[\xd7\xf0\xea\x1f`S\xd9B\xc6\x1d\r\xea\x
SF:ad\)}\x02S\xd6ne\xa2\xd9\xe3\x88c\?aDk\xf3\xde\x17\x91\x11\xb7\\\x82'uv
SF:nA\xfa\xe5\xc2\xe2\xd8\xfe")%r(GetRequest,125,"\x80c\0\0\x00622996\|com
SF:\.code42\.messaging\.security\.DHPublicKeyMessageY\xd4\0\0\0\xe30\x81\x
SF:e00\x81\x97\x06\t\*\x86H\x86\xf7\r\x01\x03\x010\x81\x89\x02A\0\x91\xe9F
SF:AA\xd8G\xb6\xb5\x1fw#hmX\x12%\x90x\xda4\x9a5\x14EYk_KQ\xf5\x11s\\\xc8\x
SF:0b\xd5\xa6\x9e9EC\xc7\xeb\rM\x81\x12\xf8Th\x1c:\t\xba\xc1\xbe=\xaa\xec\
SF:xc0G\x17!\x02@Sf\xd0\x88\x91\"s\xafdY\x7f\xd5\^\x81\r%nB\x1e&_\x93\x82\
SF:xfc\xe3\xd9\x9fZ\x96<\xd0'T\x04\x13\xe5\$\xf5>\x7f\xbeud\xc2p\xae\x89U\
SF:xaa\xcf\x06ERm\xfa\xf6S\xd2\xf9\xaf\xe5\x02n\(\x02\x02\x01\xff\x03D\0\x
SF:02A\0\x8d\|\xe6\x81\x9c`\xe7\x82\x86r\xf7\xb8\xa7\xb4\xc2L\xe1\xdc\xf0\
SF:xb5\xb4\t\x063B\xf7\xacG\xf5\xbe\xa1\$\xaa\xa7NRlh-\x02\x94\xdd\xb2<\xa
SF:a\xb26d\x0fO\xbey\xca\xbb\x96\xfc\xbd\xeb\x06E\xeb\xd1U`")%r(Help,124,"
SF:\x80c\0\0\x00622996\|com\.code42\.messaging\.security\.DHPublicKeyMessa
SF:geY\xd4\0\0\0\xe20\x81\xdf0\x81\x97\x06\t\*\x86H\x86\xf7\r\x01\x03\x010
SF:\x81\x89\x02A\0\x91\xe9FAA\xd8G\xb6\xb5\x1fw#hmX\x12%\x90x\xda4\x9a5\x1
SF:4EYk_KQ\xf5\x11s\\\xc8\x0b\xd5\xa6\x9e9EC\xc7\xeb\rM\x81\x12\xf8Th\x1c:
SF:\t\xba\xc1\xbe=\xaa\xec\xc0G\x17!\x02@Sf\xd0\x88\x91\"s\xafdY\x7f\xd5\^
SF:\x81\r%nB\x1e&_\x93\x82\xfc\xe3\xd9\x9fZ\x96<\xd0'T\x04\x13\xe5\$\xf5>\
SF:x7f\xbeud\xc2p\xae\x89U\xaa\xcf\x06ERm\xfa\xf6S\xd2\xf9\xaf\xe5\x02n\(\
SF:x02\x02\x01\xff\x03C\0\x02@WMP\?`\x12\x0bG;\xbc\xa3\xda\xfe5\xbcJVa\+N\
SF:x87UQ\xd9\*\x1b3}\x90\xb3ku\xa2\x94}\xa2\xda\xae\x960\r\x97\x83\x9d!1Ut
SF:\xbdZ\x85\x1cS\xf9\x8f\xe4\xa5\.\xde\xfe\xe2\xa1\xe4\xc3");
No exact OS matches for host (If you know what OS is running on it, see http://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=5.00%D=12/22%OT=22%CT=1%CU=39769%PV=N%DS=0%G=Y%TM=4EF33302%P=i686
OS:-pc-linux-gnu)SEQ(SP=103%GCD=1%ISR=10E%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M400CS
OS:T11NW4%O2=M400CST11NW4%O3=M400CNNT11NW4%O4=M400CST11NW4%O5=M400CST11NW4%
OS:O6=M400CST11)WIN(W1=8000%W2=8000%W3=8000%W4=8000%W5=8000%W6=8000)ECN(R=Y
OS:%DF=Y%T=40%W=8018%O=M400CNNSNW4%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%R
OS:D=0%Q=)T2(R=N)T3(R=Y%DF=Y%T=40%W=8000%S=O%A=S+%F=AS%O=M400CST11NW4%RD=0%
OS:Q=)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%
OS:A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%
OS:DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIP
OS:L=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Uptime guess: 25.542 days (since Sat Nov 26 16:38:31 2011)
Network Distance: 0 hops
TCP Sequence Prediction: Difficulty=259 (Good luck!)
IP ID Sequence Generation: All zeros
Final times for host: srtt: 48 rttvar: 3  to: 100000

Read from /usr/share/nmap: nmap-os-db nmap-rpc nmap-service-probes nmap-services.
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 57.09 seconds
           Raw packets sent: 1095 (51.990KB) | Rcvd: 2212 (98.808KB)

Note: You can submit OS fingerprints to the nmap database to contribute.

Also check out the nmap doc on OS detection which has more information. It’s always good to RTFM.



OS Detection with ping

And a good trick to know: a simple ping command can often help determine a target OS. Though if a firewall is responding on behalf of the host, results may vary and be skewed.

The TTL for Linux is typically 64 or 255.

The TTL for Windows is 128.

Linux host, see the ttl=64 results:

$ ping 192.168.1.215
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.041 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=0.049 ms
64 bytes from localhost (127.0.0.1): icmp_seq=5 ttl=64 time=0.040 ms
^C
--- localhost ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.029/0.043/0.056/0.009 ms

Windows host, see the ttl=128 results:

$ ping 10.112.12.30
PING 10.112.12.30 (10.112.12.30): 56 data bytes
64 bytes from 10.112.12.30: icmp_seq=0 ttl=128 time=0.622 ms
64 bytes from 10.112.12.30: icmp_seq=1 ttl=128 time=0.786 ms
64 bytes from 10.112.12.30: icmp_seq=2 ttl=128 time=0.704 ms
64 bytes from 10.112.12.30: icmp_seq=3 ttl=128 time=0.510 ms
64 bytes from 10.112.12.30: icmp_seq=4 ttl=128 time=0.913 ms
^C
--- 10.112.12.30 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.510/0.707/0.913/0.138 ms

Cool!

One thought on “TCP/OS Fingerprinting Tools – p0f and nmap

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.