IPv6 Design Review


IPv4 -> IPv6 Patterns

In our AC code, as it stands, much of the time an IP address is  represented as a four-byte value (which I will henceforth refer to as the 4-byte format). This is typically represented as either an unsigned long, or array of four chars.

However, we now need a standardized address format, which would replace all instances of the 4 byte format. According to the IPv6/IPv4 agnostic code specifications, that new structure is struct sockaddr_storage *. This would require replacing all functions that return, or use, the 4-byte IPv4 address format, with sockaddr_storage *.

With the above being the case, the following utility functions are required to implement the AC functionality currently in use.

- We need a function that converts standardized address -> hostname code, which will take the address in either form and return a name (See convertAddrToHostname(...) )
- We need a function that converts standardized address -> text ip address code, which will take the address in either form and return dots or colons and numbers. (See convertAddrToIpString(...) )

- We need a function that gets the standarized address from a socket, either from the source or destination (peer) of that socket. (See getSelfAddrOfSocket(...) and getPeerAddrOfSocket(...) )
- We need a function that gets the standarized address(es) for any given hostname/ip address. (See convertHostnameToAddrs(...))
- We need a function that gets the standardized address(es) for a local host. (See getLocalHostAddresses(...))

- We need a function that determines whether a standardized address is a local host address (See isAddrLocal(...) ).
- We need a function that compares (binary comparison) standardizes addresses with each other (See compareAddresses(...) )

- We need a function that converts the standardized address into its 4 (IPv4) or 16 (IPv6) byte representation, and vice versa. (See getByteFormatFromSockAddr() and getSockAddrFromByteFormat() )

I've implemented the above functions, plus more, in the TptpNewSocket.c of the updated socket code, which is partially based on the Client/Server IPv4/IPv6 code that I've previously posted. The code isn't complete (e.g. for instance, there is no logging, and it hasn't been heavily tested), but it serves as an excellent base for delivery into the agent controller. I'd expect as part of stage 2, Intel would handle moving this code into the AC code as they port TransportSupport/socketTL.

Central Guidelines

I highly recommend reading through this section and making sure everything is clear, before moving past this section. The following sections rely greatly on this section.

- One problem is that the functions that we are NOT  porting in stage 2 (e.g. stage 4 functions: request peer monitoring and access list/check host) use functions that we ARE porting in stage 2. This will cause the functions that we are NOT porting in stage 2 to fail to compile. This is a problem, because we still need those unchanged stage 4 functions to compile.

- My solution: Rewrite the IPv4 functions as per the notes below... BUT, for any IPv4-only functions that these stage 4 functions use, create a copy of the old IPv4 method AS IS, but give it a new name: for example, 
getSocketIPString is called by the peer monitoring method getPeerConnectionInfo. Create a new method called getSocketIPStringIPv4M(), with the same contents as the original, and replace any references in getPeerConnectionInfo with the new IPv4 name. At the end of IPv4 function name should be IPv4M, to allow us to track them.  

- Reserve porting the request peer monitoring functionality until stage 4.
- Disable host checking functionality until stage 4: Essentially, comment out "if (!tptp_checkHost(cctlData->network_list, address)) {  ..... } " in serveRequests of  CCTLServer.c, and comment out "rc = parseHostList(pTransportData->configurationData, &cctlData->network_list);" in createTransportListener of ClientCTL.c.

- Use the new 'getTheSocket' method which I have provided in the example file.
- Replace all getTheSocket calls (not many) with the new format, and then rewrite the calling functions to handle multiple potential sockets that they need to listen on.
- Fix connectToTCPServer so that it takes the standardized address, as above (I've written a replacement for this method, either 'connectToHostWithAddr' or 'connectToHostWithHostname', depending on the context, usually the former)

- Fix all functions that directly or indirectly pass the 4-byte IP address into connectToTCPServer with the struct sockaddr_storage * code equivalent.
- Having changed the method signatures of the above functions, fix any calling methods of these functions, ad infinitium.

- For all functions that are listed as "not used" below, ignore them for now, and mark in their comments that they are IPv4 only. I'd recommend a standard tag so we can track them, e.g /* IPV4-ONLY */

- Lower Priority: May want to comment out, the RAInetAddress java code.
- See function level recommendations below, for remaining functions.




Intel / IBM Dependencies

With the way we've divided the IPv6 code in the original planning document,  I've observed that IBM's files have a lot of dependencies on Intel's files, while Intel's files only depend on themselves (for the most part). This requires Intel to complete their stage 2 changes first, before IBM can proceed with its stage 2 changes.

Stage 2:
- First, Intel should complete the changes to the projects that are listed as theirs in the original planning document. These functions mostly have either no dependencies, or depend only on other Intel functions.
- Note, there will be lots of build errors in the IBM side of the code once the Intel side is completed for stage 2. This is expected.
- Once Intel's stage 2 code is complete, a patch should be sent to IBM that includes the changes.
- IBM will use this patch and make its stage 2 changes to its side of the code, and make any touchups that are required in the AC.
- Once complete, IBM will produce a patch that should be a working, compileable AC, but with host access and request peer monitoring functionality disabled.
- From here, we can pass to stage 3.

Stage 3+:
- After Stage 2, we'll manage dependencies differently.



New AC Code Methods where IPv4-only code is used

I've worked through Microsoft scan tool's output code, and noted the method that the IPv4-only code is contained in. I then noted which functions reference this function, and for what purposes. In most cases I've included a recommendation as well. In many cases, these functions can merely be replaced with the updated socket code equivalent.

AgentController.c:

unsigned int parsePeerAttachAddress(char* str):
- Takes a dots and numbers IP addresse and returns it in 4 byte format.

Called by:
- parseAndProcessParameters(), which is called by main.
- Stored in
            cm->peerInfo.usePeerAttachAddress = TRUE;
            cm->peerInfo.peerAttachAddress = parsePeerAttachAddress(arg);

- See also, PeerAttachInfo_t, below.

Recommendation: Leave this for stage 4. As long as the consumer doesn't use the two peer monitoring command line switches, this should be fine.


ConnectionImpl.cpp:

ConnectionImpl::getLocalIPAddress() (not used)

ConnectionImpl::getIPAddress()  (used by itself)
- Returns IP address in 4-byte format (unsigned long).
- Used only as the first parameter to connectToTCPServer
- Recommendation: When connectToTCPServer is fixed, this function should be fixed to return the appropriate IPv6 struct.  Note, I think for backwards compatibility, a second copy of this function should be created called  getIPAddressIPv4() (that only returns IPv4 addreses in 4-byte format), for any consuming products that don't wish to make the switch to IPv6 support.



TCPDataServer.cpp:

TCPDataServer::getLocalIPAddress()  (used by itself, it would seem)
- Returns IP address in 4-byte format (unsigned long).
- Used only as the first parameter to connectToTCPServer
- Recommendation: When connectToTCPServer is fixed, this function should return the appropriate IPv6 struct.

TPTP_INetAddress.cpp:

TPTP_INetAddress::getAddress (unused, however part of native client api... may be used by consuming product)
- Is merely a host name resolve.
- Input: Hostname (char *)
- Output: char * (dots and numbers IP address, string)
- Recommendation: Is self-contained, we need only to replace this with IPv6-based host name resolution.


TPTPCBE.cpp:

createSourceComponentID (used, called by itself, merely prints the hostname)
- The offending code in this method only gets the local hostname (char *) and sprintfs it into a string.
- Recommendation: Self-contained, easily replaced.


SocketListener.c:

doListening
- Rewrite the function using the new getTheSocket(...) call. bindAndListen call no longer needed.
- Code must now listen on multiple server sockets.
- Recommendation: Rewrite using the new getTheSocket(...) method, and the code must now listen on multiple server sockets.

TransportOSCalls_win.c:

printSocketRequest  (not used - may be for debug purposes)

convertIPAddressStringToArray
- input is an IP address in string form, output is 4 unsigned characters
   o in CCTLServer.c serveRequests() - Grabs's the peer's IP in string form, calls this method, then passes it into tptp_checkHost.
   o in Connect2AC.c (TPTPClientCompTL)  => translateAndForwardPeerRequestMonitor - Gets the local ip address of the socket, converts it to 4-byte, stores it in command->info.controller_request_monitor_port. Also, is used to convert the PeerHost (string) to peerAddr (4 byte), to be stored in command->info.controller_request_monitor_port.peerNode.

   o in Connect2AC.c (TPTPClientCompTL)  => translateAndForwardRequestMonitor -  Gets the local ip address of the socket, converts it to 4-byte, stores it in command->info.controller_request_monitor_port., Also, is used to convert the PeerHost (string) to peerAddr (4 byte), to be stored in command->info.controller_request_monitor_port.peerNode.

Recommend leaving this one alone for now, until the fourth stage.
Disable the tptp_CheckHost call in CCTLServer.c...serveRequests. Any socket functions used by the request peer monitoring code should be IPv4M'ed, as per above.

 
convertIPAddressUlongToString
- Converts the four byte IP format to a 'dots and numbers' string
  o Used only by getPeerConnectionInfo in ClientCTL.c
  o Outputted as 'dots and numbers' to host portion: <transportType>TPTP_CCTL</transportType><host>%s</host><port>%d</port>
  o This call is only made when cctlData->usePeerAttachPort is called. It is called on cctlData->peerAttachAddress.

Recommendation: Because this is peer monitoring specific, recommend leaving it to stage 4. IPv4M it.

extractAddressFromSockAddr (not used)



TransportOSCalls_linux.c (as above):

printSocketRequest (not used - may be for debug purposes)
convertIPAddressStringToArray
convertIPAddressUlongToString
extractAddressFromSockAddr (not used)
- Same as above.


TransportSupport:

tptp_getLocalIPAddress (not used)

tptp_getLocalIPAddresses
-  Stores the local IP addresses in 4 byte form (null terminated char* list format, inside a tptp_IPAddresses_t )
   o Used by isLocalHost() and tptp_checkHost(), below.
- Recommendation: Because it's only used by the checkHost functionality, leave as is in stage 2. IPv4M it.

isLocalHost
- Input is host name, output is either true or false.
- Called only by tptp_checkHost
- Recommendation: Leave as in stage 2 (IPv4M it.). In stage 4, rewrite: Self contained, rewrite to use  IPv6 compliant code.
 
tptp_checkHost
- Input is network_list_t, and an address in four byte format.
   o Used by serverRequests() of CCTLServer.c
- Recommendation: Leave as in stage 2.



Stage 4 Work (skip this section for Stage 2):

The structs related to the code are:
 

typedef struct {
    network_list_node_t *head;
    network_list_node_t *tail;
} network_list_t;


Stored in:
{
    (...)
    BOOL            securityEnabled;
    tptp_uint32        securedPort;
    tptp_string        *keystore;
    tptp_string        *keystorePassword;
    network_list_t    *network_list;
    tptp_string        *users;
} cctl_state_data_t;

Unsupported, nothing will generate these entries: TPTP_HW_UNKNOWN, TPTP_HW_KNOWN, TPTP_HW_MAX_VALUE,

TransportSupport.c:

BOOL tptp_checkHost(network_list_t *list, unsigned char *address);

- Called only in THREAD_USER_FUNC_RET_TYPE serveRequests(LPVOID args)
  o Gets the string host name of the peer connected to it
  o Converts that to 4-byte format
  o calls tptp_checkHost on that 4 byte format.
  o Note: the tptp_checkHost called can be easily commented out.

- address is address in 4-byte format.

- begins at list->head
- pulls a network_t out of current->entry
- entry->wildcard = TPTP_HW_ALL, TPTP_HW_LOCAL, TPTP_HW_UNKNOWN, TPTP_HW_KNOWN, TPTP_HW_NET, TPTP_HW_NAMED

case TPTP_HW_ALL: 
- if allow return true, otherwise return false. Doesn't need to be rewritten.

case TPTP_HW_LOCAL:
- needs to be rewriten
- calls tptp_getLocalIPAddresses() and compares each of the returned IP addresses with the 'address' parameter that was passed in. If match, return either true or false based on allow or deny.

case TPTP_HW_NET:
- needs to be rewritten
- binary & the address with the mask to see if it matches the net. If so, return either true or false based on allow or deny.
- resolve the address into string format, and store the alternative names as well
- compare the named ip listed in the file with the one we now have
- compare aliases as well.


The above constants are referenced in the following places:

- TPTP_HW_ALL    (parseHostList in TPTPUtil.c)
- TPTP_HW_LOCAL  (parseHostList in TPTPUtil.c)
- TPTP_HW_NET    (tptp_addNetwork, parseHostList in TPTPUtil.cpp)
- TPTP_HW_NAMED  (tptp_addNetwork, parseHostList in TPTPUtil.cpp)



TPTPUtil.cpp:

void tptp_addNetwork(network_list_t *list, int allow, tptp_host_wildcard_t wildcard, char *name, char *mask)
- called by parseHostList(...)

network_t *network;

network->allow=allow; // This handles the allow field.
network->wildcard=wildcard;  // This handles TPTP_HW_ALL and TPTP_HW_LOCAL

if wildcard is TPTP_HW_NAMED:
- This needs to be rewritten for IPv6.
- If a number is specified in here, then maskTemp is set to 255.255.255.255, and the type is changed to TPTP_HW_NET.
- ELSE, if a named host is specified here, then store that named host in network->hostname


if wildcard is TPTP_HW_NET:
- This needs to be rewritten for IPv6
- network->net is 4 byte format IP address.
- network->mask is 4 byte format IP address.
- This code converts a text string into IPv4 IP format.
- It converts net and mask to IPv4 4 byte format.


int parseHostList(const char *initString, network_list_t **nList):
- Called by 'createTransportListener' of ClientCTL.c.

No IPv6 changes required.

(network_list_t is malloc here. It's entirely possible for it to be NULL.)

Under <Hosts configuration="default">....</Hosts>, you will see either <Allow host=""/> or <Deny host=""/> tags here.

You can specify, 'host', 'net', or 'mask' as the above attributes.

if host = 'ALL' then it calls tptp_addNetwork(*nList, 0, TPTP_HW_ALL, NULL, NULL);
if host = 'LOCAL' then it calls tptp_addNetwork(*nList, 0, TPTP_HW_LOCAL, NULL, NULL);
else host exists, but isn't either of the above, then: tptp_addNetwork(*nList, 0, TPTP_HW_NAMED, host, NULL);
-  Adds it to nList, which is a 'network_list_t'. The second value is either allow or deny.

However, if host is not specified, then either net or mask is specified, and it calls:
- tptp_addNetwork(*nList, 0, TPTP_HW_NET, net, mask);




TransportSupportSocket:

getSocketPort (not used)

getHostInfo
Returns the IP address (4 byte format) of the given hostname.
Used by:
- unsigned long ConnectionImpl::getLocalIPAddress()
- unsigned long ConnectionImpl::getIPAddress(char* hostname) {
- unsigned long TCPDataServer::getLocalIPAddress()
- int getSocketIPString( SOCKET sock, char** ipAddrStr )

- Recommendation: Replace with equivalent struct sockaddr_storage * function.

convertIPAddressStringToUlong
- Converts 'dots and numbers' IP address to 4 byte format.

Used by:

- tptp_int32 createSocketPeerConnection( server_block_t* pServerData, tptp_string* sourceConnectionInfo, tptp_uint32* connectionID ) of SocketListener.c
o parses the <host></host> tag of sourceConnectionInfo, calls convertIPAddressStringToULong, passes the address to connectToTCPServer.

- tptp_int32 createPeerConnection( tptp_object* tlo, tptp_string* sourceConnectionInfo, tptp_uint32* connectionID ) of ClientCTL.c
o parses the <host></host> tag of sourceConnectionInfo, calls convertIPAddressStringToULong, passes the address to connectToTCPServer.

- int processServerReachCmd(fs_connection_block_t* con) of nativeFileServer.c
o Reads an int from the connection (which it presumes to be the IP address), and calls connectToTCPServer() with that address.

- Recommendation: Replace with equivalent struct sockaddr_storage * function. Also, create an IPv4M'ed copy for reference by the peer monitoring code.



getSocketIPString
Given a SOCKET, it converts its 4-byte IP format into 'dots and numbers' IP address. (If SOCKET passed in is NULL, it merely uses local host)
o createSocketPeerConnection in SocketListener.c (used to place IP into an xml tag)
o createPeerConnection in ClientCTL.c. (used to place IP into an xml tag)
o translateAndForwardPeerRequestMonitor (grabs the local IP in string form, converts it to 4 byte form,  and stores it in command->info.controller_request_monitor_port.node )
o translateAndForwardRequestMonitor (grabs the local IP in string form, converts it to 4 byte form,  and stores it in command->info.controller_request_monitor_port.node )
- Recommendation: Replace with equivalent struct sockaddr_storage * function. Create an IPv4M'ed copy for reference by the peer monitoring code.

getPeerIPString

- Given a socket, store the dots and numbers format for the person we're connected to.
o Used only by serveRequests in CCTLServer.c. It uses the 'dots and numbers' string to convert into a 4 byte format ip, then calls tptp_checkHost on it.
- Recommendation: Replace with equivalent struct sockaddr_storage * function.

getTargetHostInfo
- Given a host name string, return hostent.
o Used only by unsigned long ConnectionImpl::getIPAddress(char* hostname). Here it's used only to convert the string to the 4-byte format
o When getIPAddress is rewritten, dump this method.
- Recommendaiton: This function is entirely IPv4, and should be removed. Rewrite getIPAddress to use sockaddr_storage *

getPeerName
- Given a socket, store the peer of the socket in 4 byte format.
o Used by int getClientIP(client_connection_block_t* ccb, unsigned char *buffer, int *length) of RACClientSupport.c.
o Called by getClientIP, the socket is read from ccb, and the four-byte address is stored in buffer.


connectToTCPServer
- Given an IP address in 4 byte format, and a portnumber, return a SOCKET to that connection.
- Recommendation: Rewrite the function to take struct sockaddr_storage * instead of the four byte format. Then fix the calling functions below to pass it that format. For the peer monitoring functions, create an empty function called connectToTCPServerIPv4M(...) and replace all RPM calls with this method.

Used by
:
o int ConnectionImpl::connect(INode* node, int port)
o int ConnectionImpl::connect(class INode* node, ConnectionInfo* connInfo)
o int ConnectionImpl::createDataConnection(int direction, int flags)

o void TCPDataServer::connect()

o tptp_int32 createSocketPeerConnection( server_block_t* pServerData, tptp_string* sourceConnectionInfo, tptp_uint32* connectionID ); in SocketListener.c
o tptp_int32 createPeerConnection( tptp_object* tlo, tptp_string* sourceConnectionInfo, tptp_uint32* connectionID )  in ClientCTL
o int processServerReachCmd(fs_connection_block_t* con) in nativeFileServer.c

o SOCKET openClientDataSocket(tptp_int32 ip, tptp_int32 port) in RACClientSupport.c



Native Code Structs that reference IP Addresses

TransportSupport.c:

typedef struct {
    unsigned short addressLength;
    unsigned char *addresses;          
} tptp_IPAddresses_t;

- Referenced ONLY in TransportSupport.c, doesn't leave the C file.
- Used by isLocalHost() and tptp_checkHost().
- Data is stored in it by tptp_getLocalIPAddresses(...)

Recommendation: Leave as is for Stage 2.


MsgPipeline.h:

/* Structure used to override peer monitoring defaults */
typedef struct PeerAttachInfo_tag
{
    int           usePeerAttachPort;
    int           usePeerAttachAddress; // Not an IP Address
    int           peerAttachPort;
    unsigned int  peerAttachAddress;      // IP address, 4 byte format.
} PeerAttachInfo_t;

Generated only by parseAndProcessParameters(...), which parses the command line.
Stored in ConnectionManager_t.

- passed into setPeerAttachInfo (which copies the together the ConnectionManager_t->peerInfo data structure and the cctl_state_data_t of CCTL.)

Call stack:
return tl->setPeerAttachInfo( &tl->tlo, &cm->peerInfo );
tptp_int32 connectionManager_initializePeerConnectionTransport( ConnectionManager_t* cm, char* peerConnectionTransport );
tptp_int32 configurationManager_readConfigFile( ConfigurationManager_t* cm );
main(...) in AgentController.


Recommend: Leave PeerAttachInfo_t and parseAndProcessParameters()  for stage 4.


TPTPUtils.h:

typedef struct {
    int  allow;                /* Is this an Allow entry or a Deny? */
    tptp_host_wildcard_t  wildcard;        /* Is this a range of addresses or an exact address? */
    unsigned char net[4];        /* The network address information in network byte order.  Note that this is IPV4 specific */
    unsigned char mask[4];        /* the subnet mask information in network byte order.  Note that this is IPV4 specific */
    char *hostname;
} network_t;

net/mask are used by:
- void tptp_addNetwork(network_list_t *list, int allow, tptp_host_wildcard_t wildcard, char *name, char *mask)
- int parseHostList(const char *initString, network_list_t **nList)
- BOOL tptp_checkHost(network_list_t *list, unsigned char *address).

- Recommend: Leave for stage 4.

RASocket:

/* IPV4 and IPV6 ipaddress compatable structure */
typedef struct {
    unsigned char addrLength;
    unsigned char *addr;
} ra_ipaddr_t;
The above is used only by the peer monitoring code. RABinding.c/RABinding.h, and hcjbnd.c.

- Recommend: Leave for stage 4.




typedef struct {
    unsigned short addressLength;
    unsigned char *addresses;          
} ra_IPAddresses_t;

produced only by short ra_getLocalIPAddresses(ra_IPAddresses_t *addr).
used by print.c of hcjbnd java_profiler:     static unsigned short printIPAddressAttribute(ThreadPrivateStorage *tps, unsigned short current)
also used by print.c of hcjbnd java_profiler:     void jvmpiAgent_printTraceStartElement(ThreadLocalStorage *tps, char *options)  (but the ra_IPAddresses_t isn't actually used)

- Recommend: Rewrite in stage 2.


typedef struct {
[...]
    /* Peer monitoring related fields */
    int             usePeerAttachPort;
    int             usePeerAttachAddress;     // peerAttachAddress is used only if this is set to 1, otherwise local host is used. If this is set to 0, peerAttachAddress is NEVER used.
    int             peerAttachPort;
    unsigned int    peerAttachAddress;     // IPv4 IP Address.. seems to double as a local IP address.

    network_list_t    *network_list;
[...]
} cctl_state_data_t; (defined in ClientCtl.h)

- Recommend: Leave for stage 4.



ra_command.t:
- defined in RAComm.h of tptp/include/compatibility.
- defined in RATypes.h of src-native-new/src/transport/RACommon

		struct {
ra_uint_t context;
ra_uint_t processId;
ra_string_t agent;
ra_string_t node; /* node->data is a 4 byte IP address */
ra_uint_t peerProcessId;
ra_string_t peerAgent;
ra_string_t peerNode; /* peerNode->data is a 4 byte IP address */
}agent_request_monitor, /* AGENT_REQUEST_ATTACH */
controller_request_monitor, /* CONTROLLER_REQUEST_MONITOR */
peer_unreachable; /* PEER_UNREACHABLE */

		struct {
ra_uint_t context;
ra_uint_t consoleIP; /* This is transmitted, but is NOT ever used. */
ra_uint_t consolePort;
ra_string_t executable;
ra_string_t arguments;
ra_string_t location;
ra_array_t environment;
ra_array_t agents;
}launch_process; /* LAUNCH_PROCESS*/

		struct {
ra_uint_t context;
ra_uint_t processId;
ra_string_t agent;
ra_uint_t ip; /* This value is transmitted, but is not ever used by the NEW AC (see below). */
ra_uint_t port;
}start_monitor_remote; /* START_MONITOR_REMOTE */


ARM/CRM/PU:
Recommendation: Wait for stage 4.

launch_process->consoleIP
:
References in only three projects: CompSupport, RACommon, and TPTPClientCompTL. None of these projects use the value, they only translate it, read it from a buffer, or write it to a buffer. I tested this by overwriting the value in the AC and profiling from a remote machine, and it works as expected.
Recommendation: Value is not used, no change required.

start_monitor_remote->ip:
hcjbnd.c:
- The only places where start_monitor_remote->ip is used is under RA_START_MONITORING_AGENT_REMOTE code, which isn't  used with the new AC.
- The only other references to start_monitor_remote are fields unrelated to IPv6. No rewrites required.

JvmpiWriter.c:
- Both references are RA_START_MONITORING_AGENT_REMOTE only.

hcthread.c:
- RA_START_MONITORING_AGENT_REMOTE only.

RACSupport.c (CompSupport):
- Reading from buffer, writing to buffer, and translation, only. No functional use here.

RAComm.c (RACommon):
- Reading from buffer, writing to buffer, and translation, only. No functional use here.

TPTPClientCompTL:
- IP address fields not used, no rewrite required.

Recommendation: No rewrites required.



Old Hyades AC Code / Agent/Client Compatibility Layer Code


Client CTL

tptp_int32 startTransportListener(tptp_object* tlo)
- Once getTheSocket is replaced, this method will need to be rewritten to use the new getTheSocket() method, and to listen on multiple sockets, rather than just the one.


RACClientSuport.c:

int getClientIP(client_connection_block_t* ccb, unsigned char *buffer, int *length)
- Retrieves the address of the peer that is connected to the AC on the ccb.
- If the ccb is a native socket, then it calls getPeerName (which returns in 4 byte format) and stores it in buffer.
- If the ccb is a java socket, then it looks like it gets the 4-byte or 16 byte formats.

o Connect2Ac.c - startProcess(...) - calls getClientIP(), then calls openClientDataSocket() which returns a SOCKET, which is used from hereon.
o RACmdHandlers.c - handleLaunchProcess(...), calls startProcess() with the 6th parameter being the 4-byte address from clientIP. Note: This value is NOT USED by startProcess.
o RACmdHandlers.c - handleStartMonitoring(...), . called by processMessage(). calls GetClientIP(), passes it directly into openClientDataSocket.

Recommendation: When openClientDataSocket is rewritten, rewrite the above with calls to the new IPv4/IPv6 agnostic code.



Connect2AC.c:

PID startProcess( client_connection_block_t* ccb,  ra_string_t *exe, ra_string_t *args, ra_string_t *location, ra_array_t *environment, unsigned long remoteConsoleIP, unsigned short remoteConsolePort, ra_array_t *finalEnvironment, SOCKET *consoleSock, ra_string_t *uuid):

- remoteConsoleIP arguments needs to be rewritten. HOWEVER, this function doesn't use the value for anything, or touch it at all. So no change here.

- calls getClientIP()  followed by openClientDataSocket(). The value is then passed into openClientDataSocket(). The value is not used after this.

o startProcess is called only by BOOL handleLaunchProcess( client_connection_block_t* ccb, ra_command_t* command ) in RACmdHandlers.c

Recommendation: Rewrite the getClientIP/openClientDataSocket() call to use struct sockaddr_storage*  equivalent. Leave the remoteConsoleIP param alone (for now).


SOCKET openClientDataSocket(tptp_int32 ip, tptp_int32 port)
- called only by handleLaunchProcess and handleStartMonitoring, above.
-  ONLY calls   connectToTCPServer(ip, (unsigned short) port, &sock);
- Recommendation: When connectToTCPServer is rewritten, rewrite this.


tptp_int32 translateAndForwardPeerRequestMonitor( tl_state_data_t*   stateData, client_connection_block_t* ccb, tptp_int32   context,  tptp_string*   peerHost,
tptp_string*  peerPort, tptp_string*  peerAgentName,  tptp_string*   peerAgentPID,  tptp_string*    srcAgentName, tptp_string*  srcAgentPID )
- peerHost is a standard dots and numbers string. No changes to function signature required.

Recommendation: Wait for stage 4. IPv4Mize any functions that this function uses.


Native File Server


THREAD_USER_FUNC_RET_TYPE startNativeFileServer(LPVOID args)

- Exactly as above, once getTheSocket is rewritten, as described above, this method will need to be rewritten to use the new getTheSocket() method, and to listen on multiple sockets, rather than just the one.
- convertIPAddressStringToUlong is used in processServerReachCmd().


RASocket

RASocket exports the following functions, used by other projects:

ra_connectToTCPServer (hcjbnd.c, java_profiler, hcthread.c)
- Note: The above code only calls this method on receiving "RA_START_MONITORING_AGENT_REMOTE". The New AC ACTL does not ever send this.
- Recommendation: Mark as IPv4 only, do not port.

int ra_writeToSocket(SOCKET fd, char *buffer, ra_uint_t byteCount)  (RADataTransfer.c)
o called only in ra_writeMessageBlock(...)
o used only in hcjbnd.c, java_profiler, perfmon, hcthread.
o The code itself is a simple send(...) on a socket.
- Recommendation: Does not need to be be rewritten.

ra_getLocalIPAddress (not called)


ra_getLocalIPAddresses (java_profiler)
o printIPAddressAttribute (At this point it is converted into a string, e.g: "9.26.145.102,127.0.0.1".  We could use the IPv6 structure between these two, and rewrite only this part)
Recommendation: Rewrite ra_getLocalIPAddresses to return sockaddr_storage, and rewrite printIPAddressAttribute to use this new struct.

- void ra_closeSocket(SOCKET sockfd) (hcjbnd.c, java_profiler, hcthread.c)
- The code itself is a simple shutdown on a socket. No changes.

- ra_getLocalHostName (java_profiler)
o called by printHostNameAttribtue() (where it is converted to a string... same conversion method as ra_getLocalIPAddresses above)
- Does not need to be rewritten. Is not IPv6 specific.

ra_win32InitializeSockets
- Code is not IPv6 specific. No rewrites needed.

RASocket exports the following functions which are not referenced outside of RASocket, and are not called within RASocket itself (they're unused):
- ra_createBoundUDPServer (RASocket only)
- ra_createTCPServer (RASocket only)
- ra_getFormattedLocalIPAddress (RASocket only)






GetAddress Revealed Problems (All Hyades, All Stage 4)

Note:
getAddress(...) can be used to get the byte array from an InetAddress. In any number of places this is used, but only 4 bytes are accepted.

This reveals problems in:
requestMonitorThroughPeer0p of RemoteComponentSkeleton:

public void requestMonitorThroughPeer_p(InetAddress addr, long port, String agentUUID, long timeout)
- requestMonitorThroughPeer0p(addr.getAddress(), port, agentUUID);
- private native void requestMonitorThroughPeer0p(byte[] addr, long port, String agentUUID);
- Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0p___3BJLjava_lang_String_2(JNIEnv *env, jobject obj, jbyteArray ipaddr, jlong port, jstring agentUUID)

- Create a ra_ipaddr_t addr, store the FULL address in there (however many bytes it is given), calls ra_requestPeerMonitor2_p.
- Sets fields in command->info.agent_request_monitor and calls send message on the resulting message. The command->tag is either RA_AGENT_REQUEST_MONITOR or RA_AGENT_REQUEST_MONITOR_PORT depending on the circumstance.

public void requestMonitorThroughPeer_p(InetAddress addr, long port, long pid, String agentName, long timeout) {
- requestMonitorThroughPeer0p(addr.getAddress(), port, pid, agentName);
- native void requestMonitorThroughPeer0p(byte[] addr, long port, long pid, String agentName);
- Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0p___3BJJLjava_lang_String_2(JNIEnv *env, jobject obj, jbyteArray ipaddr, jlong port, jlong pid, jstring agentName)
- As above, except calls ra_requestPeerMonitor_p instead, which itself uses agent_request_monitor and either of those two tags depending on circumstance.

Recommendation: Neither of these technically need to change, as long as the parsing side is handling them properly.


StartMonitoringRemoteAgentCommand: setInetAddress(..)
SMRAC is sent by startMonitoring() of AgentImpl.
When 'start_monitor_remote' is supplemented/replaced with a IPv6 compatible message, a new Java StartMonitoringRemoteAgentCommand will need to be written to support this IPv6 message. Thus, this SMRAC command itself probably won't change.

Recommendation: Stage 4: Implement new IPv6 class, that will supplement this class. Essentially the message that we send out in this class is just telling the agent controller to connect back to us at a particular IP and port.So this new command should be easy to implement.

MonitorPeerRequestCommand: getPeerNode(). getTargetNode().
MPRC kicks off the peer request monitoring feature. An agent sends this to it's agent controller to begin the RPM process. This class will be supplemented by a class that uses IPv6 compatible fields.

Recommendation: Stage 4: Same as SMRAC.

Message: public static int writeRAInetAddressToBuffer(byte[] buffer, int offset, RAInetAddress addr).
- Nothing calls it. Deprecate?

Console: public void run { }
- The Console class is used by the LaunchProcessCommand, and by Process/ProcessImpl.
- Console stores its IP as a long. It does the conversion itself, and  the IP will be stored incorrectily if  Java is using IPv6 rather than IPv4.
- run() method then calls determineServerReach() of IFileManagerExtended, which takes an InetAddress. However, DetermineServerReach sends a String so it is IPv6 compatible.
- LaunchProcessCommand reads the console and writes the console value as per it's Hyades message.
- The IP address of Console is ONLY used by LaunchProcessCommand, and no one uses that value from LaunchProcessCommand.
- And inside the agent controller, that value isn't used either. It's read and written to the message, but never accessed or used. I had the client sends 0s for this, and it worked fine (even connecting to a remote machine).

Recommendation: Leave as is.

DataChannelImpl: hc_flushDCBufferToSocket
- Unused.