using the QtocLstNetCnn api in cl

Posted on 2007-08-02
Last Modified: 2012-06-27
Can anyone give me an example of calling the QtocLstNetCnn API from CL and how to read the output?  I'm trying to get information on telnet sessions.  Thanks.
Question by:dhenderson12
    LVL 26

    Accepted Solution


    The basic part is kind of straightforward:

    ------ Begin paste
    pgm    ( +

    /*  CRTBNDCL   PGM(your-lib/TSTLSTCNN)          +
                  SRCFILE(your-lib/QCLSRC)         +
                  SRCMBR(TSTLSTCNN)           */

       dcl   &qusrspc     *char     20
       dcl   &usrspc      *char     10     value( 'LSTNETCNN' )
       dcl   &usrspclib   *char     10     value( 'QTEMP' )
       dcl   &qcnnlst     *char   1024

       dcl   &NetCnnTyp   *char     10     value( '*TCP' )
       dcl   &LstReqTyp   *char     10     value( '*ALL' )
       dcl   &reserved    *char     12     value( x'000000000000000000000000' )
       dcl   &LclLwrIP    *char      4     value( x'00000000' )
       dcl   &LclUprIP    *char      4     value( x'00000000' )
       dcl   &LclLwrPrt   *char      4     value( x'00000000' )
       dcl   &LclUprPrt   *char      4     value( x'00000000' )
       dcl   &RmtLwrIP    *char      4     value( x'00000000' )
       dcl   &RmtUprIP    *char      4     value( x'00000000' )
       dcl   &RmtLwrPrt   *char      4     value( x'00000000' )
       dcl   &RmtUprPrt   *char      4     value( x'00000000' )

       chgvar            &qusrspc       ( +
                                          &usrspc           *cat  +
                                          &usrspclib              +

       chgvar            &qcnnlst       ( +
                                          &NetCnnTyp        *cat  +
                                          &LstReqTyp        *cat  +
                                          &reserved         *cat  +
                                          &LclLwrIP         *cat  +
                                          &LclUprIP         *cat  +
                                          &LclLwrPrt        *cat  +
                                          &LclUprPrt        *cat  +
                                          &RmtLwrIP         *cat  +
                                          &RmtUprIP         *cat  +
                                          &RmtLwrPrt        *cat  +
                                          &RmtUprPrt              +

       callprc    'QtocLstNetCnn'       ( +
                                          &qusrspc       +
                                          'NCNN0100'     +
                                          &qcnnlst       +
                                          x'00000040'    +
                                          'NCLQ0100'     +
                                          x'00000000'    +


    ------ End paste

    That's the guts of accessing the API using ILE CL (not OPM CL). That proc by itself can be compiled and bound into a *PGM with a simple CRTBNDCL command. The API is in a system service program that should be available to the binding step by default.

    But, that's only a direct call to the API to get *ALL connections of type *TCP on all local IP addresses (IPV4) on all local ports and from all remote IP addresses on all remote ports.

    One potentially confusing part of the documentation is that even in V5R4 it says the addresses are to be specified in "dotted-decimal format". Since the parm is BIN(4) and a dotted-decimal address would be possibly CHAR(16) -- which allows for 15 characters followed by null-terminator for many APIs -- it's certain that they can't mean "dotted-decimal". Though I haven't had to try it, I assume they really want the BIN(4) network address format.

    If you _must_ restrict addresses and you only have dotted-decimal, you probably have to convert them by calls to inet_addr()--Translate Full Address to 32-bit IP Address -- which is one of the UNIX-type APIs under Sockets.

    Anyway, the above code is in V5R1 format. It should work on any V5 system. If I wrote it in full V5R4 format, it could make full use of the integer data types, of data structures and of pointers, and I wouldn't have used the CHAR(4) variables with hex-values. I'd have used direct integer values.

    Now, the program so far will only work if a user space has already been created. In the program, the *usrspc is QTEMP/LSTCNN. You can create and name whatever you want. In CL, you call the QUSCRTUS API to create a *usrspc. Once created, the QtocLstNetCnn API can write its list into it.

    Then, you need to read that list.

    Prior to V5R4, the only way to do that is to call the QUSRTVUS API to get blocks of bytes at a time; each time, you specify an offset to start from and a length to read into your receiver variable. The first thing to read would be the header; then you substring out the parts that tell what the offset to the list is, what the length of each entry is and how many entries are in the list. (I usually grab the whole header in one call to that API and substring the parts out, but you can call the API for each piece if you want.)

    Once you know where the list starts in the *usrspc and how long each entry is, you call QUSRTVUS over and over again. Each time, you get the next entry from the list.

    And the reason you get the next entry is because you add the length of the entries to the offset each time. That tells the API to start reading a little farther into the *usrspc for each entry.

    As you read entries in a loop, you also keep count. When your count reaches the number of entries that you read from the *usrspc header, you know you're at the last available entry.

    Each time you read an entry, you need to process it before reading the next one. The entry is sitting in whatever variable you read it into. You have to substring each part of the entry out so you can work with the different fields in the entry.

    I have no idea if you've ever used *usrspcs before, so there's no code included. The code is _only_ for the list API so far. It has a DMPCLPGM command at the end because I almost always throw one in with any example. It's often helpful when testing.

    If you create a *usrspc and run the program, the next thing you should do is look at what got written into the *usrspc. You should have a good picture of what's in there before trying to write code that will extract stuff out. IMO, the easiest thing to do would be:

     ==>  dmpobj  qtemp/lstcnn  *usrspc

    That is, after the program runs successfully, dump the space to a spooled file. Look over what gets printed and compare it to the documentation for the API. If you know what's in the *usrspc, debugging a program that reads the space is far easier. Also, if you create the space in a permanent library instead of QTEMP, you can write a smaller, separate program to read that space and run it over and over for a few days until it works.

    Once the second, smaller program works, you can decide if you want to combine the code into one program or perhaps make separate proces and just bind them together.

    Hope that gets you started. Post back for further help.


    Author Comment

    Thanks for the excellent write up.  I'm going to try running your example, and I'' see what happens.

    Author Comment

    I compiled as per your instructions but get this error when I try to call the pgm:
    msg id: CEE9901 statement 0000000138, instruction X'0000'

    Statement   0000000138 is the CALLPRC instruction ... I don't know what the x'0000' value is.  

    I did change the following two lines ... I changed the program name and library values:
                 dcl        &usrspc      *char     10     value( 'GETPORT')
                 dcl        &usrspclib   *char     10     value( 'XDAN' )
     Any ideas?
    LVL 26

    Expert Comment

    CEE9901 isn't _the_ message; it's only a message that tells you a message was sent. In order to see _the_ message, look at messages just before CEE9901 in the joblog.

    If XDAN/GETPORT wasn't created before running the program, the message is probably something like "GETPORT in library XDAN not found".


    Author Comment

    Yeah, my problem was not having created the user space, so I create the user space first then call your procedure, and it works like a champ!  I have one last question:  How can I output the returned list to a print file?  Thanks for all your help and patience.

    Author Comment

    never mind ... it's going to a print file.  Thanks again for your help.

    Featured Post

    Looking for New Ways to Advertise?

    Engage with tech pros in our community with native advertising, as a Vendor Expert, and more.

    Join & Write a Comment

    Suggested Solutions

    Disabling the Directory Sync Service Account in Office 365 will stop directory synchronization from working.
    Local Continuous Replication is a cost effective and quick way of backing up Exchange server data. The following article describes the steps required to configure Local Continuous Replication. Also, the article tells you how to restore from a backup…
    This video discusses moving either the default database or any database to a new volume.
    Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

    755 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    26 Experts available now in Live!

    Get 1:1 Help Now