Monday Nov 28, 2011

Netcat I/O enhancements

When Netcat integrated into OpenSolaris it was already clear that there will be couple of enhancements needed. The biggest set of the changes made after Solaris 11 Express was released brings various I/O enhancements to netcat shipped with Solaris 11. Also, since Solaris 11, the netcat package is installed by default in all distribution forms (live CD, text install, ...).

Now, let's take a look at the new functionality:

/usr/bin/netcat alternative program name (symlink)
-b bufsize I/O buffer size
-E use exclusive bind for the listening socket
-e program program to execute
-F no network close upon EOF on stdin
-i timeout extension of timeout specification
-L timeout linger on close timeout
-l -p port addr previously not allowed usage
-m byte_count Quit after receiving byte_count bytes
-N file pattern for UDP scanning
-I bufsize size of input socket buffer
-O bufsize size of output socket buffer
-R redir_spec port redirection
addr/port[/{tcp,udp}] syntax of redir_spec
-Z bypass zone boundaries
-q timeout timeout after EOF on stdin

Obviously, the Swiss army knife of networking tools just got a bit thicker.

While by themselves the options are pretty self explanatory, their combination together with other options, context of use or boundary values of option arguments make it possible to construct small but powerful tools. For example:

  • the port redirector allows to convert TCP stream to UDP datagrams.
  • the buffer size specification makes it possible to send one byte TCP segments or to produce IP fragments easily.
  • the socket linger option can be used to produce TCP RST segments by setting the timeout to 0
  • execute option makes it possible to simulate TCP/UDP servers or clients with shell/python/Perl/whatever script
  • etc.

If you find some other helpful ways use please share via comments.

Manual page nc(1) contains more details, along with examples on how to use some of these new options.

Tuesday Sep 01, 2009

Netcat as small packet factory

Recently I needed to test a bug fix in in.iked(1M) (should say libike.so with which in.iked is linked) after which the daemon should respond to IKEv2 requests with Notification message telling the peer to fall back to IKEv1 (previously it did not respond to IKEv2 packets at all). This can be tested by:

  • installing a OS instance which supports IKEv2 and initiating from there
  • writing a simple program (C/Perl/etc.) which will construct the UDP payload

Surely, there should be easier way how to send a UDP paket with arbitrary (in my case ISAKMP) payload. It turns out this is very easy to do just from command line with nc(1) which is available in OpenSolaris (install it via 'pkg install SUNWnetcat'). Let's try to send some garbage first to see if it works:

perl -e 'print "\\x41\\x41";' | nc -u rpe-foo.czech 500

Yep, tshark(1) (in OpenSolaris shipped by default with Wireshark) reports an IKE packet, malformed one (which is not surprising):

Capturing on eri0
  0.000000 10.18.144.12 -> 10.18.144.11 ISAKMP [Malformed Packet]

0000  00 0a e4 2f 61 eb 00 03 ba 4e 3d 38 08 00 45 00   .../a....N=8..E.
0010  00 1e 26 98 40 00 ff 11 20 fb 0a 12 90 0c 0a 12   ..&.@... .......
0020  90 0b e2 66 01 f4 00 0a 34 57 41 41               ...f....4WAA

Our two A's are there just after the UDP header (Ethernet header 14 bytes, IP header 20 bytes, UDP 8 bytes, in sum 42 bytes and our 2 bytes are just after first 8 bytes on 3rd line).

With that we can go and construct IKEv1 packet first to see if the daemon will react upon it. We will need to construct the payload which is a IKEv1 header. IKEv1 is defined in RFC 2409 (The Internet Key Exchange (IKE)). IKEv1 uses ISAKMP header definition so we need to look into RFC 2408 (Internet Security Association and Key Management Protocol (ISAKMP)) for the actual header definition. It's there in section 3.1:

                         1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    !                          Initiator                            !
    !                            Cookie                             !
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    !                          Responder                            !
    !                            Cookie                             !
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    !  Next Payload ! MjVer ! MnVer ! Exchange Type !     Flags     !
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    !                          Message ID                           !
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    !                            Length                             !
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

I'd like to construct a packet which resembles first packet sent by IKEv1 Initiator. So, our packet code (similar to shell code) will look like this (without thinking too much of what should the values look like):

  • Initiator's cookie, must not be zero
        \\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88
    
  • Responder's cookie, must be zero in the initial packet from Initiator
        \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
    
  • next payload, let's try 0 first
        \\x00
    
  • Major and Minor Version (4 bits each)
        \\x10
    
  • Exchange Type
                                Exchange Type      Value
                             NONE                    0
                             Base                    1
                             Identity Protection     2
                             Authentication Only     3
                             Aggressive              4
                             Informational           5
                             ISAKMP Future Use     6 - 31
                             DOI Specific Use     32 - 239
                             Private Use         240 - 255
    
    So let's try Base first:
        \\x01
    
  • Flags (Initiator)
        \\x00
    
  • Message ID
        \\x66\\x66\\x66\\x66
    
  • Length
        \\x28
    

We need to massage our packet code into command line. The code:

 \\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88
 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
 \\x00
 \\x10
 \\x01
 \\x00
 \\x66\\x66\\x66\\x66
 \\x28

We want source port to be 500 as well because of section 2.5.1 in RFC 2408 so use the -p option (this requires the net_privaddr privilege so either become root or use pfexec(1)). Also, we do not need to wait for the response so use -w option:

perl -e 'print "\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x01\\x00\\x66\\x66\\x66\\x66\\x28";' \\
    | nc -w 1 -p 500 -u rpe-foo.czech 500

The packet was received but there was no reply and tshark still considers this as Malformed Packet. Let's check the header again - oh yeah, the Length field has 4 bytes, not just one. Let's try again:

perl -e 'print "\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x01\\x00\\x66\\x66\\x66\\x66\\x28\\x00\\x00\\x00";' \\
    | nc -w 1 -p 500 -u rpe-foo.czech 500

Okay, this is our Base exchange but still not response:

294.029154 10.18.144.12 -> 10.18.144.11 ISAKMP Base

0000  00 0a e4 2f 61 eb 00 03 ba 4e 3d 38 08 00 45 00   .../a....N=8..E.
0010  00 38 26 a7 40 00 ff 11 20 d2 0a 12 90 0c 0a 12   .8&.@... .......
0020  90 0b 01 f4 01 f4 00 24 34 71 11 22 33 44 55 66   .......$4q."3DUf
0030  77 88 00 00 00 00 00 00 00 00 00 10 01 00 66 66   w.............ff
0040  66 66 28 00 00 00                    

Let's try something more provocative and set the Exchange type to Identity protection:

perl -e 'print "\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x02\\x00\\x66\\x66\\x66\\x66\\x28\\x00\\x00\\x00";' \\
    | nc -w 1 -p 500 -u rpe-foo.czech 500

Oh yeah, this finally deserved a response:

383.050874 10.18.144.12 -> 10.18.144.11 ISAKMP Identity Protection (Main Mode)

0000  00 0a e4 2f 61 eb 00 03 ba 4e 3d 38 08 00 45 00   .../a....N=8..E.
0010  00 38 26 a8 40 00 ff 11 20 d1 0a 12 90 0c 0a 12   .8&.@... .......
0020  90 0b 01 f4 01 f4 00 24 34 71 11 22 33 44 55 66   .......$4q."3DUf
0030  77 88 00 00 00 00 00 00 00 00 00 10 02 00 66 66   w.............ff
0040  66 66 28 00 00 00                                 ff(...

383.051672 10.18.144.11 -> 10.18.144.12 ISAKMP Informational

0000  00 03 ba 4e 3d 38 00 0a e4 2f 61 eb 08 00 45 00   ...N=8.../a...E.
0010  00 99 d3 8b 40 00 ff 11 73 8c 0a 12 90 0b 0a 12   ....@...s.......
0020  90 0c 01 f4 01 f4 00 85 ed 05 11 22 33 44 55 66   ..........."3DUf
0030  77 88 85 75 8e 0f fa a5 5d de 0b 10 05 00 69 a5   w..u....].....i.
0040  63 e4 00 00 00 7d 00 00 00 61 00 00 00 01 01 10   c....}...a......
0050  00 1e 11 22 33 44 55 66 77 88 85 75 8e 0f fa a5   ..."3DUfw..u....
0060  5d de 80 0c 00 01 00 06 00 39 55 44 50 20 50 61   ]........9UDP Pa
0070  63 6b 65 74 20 64 6f 65 73 20 6e 6f 74 20 63 6f   cket does not co
0080  6e 74 61 69 6e 20 65 6e 6f 75 67 68 20 64 61 74   ntain enough dat
0090  61 20 66 6f 72 20 49 53 41 4b 4d 50 20 70 61 63   a for ISAKMP pac
00a0  6b 65 74 80 08 00 00                              ket....

Now that we proved to ourselves that we can construct semi-valid packet it's time to try IKEv2. IKEv2 header is defined in RFC 4306, section 3.1:

                           1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !                       IKE_SA Initiator's SPI                  !
      !                                                               !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !                       IKE_SA Responder's SPI                  !
      !                                                               !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !  Next Payload ! MjVer ! MnVer ! Exchange Type !     Flags     !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !                          Message ID                           !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !                            Length                             !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

On a first sight, it looks the same (for backward compatibility). However, some of the values are different. For IKE header, the main differences are in the Exchange Type and Flags:

                       Exchange Type            Value

                       RESERVED                 0-33
                       IKE_SA_INIT              34
                       IKE_AUTH                 35
                       CREATE_CHILD_SA          36
                       INFORMATIONAL            37
                       RESERVED TO IANA         38-239
                       Reserved for private use 240-255

IKE_SA_INIT is our guy ('echo 0t34=x | mdb' produces 0x22).

The flags are now used to indicate the exchange. Set 3rd bit to say we are the Initiator. We will retain the source port even though IKEv2 supports ports other than 500 and 4500 because we're dealing with IKEv1 implementation. Now slightly change our packet code (don't forget to change the Version field to 2.0):

perl -e 'print "\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20\\x22\\x08\\x66\\x66\\x66\\x66\\x28\\x00\\x00\\x00";' \\
    | nc -w 1 -p 500 -u rpe-foo.czech 500

And we got a nice response (since the responder runs recent version libike.so):

1013.190867 10.18.144.12 -> 10.18.144.11 ISAKMP IKE_SA_INIT

0000  00 0a e4 2f 61 eb 00 03 ba 4e 3d 38 08 00 45 00   .../a....N=8..E.
0010  00 38 26 aa 40 00 ff 11 20 cf 0a 12 90 0c 0a 12   .8&.@... .......
0020  90 0b 01 f4 01 f4 00 24 34 71 11 22 33 44 55 66   .......$4q."3DUf
0030  77 88 00 00 00 00 00 00 00 00 00 20 22 08 66 66   w.......... ".ff
0040  66 66 28 00 00 00                                 ff(...

1013.192005 10.18.144.11 -> 10.18.144.12 ISAKMP Informational

0000  00 03 ba 4e 3d 38 00 0a e4 2f 61 eb 08 00 45 00   ...N=8.../a...E.
0010  00 83 d3 8d 40 00 ff 11 73 a0 0a 12 90 0b 0a 12   ....@...s.......
0020  90 0c 01 f4 01 f4 00 6f 66 da 11 22 33 44 55 66   .......of.."3DUf
0030  77 88 5c 36 e3 75 a2 7b 8e fe 0b 10 05 00 87 03   w.\\6.u.{........
0040  0c f5 00 00 00 67 00 00 00 4b 00 00 00 01 01 10   .....g...K......
0050  00 05 11 22 33 44 55 66 77 88 5c 36 e3 75 a2 7b   ..."3DUfw.\\6.u.{
0060  8e fe 80 0c 00 01 00 06 00 23 49 6e 76 61 6c 69   .........#Invali
0070  64 20 49 53 41 4b 4d 50 20 6d 61 6a 6f 72 20 76   d ISAKMP major v
0080  65 72 73 69 6f 6e 20 6e 75 6d 62 65 72 80 08 00   ersion number...
0090  00   

The only thing which is not nice is our terminal since nc(1) dumped the binary packet to it. Let's try again with some post-processing:

# perl -e 'print "\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20\\x22\\x08\\x66\\x66\\x66\\x66\\x28\\x00\\x00\\x00";'     
| nc -w 1 -p 500 -u rpe-foo.czech 500 | od -c
0000000 021   "   3   D   U   f   w 210 237   y 254 264 351 333 007 344
0000020 013 020 005  \\0   [ 251 244   j  \\0  \\0  \\0   g  \\0  \\0  \\0   K
0000040  \\0  \\0  \\0 001 001 020  \\0 005 021   "   3   D   U   f   w 210
0000060 237   y 254 264 351 333 007 344 200  \\f  \\0 001  \\0 006  \\0   #
0000100   I   n   v   a   l   i   d       I   S   A   K   M   P       m
0000120   a   j   o   r       v   e   r   s   i   o   n       n   u   m
0000140   b   e   r 200  \\b  \\0  \\0
0000147

The fix is obviously in place.

Monday May 04, 2009

External contributions to testing community

I have just integrated couple of changes which I believe are the first contributed externally to the Testing community as an open-source contribution. The changes add couple of new tests to the nc test suite to cover the enhancement described in PSARC/2008/680 (which is present in Nevada since build 106). This is the stuff which allows you to run nc(1) in client mode with complex portlist specifications. Previously it was possible only to use simple port ranges like 22-80, with this change one can connect to e.g. 22,24,50-80,66,1024-2048. Little example how it might be useful:

$ nc -v -z grok.czech 22,25,80-88,8080
Connection to grok.czech 22 port [tcp/ssh] succeeded!
nc: connect to 129.157.71.49 port 25 [host grok.czech] (tcp) failed: Connection refused
Connection to grok.czech 80 port [tcp/\*] succeeded!
nc: connect to 129.157.71.49 port 81 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 82 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 83 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 84 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 85 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 86 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 87 [host grok.czech] (tcp) failed: Connection refused
nc: connect to 129.157.71.49 port 88 [host grok.czech] (tcp) failed: Connection refused
Connection to grok.czech 8080 port [tcp/\*] succeeded!

Back to the testing part. The putback (yes, stcnv-gate is still using Teamware) log for this change looks like this (I have modified Erik's e-mail a bit):

6786859 portranges_complex_spec is missing the listener
6754842 extended port list specification needs to be tested
Code contributed by Erik Trauschke <erik.trauschke AT freenet.de>

I think this is really nice example of the ideal state - the contributor not only did the feature part but also the testing part. It shows a great degree of responsibility - not just throwing some code "over the fence" but fully participating in the process to ensure the quality even in the long term.

The tests are both positive and negative. Each purpose in portranges directory is numbered and the following numbers match the test purpose numbers:

  • 5-12 ensure nc treats ports 0 and 65536 as invalid
    Previously, it was possible to listen on ports 0 and 65536, with Erik's changes this is no longer true so we need to add regression tests for both cases (client/server) and both ports.
  • 13-19 see if various malformed port list specifications are considered as invalid
    Each purpose needs not only positive tests which make sure the functionality actually works but also negative tests which ensure it does not misbehave. In this case, invalid port list specifications are thrown at nc(1) to see it reacts accordingly (with error, that is).
  • 20-25 test the functionality of complex port lists
    This is the bunch of test which see if the functionality actually works.
  • 26 tests reallocation
    Since the internal representation of the port list is now dynamically allocated and there is a default pre-allocated value which is reallocated if needed we need to test the case of reallocation.

To be able to do such integration there is now a Test development process. It's similar to the process used in ON community but it's more lightweight. The main difference is that the request-sponsor part is done informally via the testing-discuss mailing list and there is no list of bugs to pick up from. But don't be shy, whether you're adding new functionality or completely new program, the Testing community is here to help you.

Tuesday Apr 07, 2009

Collateral salutariness

Each build of (Open)Solaris is tested with a variety of test suites on variety of platforms and I wanted nc test suite to participate in these runs.
Eoin Hughes from PIT team (which runs those tests) was kind enough to workaround couple of bugs (which are fixed now) in the test suite so it can be run in PIT environment. Later on, I got a report from Eoin that as a result of nc test suite run CR 6793191 (watchmalloc triggers system panic on sockfs copyin) was caught. This bug is manifested by a panic:

Panic message (this particular panic is on a DomU, although this happens across the board):
panic[cpu0]/thread=ffffff0150ce1540: copyin_noerr: argument not in kernel address space

ffffff000416dcf0 unix:bcopy_ck_size+102 ()
ffffff000416ddb0 genunix:watch_xcopyin+151 ()
ffffff000416dde0 genunix:watch_copyin+1d ()
ffffff000416de50 sockfs:copyin_name+91 ()
ffffff000416deb0 sockfs:bind+90 ()
ffffff000416df00 unix:brand_sys_syscall32+328 ()

The bug is actually a regression caused by CR 6292199 (bcopy and kcopy should'nt use rep, smov) and was fixed by an engineer from Intel in OpenSolaris/Nevada code base.

This is instance of an event which I like so much - unintended positive consequence elsewhere. In contrast with so called collateral damage this is something which is beneficial in other areas. I've written nc test suite to test primarily nc(1) command but here it proved to be useful for testing other areas of the system as well. In this case it was thanks to the fact that the test suite is run with memory leak checking by default (see NC_PRELOADS variable in src/suites/net/nc/include/vars file).

And yes, CR 6793191 is fixed by now.

Thursday Nov 20, 2008

Testing netcat

After multiple rounds of code review the netcat (or nc) test suite is now finally in the onnv-stc2gate. The test suite has its home in the OpenSolaris Networking community (see the networking tests page for the list of networking test suites).
The source code is present in the src/suites/net/nc/ directory and SUNWstc-netcat packages can be downloaded from OpenSolaris Download center.

Before I go further, this is how it looks like when the test suite is run (the output is trimmed a bit):

vk:honeymooners:/opt/SUNWstc-nc$ run_test nc
Validating Arguments...
New TET_ROOT for this run : /var/tmp/honeymooners_27828
The results will be available in /var/tmp/results.27828
tcc: journal file is /var/tmp/results.27828/testlog
12:45:57  Execute /tests/dflag/tc_dflag
12:46:04  Execute /tests/hflag/tc_hflag
12:46:05  Execute /tests/kflag/tc_kflag
12:46:11  Execute /tests/nflag/tc_nflag
12:46:15  Execute /tests/portranges/tc_portranges
12:46:23  Execute /tests/pflag/tc_pflag
12:46:26  Execute /tests/sflag/tc_sflag
12:46:35  Execute /tests/Uflag/tc_Uflag
12:46:36  Execute /tests/vflag/tc_vflag
12:46:43  Execute /tests/zflag/tc_zflag
12:46:46  Execute /tests/iflag/tc_iflag
12:46:59  Execute /tests/lflag/tc_lflag
12:47:29  Execute /tests/rflag/tc_rflag
12:48:16  Execute /tests/Tflag/tc_Tflag
12:48:33  Execute /tests/uflag/tc_uflag
12:48:50  Execute /tests/wflag/tc_wflag
##################################################
TC /tests/dflag/tc_dflag

TP 1 tc_dflag PASS
##################################################
TC /tests/hflag/tc_hflag

TP 1 tc_hflag PASS

...

##################################################
                 SUMMARY      
                 =======      
 
Number of Tests : 50

PASS            : 50
FAIL            : 0
UNRESOLVED      : 0
UNINITIATED     : 0
OTHER           : 0
 
##################################################

Test Logs are at /var/tmp/results.27828, Journal File = /var/tmp/results.27828/testlog 

vk:honeymooners:/opt/SUNWstc-nc$

It's been almost a year since I started developing the test suite last Christmas (see the initial blog entry about nc-tet). Since then, I have lost part of the source code in hard drive crash, had to redo the source tree structure, fix ksh style, fix numerous bugs in test suite code and make the test suite more robust. One might ask whether having test suite for such a simple program like nc(1) was worth the hassle. I have only one answer to that: absolutely. First, it gives a confidence of not breaking (most of; see below) existing things when changing/adding functionality and second it helped me (and I hope the others participating/observing the code review on testing-discuss too) to explore what it takes to write a test suite from scratch (I will not go here into details whether I prefer CTI-TET over STF and vice versa).

The Beautiful code book (which I really recommend for anyone tinkering with any source code) contains a chapter called Beautiful tests by Alberto Savoia. I hope that at least some of the test purposes in nc test suite have some degree of beautifulness of at least one of the ways highlighted by Alberto (1. simplicity/efficiency, 2. help making the software being tested better in terms of quality and testability, 3. breadth/thoroughness).

One of the important questions for a test suite is code coverage level. Obviously, for software adhering to the OpenSolaris interface taxonomy model it is important that the test suite exercises all of the Committed interfaces and execution paths around those interfaces. For nc(1) this means a subset of the command line options and their arguments (see PSARC 2007/389 for the actual list). The key is certainly to test the features which are likely to break with an intrusive code change.

Very crude view of test coverage for nc(1) test suite (counting test purposes gives only very remote idea about real coverage but at least provides visual image) looks like this:

       rflag: +
       Tflag: +++++---
       pflag: +
       iflag: +-
       vflag: ++
       kflag: +
       Uflag: +-
       dflag: +
       uflag: ++-
       sflag: +-
       hflag: +
       nflag: +-
       wflag: +
  portranges: +---
       lflag: ++++++++----------

One plus character stands for one positive test purpose, minus is negative test purpose.

Side note: the above ASCII graph was produced using test-coverage-graph.sh script (which presumes certain naming scheme for test purpose files). Just pipe a file listing into the script with test purpose filenames compliant to the scheme used in ontest-stc2 gate and it will spew out graph similar to the above.

In the above musing about code coverage I left out an important piece - why some of the features are not tested. For nc(1) the yet untested part is the SOCKS protocol support. Basically, this is because test suite environment does not contain SOCKS server to test against. There might not be many people using the -x/-X options but from my own experience nothing is more frustrating than discovering some old dusty corner which had to be fixed long time ago or removed completely. So for now, on my workstation which sits behind SOCKS proxy I have the following in ~/.ssh/config for a server outside corporate network which hosts my personal mailbox so it is accessed every day:

Host bar
  User foo
  Hostname outside.kewl.org
  # NOTE: for nc(1) testing
  ProxyCommand /usr/bin/nc -x socks-proxy.foothere.bar outside.kewl.org %p
  ForwardAgent no
  ForwardX11 no

This ensures (along with upgrades of the workstation to recent Nevada builds periodically) that SOCKS support gets tested as well. And yes, ssh-socks5-proxy-connect(1) and ssh-http-proxy-connect(1) are not really needed.

Now with the test suite in place, anybody modifying nc(1) (there are some RFEs for nc in the oss-bit-size list and other bugfixes or features are also welcome) can have pretty high confidence that his change will not break things. Yes, this means that more nc(1) features are coming.

Sunday Apr 27, 2008

Test suite for netcat

In OpenSolaris world we very much care about correctness and hate regressions (of any kind). If I loosely paraphrase Bryan Cantrill the degree of devotion should be obvious:

"Have you tested your change in every way you know of ? If not, do not go any further with the integration unless you do so."

This implies that ordinary bug fix should have a unit test accompanying it. But, unit tests are cumbersome when performed by hand and do not mean much if they are not accumulated over time.

For integration of Netcat into OpenSolaris I have developed number of unit tests (basically at least one for each command line option) and couple more after spotting some bugs in nc(1). This means that nc(1) is ripe for having a test suite so the tests can be performed automatically. This is tracked by RFE 6646967. The test suite will live in onnv-stc2 gate which is hosted and maintained by OpenSolaris Testing community.

To create a test suite one can choose between two frameworks: STF and CTI-TET. I have chosen the latter because I wanted to try something new and also because CTI-TET seems to be the recommended framework these days.

The work on nc test suite has started during Christmas break 2007 and after recovery from lost data it is now in pretty stable state and ready for code review. This is actually somewhat exciting because nc test suite is supposed to be the first OpenSolaris test suite developed in the open.

Fresh webrev is always stored on cr.opensolaris.org in nc-tet.onnv-stc2 directory. Everybody is invited to participate in the code review.

Code review should be performed via testing-discuss at opensolaris.org mailing list (subscribe via Testing / Discussions). It has web interface in the form of testing-discuss forum.

So, if you're familiar with ksh scripting or CTI-TET framework (both not necessary) you have unique chance to bash (not bash) my code ! Watch for official code review announcement on the mailing list in the next couple of days.

Lastly, another philosophical food for thought: Test suites are sets of programs and scripts which serve mainly one purpose - they should prevent bugs from happening in the software they test. But, test suites are software too. Presence of bugs in test suites is an annoying phenomenon. How to get rid of that one ?

Saturday Dec 01, 2007

Netcat in Solaris

CR 4664622 has been integrated into Nevada and will be part of build 80 (which means it will not be part of next SXDE release but I can live with that :)).

During the course of getting the process done I have stumbled upon several interesting obstacles. For example, during ingress Open Source Review I was asked by our open-source caretaker what will be the "support model" for Netcat once it is integrated. I was puzzled. Because, for Netcat, support is not really needed since it has been around for ages (ok, since 1996 according to wikipedia) and is pretty stable piece of code which is basically no longer developed. Nonetheless, this brings some interesting challenges with move to a community model where more and more projects are integrated by people outside Sun (e.g. ksh93 project).

The nc(1) man page will be delivered in build 81. In the meantime you can read Netcat review blog entry which contains the link to updated man page. The older version of the man page is contained in the mail communication for PSARC 2007/389.
Note: I have realized that the ARC case directory does not have to include most up-to-date man page at the time of integration. Only when something _architectural_ changes, then the man page has to be updated (which was not the case with Netcat since we only added new section describing how to setup nc(1) with RBAC). Thanks to Jim for the explanation.

I have some ideas how to make Netcat in Solaris even better and will work to get them done over time. In particular, there are following RFEs: 6515928, 6573202. However, this does not mean that there is only single person who can work on nc(1). Since it is now part of ONNV, anyone is free to hack it.

So, I'd like to invite everyone to participate - if you have an idea how to extend Netcat, what features to add, it is sitting in ONNV waiting for new RFEs (or bugs) and sponsor requests (be sure to read Jayakara Kini's explanation of how to contribute if you're not OpenSolaris contributor yet).

Also, if you're Netcat user and use Netcat in a cool way, I want to hear that !

About

blog about security and various tools in Solaris

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today