LSP packet modify - winsock

anybody care to share some insights on how to use LSP for packet modifying ?
I am using the non IFS subtype and I can see how (pseudo?) packets first enter WSPRecv. But how do I modify them ? My inquiry is about one single HTTP response that causes WSPRecv to be called 3 times :((. I need to modify several parts of this response, but since it comes in 3 slices, it is pretty hard to modify it accordingly. And, maybe on other machines or under different conditions (such as high traffic) there would only be one sole WSPRecv call, or maybe 10 calls. What is the best way to work arround this (please no NDIS :D), and how to properly change the buffer (lpBuffers->buf) by increasing it ?
int WSPAPI
WSPRecv(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno
)
{
LPWSAOVERLAPPEDPLUS ProviderOverlapped = NULL;
SOCK_INFO *SocketContext = NULL;
int ret = SOCKET_ERROR;
*lpErrno = NO_ERROR;
//
// Find our provider socket corresponding to this one
//
SocketContext = FindAndRefSocketContext(s, lpErrno);
if ( NULL == SocketContext )
{
dbgprint( "WSPRecv: FindAndRefSocketContext failed!" );
goto cleanup;
}
//
// Check for overlapped I/O
//
if ( NULL != lpOverlapped )
{
/*bla bla .. not interesting in my case*/
}
else
{
ASSERT( SocketContext->Provider->NextProcTable.lpWSPRecv );
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPRecv(
SocketContext->ProviderSocket,
lpBuffers,
dwBufferCount,
lpNumberOfBytesRecvd,
lpFlags,
lpOverlapped,
lpCompletionRoutine,
lpThreadId,
lpErrno);
SetBlockingProvider(NULL);
//is this the place to modify packet length and contents ?
if (strstr(lpBuffers->buf, "var mapObj = null;"))
{
int nLen = strlen(lpBuffers->buf) + 200;
/*CHAR *szNewBuf = new CHAR[];
CHAR *pIndex;
pIndex = strstr(lpBuffers->buf, "var mapObj = null;");
nLen = strlen(strncpy(szNewBuf, lpBuffers->buf, (pIndex - lpBuffers->buf) * sizeof (CHAR)));
nLen = strlen(strncpy(szNewBuf + nLen * sizeof(CHAR), "var com = null;\r\n", 17 * sizeof(CHAR)));
pIndex += 18 * sizeof(CHAR);
nLen = strlen(strncpy(szNewBuf + nLen * sizeof(CHAR), pIndex, 1330 * sizeof (CHAR)));
nLen = strlen(strncpy(szNewBuf + nLen * sizeof(CHAR), "if (com == null)\r\n" \
"com = new ActiveXObject(\"InterCommJS.Gateway\");\r\n" \
"com.lat = latitude;\r\n" \
"com.lon = longitude;\r\n}", 111 * sizeof (CHAR)));
pIndex = strstr(szNewBuf, "Content-Length:");
pIndex += 16 * sizeof(CHAR);
strncpy(pIndex, "1465", 4 * sizeof(CHAR));
lpBuffers->buf = szNewBuf;
lpBuffers->len += 128;*/
}
if ( SOCKET_ERROR != ret )
{
SocketContext->BytesRecv += *lpNumberOfBytesRecvd;
}
}
cleanup:
if ( NULL != SocketContext )
DerefSocketContext( SocketContext, lpErrno );
return ret;
}
Thank you

my comment worked out. http response headers / request turned out to end in \r\n\r\n.

Related

Linux TCP socket timestamping option

Quoting form this online kernel doc
SO_TIMESTAMPING
Generates timestamps on reception, transmission or both. Supports
multiple timestamp sources, including hardware. Supports generating
timestamps for stream sockets.
Linux supports TCP timestamping, and I tried to write some demo code to get any timestamp for TCP packet.
The server code as below:
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
// Note: I am trying to get software timestamp only here..
int oval = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
int olen = sizeof( oval );
if ( setsockopt( client_sock, SOL_SOCKET, SO_TIMESTAMPING, &oval, olen ) < 0 )
{ perror( "setsockopt TIMESTAMP"); exit(1); }
puts("Connection accepted");
char buf[] = "----------------------------------------";
int len = strlen( buf );
struct iovec myiov[1] = { {buf, len } };
unsigned char cbuf[ 40 ] = { 0 };
int clen = sizeof( cbuf );
struct msghdr mymsghdr = { 0 };
mymsghdr.msg_name = NULL;
mymsghdr.msg_namelen = 0;
mymsghdr.msg_iov = myiov;
mymsghdr.msg_iovlen = 1;
mymsghdr.msg_control = cbuf;
mymsghdr.msg_controllen = clen;
mymsghdr.msg_flags = 0;
int read_size = recvmsg( client_sock, &mymsghdr, 0);
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
else
{
struct msghdr *msgp = &mymsghdr;
printf("msg received: %s \n",(char*)msgp->msg_iov[0].iov_base);// This line is successfully hit.
// Additional info: print msgp->msg_controllen inside gdb is 0.
struct cmsghdr *cmsg;
for ( cmsg = CMSG_FIRSTHDR( msgp );
cmsg != NULL;
cmsg = CMSG_NXTHDR( msgp, cmsg ) )
{
printf("Time GOT!\n"); // <-- This line is not hit.
if (( cmsg->cmsg_level == SOL_SOCKET )
&&( cmsg->cmsg_type == SO_TIMESTAMPING ))
printf("TIME GOT2\n");// <-- of course , this line is not hit
}
}
Any ideas why no timestamping is available here ? Thanks
Solution
I am able to get the software timestamp along with hardware timestamp using onload with solarflare NIC.
Still no idea how to get software timestamp alone.
The link you gave, in the comments at the end, says:
I've discovered why it doesn't work. SIOCGSTAMP only works for UDP
packets or RAW sockets, but does not work for TCP. – Gio Mar 17 '16 at 9:331
it doesn't make sense to ask for timestamps for TCP, because there's
no direct correlation between arriving packets and data becoming
available. If you really want timestamps for TCP you'll have to use
RAW sockets and implement your own TCP stack (or use a userspace TCP
library). – ecatmur Jul 4 '16 at 10:39

modbus_read_register - Error connection timed out

We are using libmodbus library to read register values from energy meter EM6400 which supports Modbus over RTU. We are facing the following two issues.
1) We are facing an issue with modbus_read_registers API, this API returns -1 and the error message is:
ERROR Connection timed out: select.
After debugging the library, we found this issue is due to the echo of request bytes in the response message.
read() API call in _modbus_rtu_recv returns request bytes first followed by response bytes. As a result, length_to_read is calculated in compute_data_length_after_meta() based on the request bytes instead of response bytes (which contains the number of bytes read) and connection timed out issue occurs.
We tried to use both 3.0.6 and 3.1.2 libmodbus versions but same issue occurs in both the versions.
2) modbus_rtu_set_serial_mode (ctx, MODBUS_RTU_RS485) returns "BAD file descriptor".
Please confirm if there is any API call missing or any parameter is not set correctly.
Our sample code to read register value is as follows.
int main()
{
modbus_t *ctx;
uint16_t tab_reg[2] = {0,0};
float avgVLL = -1;;
int res = 0;
int rc;
int i;
struct timeval response_timeout;
uint32_t tv_sec = 0;
uint32_t tv_usec = 0;
response_timeout.tv_sec = 5;
response_timeout.tv_usec = 0;
ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'E', 8, 1);
if (NULL == ctx)
{
printf("Unable to create libmodbus context\n");
res = 1;
}
else
{
printf("created libmodbus context\n");
modbus_set_debug(ctx, TRUE);
//modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |MODBUS_ERROR_RECOVERY_PROTOCOL);
rc = modbus_set_slave(ctx, 1);
printf("modbus_set_slave return: %d\n",rc);
if (rc != 0)
{
printf("modbus_set_slave: %s \n",modbus_strerror(errno));
}
/* Commented - Giving 'Bad File Descriptor' issue
rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
printf("modbus_rtu_set_serial_mode: %d \n",rc);
if (rc != 0)
{
printf("modbus_rtu_set_serial_mode: %s \n",modbus_strerror(errno));
}
*/
// This code is for version 3.0.6
modbus_get_response_timeout(ctx, &response_timeout);
printf("Default response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
response_timeout.tv_sec = 60;
response_timeout.tv_usec = 0;
modbus_set_response_timeout(ctx, &response_timeout);
modbus_get_response_timeout(ctx, &response_timeout);
printf("Set response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
/* This code is for version 3.1.2
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Default response timeout:%d sec %d usec \n",tv_sec,tv_usec );
tv_sec = 60;
tv_usec = 0;
modbus_set_response_timeout(ctx, tv_sec,tv_usec);
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Set response timeout:%d sec %d usec \n",tv_sec,tv_usec );
*/
rc = modbus_connect(ctx);
printf("modbus_connect: %d \n",rc);
if (rc == -1) {
printf("Connection failed: %s\n", modbus_strerror(errno));
res = 1;
}
rc = modbus_read_registers(ctx, 3908, 2, tab_reg);
printf("modbus_read_registers: %d \n",rc);
if (rc == -1) {
printf("Read registers failed: %s\n", modbus_strerror(errno));
res = 1;
}
for (i=0; i < 2; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
avgVLL = modbus_get_float(tab_reg);
printf("Average Line to Line Voltage = %f\n", avgVLL);
modbus_close(ctx);
modbus_free(ctx);
}
}
Output of this sample is as follows:
created libmodbus context
modbus_set_slave return: 0
modbus_rtu_set_serial_mode: -1
modbus_rtu_set_serial_mode: Bad file descriptor
Default response timeout:0 sec 500000 usec
Set response timeout:60 sec 0 usec
Opening /dev/ttyUSB0 at 19200 bauds (E, 8, 1)
modbus_connect: 0
[01][03][0F][44][00][02][87][0A]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><03><0F><44><00><02><87><0A><01><03><04><C4><5F><43><D4><C6><7E>modbus_read_registers: -1
Read registers failed: Connection timed out
reg[0]=0 (0x0)
reg[1]=0 (0x0)
Average Line to Line Voltage = 0.000000
Issue 1) is probably a hardware issue, with "local echo" enabled in your RS-485 adapter. Local echo is sometimes used to confirm sending of data bytes on the bus. You need to disable it, or find another RS-485 adapter.
I have written about this in the documentation of my MinimalModbus Python library: Local Echo
It lists a few common ways to disable local echo in RS-485 adapters.

cannot connect to lwip binded socket address after idle for sometime

I am using lwIP under FreeRTOS, the IP server runs on an ARM based device (Xilinx Zynq-7020) and the client is a windows.
At the server side, when I bind, listen, and accept an address:port, the client can connect to and read/write from this address. And after program exit, idle for some short time (10s~30s) then start again, it can also read/write from the server. Howeber, when I exit the client, and idle for a long time (>30s), I cannot connect to the server anymore. And at the server side, it no longer accept any address. Any solutions ?
The code for the server side is listed below:
void echo_server( void *pvParameters )
{
long lSocket, lClientFd, lAddrLen = sizeof( struct sockaddr_in );
struct sockaddr_in sLocalAddr;
struct sockaddr_in client_addr;
static char dIn[BUF_SIZE];
int ret;
( void ) pvParameters;
int on = 1;
int idle = 60;
int intvl = 15;
int cnt = 3;
/* step 1. create and setopts */
lSocket = lwip_socket(AF_INET, SOCK_STREAM, 0);
if( lSocket >= 0 )
{
lwip_setsockopt(lSocket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
//lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
//lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
//lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
// prepare bind on port
sLocalAddr.sin_family = AF_INET;
sLocalAddr.sin_len = sizeof(sLocalAddr);
sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sLocalAddr.sin_port = ntohs( ( ( unsigned short ) ECHO_PORT ) );
/* step 2. bind */
if( lwip_bind( lSocket, ( struct sockaddr *) &sLocalAddr, sizeof( sLocalAddr ) ) < 0 )
{
lwip_close( lSocket );
vTaskDelete( NULL );
}
/* step 3. listen */
if( lwip_listen( lSocket, BACKLOG ) != 0 )
{
lwip_close( lSocket );
vTaskDelete( NULL );
}
for( ;; )
{
/* step 4. accept */
xil_printf("(ZYNQ-ECH) wait connection\n");
lClientFd = lwip_accept(lSocket, ( struct sockaddr * ) &client_addr, ( u32_t * ) &lAddrLen );
xil_printf("(ZYNQ-ECH) accept connection\n");
lwip_setsockopt(lClientFd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
//lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
//lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
//lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
// if client socket created
if( lClientFd > 0L )
{
int packet = 0;
while(1)
{
ret = mfeit_read(lClientFd, dIn);
if (ret == -1 || ret == 0)
break;
ret = mfeit_write( lClientFd, dIn, ret );
if (ret == -1 || ret == 0)
break;
packet ++;
}
xil_printf("(ZYNQ-ECH) close connection, total = %d\n", packet);
lwip_close( lClientFd );
}
}
}
/* Will only get here if a listening socket could not be created. */
xil_printf("(ZYNQ-ECH) task killed !!\n");
vTaskDelete( NULL );
}
I forgot about that stuff, but first you need to set up proper way of keep-alive.
is keep-alive on server configured, so for how long he is persisting keep-alive
set proper time for keep-alive on your side.
Don't do keep-alive with 2hrs or someting. Create a new socket for that it's bad for server resources.

For Linux 3.10 what what changes do I need to make to get netmap/virtio_net working?

The netmap/virtio_net driver didn't work (Linux 3.10 kernel). There were two problems.
On the 3.10.60 kernel from kernel.org, the patch to virtio_net.c didn't
work, one part of the patch was rejected. This is easily fixed.
More serious, was that the virtio initialization code didn't work, nor
did the packet receive code. The basic problem was failure to initialize
the indices properly and failure to maintain a 1 slot separation between
head/tail indices. (Same problem 2 locations in the code.)
This problem is easily seen by creating a KVM guest with a
netmap/virtio_net driver, and simply pinging the guest from the host.
The receive traffic can easily be monitored using the pkt-gen tool on
the guest.
The first 255 pings will work fine, when the index hits 255, then the
packet receive will fail, and will continue to fail every time on slot 255.
I've included patches for both problems in the hopes that the source code
will be updated and others won't have to find these problems.
First virtio_netmap_3.10.60.patch:
# patch is the whole netmap virtio driver patch for 3.10.60 (from
# kernel.org), and it applies correctly.
#
Index: linux-3.10.60/drivers/net/virtio_net.c
===================================================================
--- linux-3.10.60.orig/drivers/net/virtio_net.c 2014-11-14 11:48:23.000000000 -0500
+++ linux-3.10.60/drivers/net/virtio_net.c 2014-11-21 12:54:29.751760095 -0500
## -131,6 +131,10 ##
struct notifier_block nb;
};
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
+#include <virtio_netmap.h>
+#endif
+
struct skb_vnet_hdr {
union {
struct virtio_net_hdr hdr;
## -210,6 +214,10 ##
/* Suppress further interrupts. */
virtqueue_disable_cb(vq);
+#ifdef DEV_NETMAP
+ if (netmap_tx_irq(vi->dev, vq2txq(vq)))
+ return;
+#endif
/* We were probably waiting for more output buffers. */
netif_wake_subqueue(vi->dev, vq2txq(vq));
}
## -646,7 +654,16 ##
struct virtnet_info *vi = rq->vq->vdev->priv;
void *buf;
unsigned int r, len, received = 0;
+#ifdef DEV_NETMAP
+ int work_done = 0;
+
+ if (netmap_rx_irq(vi->dev, vq2rxq(rq->vq), &work_done)) {
+ napi_complete(napi);
+ ND("called netmap_rx_irq");
+ return 1;
+ }
+#endif
again:
while (received < budget &&
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
## -679,6 +696,16 ##
{
struct virtnet_info *vi = netdev_priv(dev);
int i;
+#ifdef DEV_NETMAP
+ int ok = virtio_netmap_init_buffers(vi);
+
+ netmap_enable_all_rings(dev);
+ if (ok) {
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ virtnet_napi_enable(&vi->rq[i]);
+ return 0;
+ }
+#endif
for (i = 0; i < vi->max_queue_pairs; i++) {
if (i < vi->curr_queue_pairs)
## -972,6 +999,9 ##
struct virtnet_info *vi = netdev_priv(dev);
int i;
+#ifdef DEV_NETMAP
+ netmap_disable_all_rings(dev);
+#endif
/* Make sure refill_work doesn't re-enable napi! */
cancel_delayed_work_sync(&vi->refill);
## -1644,6 +1674,10 ##
goto free_recv_bufs;
}
+#ifdef DEV_NETMAP
+ virtio_netmap_attach(vi);
+#endif
+
/* Assume link up if device can't report link status,
otherwise get link status from config. */
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
## -1690,6 +1724,9 ##
{
struct virtnet_info *vi = vdev->priv;
+#ifdef DEV_NETMAP
+ netmap_detach(vi->dev);
+#endif
unregister_hotcpu_notifier(&vi->nb);
/* Prevent config work handler from accessing the device. */
Next is the virtio_netmap.patch
# There is a problem with the initialization, and during read packet with
# control of the indices .
#
# This problem is easily seen by building a KVM netmap/virtio_net driver, and
# simply pinging it (host pings KVM guest). All goes well, until ring buffer
# reaches index 255, and no packet is actually received. This will fix that
# problem and resulted in a working driver.
#
Index: b/LINUX/virtio_netmap.h
===================================================================
--- a/LINUX/virtio_netmap.h 2014-11-21 16:26:03.951278021 -0500
+++ b/LINUX/virtio_netmap.h 2014-11-21 16:26:25.451386665 -0500
## -398,8 +398,8 ##
* Second part: skip past packets that userspace has released.
*/
nm_i = kring->nr_hwcur; /* netmap ring index */
- if (nm_i != head) {
- for (n = 0; nm_i != head; n++) {
+ if (nm_next(nm_i, lim) != head) {
+ for (n = 0; nm_next(nm_i, lim) != head; n++) {
struct netmap_slot *slot = &ring->slot[nm_i];
void *addr = NMB(slot);
int err;
## -421,7 +421,7 ##
virtqueue_kick(vq);
nm_i = nm_next(nm_i, lim);
}
- kring->nr_hwcur = head;
+ kring->nr_hwcur = nm_i;
}
/* We have finished processing used RX buffers, so we have to tell
## -454,6 +454,7 ##
for (r = 0; r < na->num_rx_rings; r++) {
COMPAT_DECL_SG
struct netmap_ring *ring = na->rx_rings[r].ring;
+ struct netmap_kring *kring = &na->rx_rings[r];
struct virtqueue *vq = GET_RX_VQ(vi, r);
struct scatterlist *sg = GET_RX_SG(vi, r);
struct netmap_slot* slot;
## -485,6 +486,7 ##
if (VQ_FULL(vq, err))
break;
}
+ kring->nr_hwcur = i;
D("added %d inbufs on queue %d", i, r);
virtqueue_kick(vq);
}

Bad socket id, Stream closed error + blackberry socket connection

I am writing a program in blackberry curve 9300 using socketConnection. I get stream closed/bad socket id error when I try to read the inputstream.
Can you suggest me what could be the issue.
String url = Constants.SOCKET + serverIp + Constants.COLON + serverPort + UserInfo.getConnectionType();
//connection open
socketConne`enter code here`ction = (SocketConnection) Connector.open(url, Connector.READ_WRITE,true);
socketConnection.setSocketOption(SocketConnection.DELAY, 0);
socketConnection.setSocketOption(SocketConnection.KEEPALIVE, 1);
socketConnection.setSocketOption(SocketConnection.RCVBUF, 16834);
socketConnection.setSocketOption(SocketConnection.LINGER, 10);
outputStream = socketConnection.openDataOutputStream();
//Output stream deligated to Sender Object to send the command
sender = new Sender(outputStream);
sender.send(command);
inputStream = socketConnection.openDataInputStream();
//read inputstream
while (tobeRead < toRead && retryCount < 5) {
try {
if ((toRead - tobeRead) > 8192) {
readBufferLength = 8192;
} else {
readBufferLength = (toRead - tobeRead);
}
buffer = new byte[readBufferLength + 1];
bytesRead = inputStream.read(buffer, 0, readBufferLength);
sb.append(new String(buffer, 0, bytesRead));
tobeRead += bytesRead;
totalBytesRead += bytesRead;
} catch (Exception cce) {
}
}
say if number of bytes to read is 5192. I get say 2123 bytes then it iterates the loop, next time while reading it fails. I run this in seperate thread. I use WIFI network for connectivity