Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

Programmatically enumerate open sockets

SOLVED
Go to solution
chorneck
Occasional Visitor

Programmatically enumerate open sockets

Does anyone know of a way to programmatically enumerate all of the open sockets in OpenVMS? I'd like to be able to write a C program that can produce output that is similar to netstat.

Regards,
chorneck
18 REPLIES
Steven Schweda
Honored Contributor

Re: Programmatically enumerate open sockets

I don't, but you might look at using
$DEVICE_SCAN to provide a list of all the
BG* devices. Then, perhaps, some $GETDVI
magic would reveal the inner secrets of a
particular BGxxx device (perhaps some
DEVDEPENDx item code or other).
Richard Whalen
Honored Contributor

Re: Programmatically enumerate open sockets

You didn't say what IP stack you are using.

For MultiNet and TCPware this can be done with IO$_SENSEMODE calls, the details of which can be found in the programmer's guides. I don't know what mechanism to use for TCP/IP Services. If you want to do it in a completely portable manner, then the TCP and UDP tables in SNMP have the information provided that an SNMP agent is active on the system.
Hoff
Honored Contributor

Re: Programmatically enumerate open sockets

Eh? Please consider adding a few more words around the background and the question? This, and some details on the version and the platform?

Why do I ask? Current TCP/IP Services has a netstat tool.

$ netstat -?
ddcu:[dir]tcpip$netstat.exe;1: illegal option -- ?
usage: netstat [-AanXx] [-f address_family]
[-abgHilmMNnPrsuv] [-f address_family] [-p protocol]
[-acdntz] [-I interface] [interval]
$

This and other common tools are available after invoking sys$startup:tcpip$define_commands.com

As an alternative approach to a host-based port scan, I'd probably aim nessus or nmap or other such at the box.

chorneck
Occasional Visitor

Re: Programmatically enumerate open sockets

I apologize for being vague with my question. I wasn't sure what details were relevant. I am used to working with UNIX, so OpenVMS is a bit of a struggle for me.

>You didn't say what IP stack you are using.

We are running OpenVMS Alpha 8.3 with HP TCP/IP Services 5.6.


>Eh? Please consider adding a few more words around the background and the question?

Basically, what I'm trying to do is write a JNI library that can retrieve a list of open sockets so that this information can be consumed by our java system management agent. I mentioned netstat because it's a tool that is familiar to most and I noticed that it was available as part of the TCP/IP services.


Based on what I have come up with from my research so far, it looks like SNMP might be the only way to do this with TCP/IP services.


Regards,
chorneck
Hein van den Heuvel
Honored Contributor

Re: Programmatically enumerate open sockets

Maybe just spawning 'netstat' and parsing its output is a reasonable thing to do for your application?

As long as you do not ned that data more than say once a minute the overhead is probably acceptable.

fwiw,
Hein.
Richard J Maher
Trusted Contributor

Re: Programmatically enumerate open sockets

His views on the ITRC points system are well known, but I am suprised you only gave Steven S two points for what, IMHO, is the correct answer.

What does his strategy (possibly in combo with io$_sensmode for what's not available with $getdvi) not give you?

Cheers Richard Maher
Wim Van den Wyngaert
Honored Contributor

Re: Programmatically enumerate open sockets

Note that a "netstat" or "netstat -a" will do a DNS lookup for every IP address (could be thousands). Better to use "ucx show dev" or "netstat -n" to avoid this.

Wim
Wim
Richard W Hunt
Valued Contributor

Re: Programmatically enumerate open sockets

You could also spawn a command

$ TCPIP SHOW DEVICE_SOCKET

and trap the output, which is columnar and suitable for simple-minded (fixed-column extraction) parsing. The device names will be BGxxxx, which you can then look up through GETDVI functions. The last column will tell you whether the socket is actually connected to something external, usually just by IP address rather than a reverse lookup (at least on my system.)

In GETDVI, you can then see if there is an owner process ID, in which case there will be an owner process name and owner UIC.

OK, I'm somewhat of a script fanatic, but I do a somewhat more detailed version of this in DCL with the combination of three commands:

$ TCPIP SHOW DEVICE_SOCKET
$ SHOW DEVICE/FULL BG
$ SHOW USER/FULL

(with appropriate output capture, of course) and then use DCL symbol substitution to correlate the BG devices with each other to show the open ports, partner ports where a connection exists (i.e. not just listening but active), connect type, protocol type, owner, image name, process name, IP address, and a bunch of other data. OK, probably could have done it a thousand other ways, but did it in DCL because of the ability to more easily see intermediate data when debugging. There is enough data among the output of those three commands to really tie it all together into a neat, if VERY LONG, display.
Sr. Systems Janitor
Richard J Maher
Trusted Contributor

Re: Programmatically enumerate open sockets

Nah, honestly Steven Schweda gave you the answer. Really truly! It's called programming. Something that's not done much on VMS anymore but give it a go; you might like it.

Oh I get it, this is just a wind up to get someone to write the code for you?

What's next? A Perl or Python script to parse the output from some dodgy pipe command? I'm sure we can get a couple of REGEXes in there and maybe some bash scripting to go along with the DCL? This is a System Managers dream!

Regards Richard Maher

Richard J Maher
Trusted Contributor
Solution

Re: Programmatically enumerate open sockets

Hi Chorneck,

On re-reading this thread, I see that you are new(ish) to VMS, so I might not have been as helpful as I could've. Please see attached for an example of what Steven S was talking about. (Or if I'm wrong, I'm sure he'll correct me with his version.)

I would've given a more complete version but this has honestly taken over two full days and (unlike the IMM team that have cost centres galore - how's gSOAP going btw) I can't spend anymore "free" time on it :-(

Yes, I did imply that this was easy, and I stand corrected. Moving forward, here are some issues you should be aware of: -

. This example looks specifically at the BG driver. While Multinet and TCPWare both support the BG driver they also have other "lesser" drivers that are probably being used for Telnet, or FTP and so on. I don't have priv on DEATHROW to test it but maybe Richard W will give it a go?

. I successfully tested this on Alpha VMS 7.2-2 UCX 5.1 with no (visible) ill effects. Please be aware that with VAX/VMS 6.2 UCX 4.1 all your Telnet sessions stop working :-( Check the supportability of assigning an additional channel to a BG device that doesn't have ucx$c_share set.

. I haven't bothered with the IPv6 code for socket names but that won't be hard.

. I don't get IP address returned for Telnet connections for some reason?

. Full duplex close option doesn't seem identifyable

. I don't know if there is a ACP/QIO Stats call to get the number of I/Os bytes etc? a la mode de $UCX SH DEV/FULL

. Maybe this should all be done by walking some UCB chain?

OTY (or anyone else)

Cheers Richard Maher
chorneck
Occasional Visitor

Re: Programmatically enumerate open sockets

Thanks for all the replies! I think the code provided by Richard does what I want.

Regards,
chorneck
Richard Whalen
Honored Contributor

Re: Programmatically enumerate open sockets

I don't have a COBOL compiler on my systems, so I can't test Richard Maher's program on TCPware or MultiNet. TCP/IP services also supports the INET device that MultiNet and TCPware provide, though it is probably not commonly used.
Richard J Maher
Trusted Contributor

Re: Programmatically enumerate open sockets

Hi Richard,

> I don't have a COBOL compiler on my systems,

You should get out more :-)

> so I can't test Richard Maher's program
> on TCPware or MultiNet.

If anyone has SHARE privilege on the Deathrow cluster, I have put a copy of the code, and built an executable on GEIN: -

DISK$USERS:[USERS.TIER3]SOCKET_SCAN.EXE

Richard, could you also please tell me/everyone the API for getting this sort of statistics information from the socket: -

Total buffer alloc 0 0
Total buffer limit 70080 70080
Buffer or I/O waits 0 0
Buffer or I/O drops 0 0
I/O completed 5 23
Bytes transferred 148 1219

Cheers Richard Maher
chorneck
Occasional Visitor

Re: Programmatically enumerate open sockets

What would be the impact of assigning an additional channel to a BG device and then subsequently deassigning that channel?

The HP TCP/IP Services guide seems to suggest that it actually closes the port and clears all pending I/O operations if I am understanding this correctly.

To quote a bit...

After all communication is completed, use the $DASSGN system service to free an I/O channel. A $DASSGN operation executed on a channel associated with a network pseudodevice does the following:

* Ends all pending operations to send or receive data at $QIO level ($CANCEL system service).
* Clears the port associated with the channel. When executing the $DASSGN system service for TCP sockets, the socket remains until the connection is closed on both the local and remote sides.
* Ends all communications with the network pseudodevice that the I/O channel identifies.
* Frees the channel associated with the network pseudodevice. An I/O channel can be deassigned only from an access mode equal to or more privileged than the access mode from which the original channel assignment was made.


Does anyone have any insight on this? Am I just misunderstanding how this program is working?


Thanks!
David Jones_21
Trusted Contributor

Re: Programmatically enumerate open sockets

"What would be the impact of assigning an additional channel to a BG device and then subsequently deassigning that channel?

The HP TCP/IP Services guide seems to suggest that it actually closes the port and clears all pending I/O operations if I am understanding this correctly."

I have an application that hands off accepted connections to worker processes, which involves the listener process setting the socket shared and deassinging the channel after the worker has assigned its own channel to the BG device. Normally, rundown operations on devices are only triggered when the last channel is deassigned.
I'm looking for marbles all day long.
chorneck
Occasional Visitor

Re: Programmatically enumerate open sockets

I ended up throwing together a C program based on Richard's COBOL program. I am attaching the code if anyone is interested. However, as Richard mentioned, there are a few side effects that I discovered while testing on OpenVMS Alpha 7.3-2/TCPIP Services v5.4 ECO 6.

1) I discovered that executing QIO requests on BG* devices that are owned by the TCPIP Ancillary Control Process is a bad idea. It seemed to cause random freezes in TCPIP services and no one else could log into the node via Telnet or SSH until the node was rebooted. Therefore, I put a check in so that the code does not execute the QIOW requests on devices where Owner PID == ACP PID.

2) Once I worked around problem 1, I discovered that Richard was right about the Telnet sessions. For some reason, I cannot seem to get their IP Addresses. SSH sessions are another story. I was able to get their addresses, but the end result was that the SSH sessions that I was able to retrieve information for stopped working. Apparently, the SSH sessions don't handle QIO requests well either.


Thank you to everyone for all the help!
Richard J Maher
Trusted Contributor

Re: Programmatically enumerate open sockets

Hi Corneck,

Short of opening a formal support call, you'd need someone with Richard Whalen's level of detailed knowledge to tell you, or access to the VMS sources for $UCX SHOW DEV

Cheers Richard Maher

PS. When you find out, please report back :-)
Richard W Hunt
Valued Contributor

Re: Programmatically enumerate open sockets

Maybe I'm lost here and don't follow what you are trying to do, but I don't think you can just assign a channel to a BG device. They are "template-created" devices in that there is really only device BG0 and all other BG devices are cloned. When I look at the device characteristics of the BG devices on my system, the SHR flag is 0 i.e. not shareable. So I don't think you can just name a BG device and open it.

The closest analogy is the MBA device, mailboxes, where you have to use a specific system call, CREMBX, to clone from MBA0 (yes, another template UCB device) before you can open a channel to it. While I won't swear to it, I think BG devices are similar except I don't know how to force a clone.

If you really created one, you could maybe see WHICH BG you got. Doing it that way means you get a fresh BG and don't have to try to share one. You also would then avoid interfering with arbitrary BG devices engaged in protocol exchange operations.

Or was that too simple-minded for what you were really looking at?
Sr. Systems Janitor