how do I reassemble TCP packet in LUA dissector? - tcp

I have a dissector that runs above the TCP protocol and has data that flows on more than one TCP packet.
I want to assemble the data before I convert everything, so I understood that I need tcp_dissect_pdus() for it, but I can't find documentation or examples for it.
Can anyone direct me to it or help me understand how I use it?

There is no wslua API for tcp_dissect_pdus. But you can implement it yourself.
If you want to assemble pdu that span two or more packets it's rather simple:
function slicer.dissector(tvb, pinfo, tree)
...
local pdu_length = get_pdu_length(...)
if pdu_length > tvb:len() then
pinfo.desegment_len = pdu_length - tvb:len()
else
do_dissection(tvb, pifo, tree)
end
return
end
If you don't know exact length of the pdu you can do:
pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT
You should read README.developer section 2.7.

Related

At where TCP New Reno set the threshold value once a packet is dropped in NS3

In TCP New Reno it set the threshold value to half of the current CWND once a packet drop is identified. I need to find the method, that does the task.
In tcp-l4-protocol.h it uses TcpClassicRecovery as the recovery method. In TcpClassicRecovery entering phase, it uses the following code segment to set the current CWND,
void
TcpClassicRecovery::EnterRecovery (Ptr<TcpSocketState> tcb, uint32_t dupAckCount,
uint32_t unAckDataCount, uint32_t lastSackedBytes)
{
NS_LOG_FUNCTION (this << tcb << dupAckCount << unAckDataCount << lastSackedBytes);
NS_UNUSED (unAckDataCount);
NS_UNUSED (lastSackedBytes);
tcb->m_cWnd = tcb->m_ssThresh;
tcb->m_cWndInfl = tcb->m_ssThresh + (dupAckCount * tcb->m_segmentSize);
}
Then I assume before calling the EnterRecovery method, the cwnd is already updated. I need to find the place that cwnd is updated.
I also updated TcpNewReno::GetSsThresh and analyzed the output. But it's also not the method I need as it doesn't cut the cwnd to half.
NOTE: I'm using seventh.cc to inspect cwnd. It always drops the cwnd to 1072. The graph I'm getting is also included. What I need to do is drop the cwnd to half of the value once a packet is dropped. Maybe the seventh.cc is not using the default tcp-l4-protocol.h. If so how I can change it?
I found the answer. The problem was with the seventh.cc. It does not use the default layer 4 TCP protocol.
To run the default layer 4 TCP protocol (TCP New Reno), I found an example, which is tcp-large-transfer.cc. It's located in ns-3.30/examples/tcp/tcp-large-transfer.cc.
I just wanted to add a quick note: the code to change cwnd is in the very snippet in your question. Specifically, it is this line:
tcb->m_cWnd = tcb->m_ssThresh;
Much of the state of a TCP Socket is actually stored in the the tcb which is a Ptr<TcpSocketState>.

How can I to transmit at least a "couple of bytes" on the local network (UEFI DXE)

I need to write driver (DXE), that can transmit "couple of bytes" from virtual machine (QEMU) to the host system (OS - Ubuntu). I've read the UEFI_Spec and Guide for developers, but I still don't understand, how to write the code and what protocol should I use (tried to use TCPv4 but can't even LocateHandleBuffer).
EFI_STATUS Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiTcp4ProtocolGuid, NULL, &HandleCount, &HandleBuffer);
I get:
EFI_UNSUPPORTED
If somebody can explain me or can show examples of the code, I'll be very grateful. Thanks.
For most network related protocols you first have to use the corresponding "Service Binding Protocol" to get a handle which contains the protocol you are looking for.
Use this steps to access the Tcp4Protocol:
gBS->LocateHandleBuffer(ByProtovol,gEfiTcp4ServiceBindingProtocolGuid, NULL, &HandleCount, &HandleBuffer);
// Loop over the HandleBuffer Array and pick the one you need
gBS->HandleProtocol(HandleBuffer[YourIndex], &gEfiTcp4ServiceBindingProtocolGuid, &Tcp4SBProtocol);
Tcp4SBProtocol->CreateChild(Tcp4SBProtocol, &Tcp4Handle);
gBS->HandleProtocol(Tcp4Handle, &gEfiTcp4ProtocolGuid, &Tcp4Protocol);
To check if a NIC is available you can use:
// This should return EFI_SUCCESS
gBS->LocateProtocol(&gEfiSimpleNetworkProtocolGuid, NULL, &SimpleNetworkProtocol);
There is a complete code sample for the HttpProtocol inside the Uefi specification (starting at page 1548), the Tcp4Protocol is not very different.

how to listen on L3 network layer?

I am creating a chat application backend and want to take into consideration the scalability.
I wanted to create a load balancer but not on the L7 layer where HTTP is located, but on the L3 layer where IP network is located to direct connections to the specific servers where I can then make TCP.
Is net.ListenIP the correct function to use to listen to the packets on the IP layer?
Is it the same as the higher Listen("tcp") for example? Is it the right method that I need to implement the load balancer?
Is there a reference to how the packet is structured so I am able get out from it the source and destination IPs to forward them?
If not tell me which function to use to listen on the L3 network layer to balance the loads to other servers.
Personally, I use gopacket in order to capture multiple network layers, and this library is very impressive.
When you're using gopacket, you are able to capture multiple network layers by specifying them, for example Ipv4, TCP, Ethernet...
For more information, see layers packet.
Then, you will be able to analyze your layers by using packet.Data(), which is a set of bytes that make up this entire packet, and then switch on the packet type to perform some actions.
For example, capturing multiple network layers on eth0 :
package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"time"
)
//Layers we want to decode
var (
ip4 layers.IPv4
eth layers.Ethernet
tcp layers.TCP
)
func main() {
//Array to store decoded layers
decodedLayers := []gopacket.LayerType{}
//Create parser
parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &tcp)
//Here we use pcap to capture packet on eth0 interface, we can also use afpacket for example, which is more efficient
handle, err := pcap.OpenLive("eth0", 65536, true, pcap.BlockForever)
if err != nil {
panic("Error opening pcap: " + err.Error())
}
datasource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
//packets will be a channel of packets
packets := datasource.Packets()
for {
select {
case packet := <-packets:
//We are decoding layers, and switching on the layer type
err := parser.DecodeLayers(packet.Data(), &decodedLayers)
for _, typ := range decodedLayers {
switch typ {
case layers.LayerTypeIPv4:
fmt.Printf("Source ip = %s - Destination ip = %s \n", ip4.SrcIP.String(), ip4.DstIP.String())
case layers.LayerTypeTCP:
//Here, we can access tcp packet properties
fmt.Println("Capture tcp traffic")
}
//etc ....
}
if len(decodedLayers) == 0 {
fmt.Println("Packet truncated")
}
//If the DecodeLayers is unable to decode the next layer type
if err != nil {
//fmt.Printf("Layer not found : %s", err)
}
}
}
}
After reading the Docs, yes this function will help you receive IP Packets.
ListenIP acts like ListenPacket for IP networks.
ListenIP is similar to ListenPacket("tcp") but for IP packets.
As for the structure of IP packets, and working with them, the net package doesn't seem to have that.
There's another package gopacket which looks like it will be able to help you read and modify packets from any layer.
In gopacket there is a Packet type, which allows working with the network layer.
Packet.NetworkLayer().LayerContent() and Packet.NetworkLayer().LayerPayload() will each return byte[] which you can interpret by the expected structure of an IP packet.
Note: Now that I've written this whole thing I have to imagine somebody out there has written a nice overlay/wrapper to make this easier. This is just the result of me Googling for 10 minutes. Maybe somebody else will answer with a better tool/method

Twain always returns TWRC_NOTDSEVENT

I use twain 2.3 (TWAINDSM.DLL) in my application with HP Scanjet 200 TWAIN Protocol 1.9.
My TWAIIN calls are:
OpenDSM: DG_CONTROL, DAT_PARENT, MSG_OPENDSM
OpenDS: DG_CONTROL, DAT_IDENTITY, MSG_OPENDS
EnableDS: DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS
ProcessDeviceEvent: DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT
and as a result of the last call I allways get TWRC_NOTDSEVENT instead of TWRC_DSEVENT.
Could please someone help with this?
Once you use DG_CONTROL / DAT_EVENT / MSG_PROCESSEVENT, all messages from the applications message loop must be sent to the data source for processing. Receiving TWRC_NOTDSEVENT means the forwarded message isn't for the source so the application should process it as normal.
Keep forwarding all messages to the source until you receive MSG_XFERREADY which means there is data to transfer. Once the transfer is finished and you have sent MSG_DISABLEDS that's when you can stop forwarding messages to the source.
Twain is a standard, and when many company implement that standard, not all of them do the same way. Along the way to support Twain, we will learn and adjust the code to support all the different implementations.
I experienced this situation before, and this is my workaround:
Instead of placing (rc == TWRC_DSEVENT) at the beginning of code (will skip the following MSG_XFERREADY processing afterward) you can move the comparison to the end after MSG_XFERREADY processing, so that MSG_XFERREADY is always checked and processed.
(rc == TWRC_DSEVENT) is only to determine if we should forward the window message or not.
I don't know your specific situation. I ran into a similar issue because I called OpenDSM with a HWND/wId which is from another process. You should call OpenDSM with the HWND of
the active window/dialog which is owned by current process.

Why does my concurrent Haskell program terminate prematurely?

I have a UDP server that reflects every ping message it receives (this works well I think). I the client side I would then like to do two things:
make sure that I fired off N (e.g. 10000) messages, and
count the number of correctly received responses.
It seems that either because of the nature of UDP or because of the forkIO thing, my client code below ends prematurely/does not do any counting at all.
Also I am very surprised to see that the function tryOnePing returns 250 times the Int 4. Why could this be?
main = withSocketsDo $ do
s <- socket AF_INET Datagram defaultProtocol
hostAddr <- inet_addr host
thread <- forkIO $ receiveMessages s
-- is there any better way to eg to run that in parallel and make sure
-- that sending/receiving are asynchronous?
-- forM_ [0 .. 10000] $ \i -> do
-- sendTo s "ping" (SockAddrInet port hostAddr)
-- actually this would be preferred since I can discard the Int 4 that
-- it returns but forM or forM_ are out of scope here?
let tryOnePing i = sendTo s "ping" (SockAddrInet port hostAddr)
pings <- mapM tryOnePing [0 .. 1000]
let c = length $ filter (\x -> x==4) pings
-- killThread thread
-- took that out to make sure the function receiveMessages does not
-- end prematurely. still seems that it does
sClose s
print c
-- return()
receiveMessages :: Socket -> IO ()
receiveMessages socket = forever $ do
-- also tried here forM etc. instead of forever but no joy
let recOnePing i = recv socket 1024
msg <- mapM recOnePing [0 .. 1000]
let r = length $ filter (\x -> x=="PING") msg
print r
print "END"
The main problem here is that when your main thread finishes, all other threads gets killed automatically. You have to get the main thread to wait for the receiveMessages thread, or it will in all likelyhood simply finish before any responses have been received. One simple way of doing this is to use an MVar.
An MVar is a synchronized cell that can either be empty or hold exactly one value. The current thread will block if it tries to take from an empty MVar or insert into a full one.
In this case, we don't care about the value itself, so we'll just store a () in it.
We'll start with the MVar empty. Then the main thread will fork off the receiver thread, send all the packets, and try to take the value from the MVar.
import Control.Concurrent.MVar
main = withSocketsDo $ do
-- prepare socket, same as before
done <- newEmptyMVar
-- we need to pass the MVar to the receiver thread so that
-- it can use it to signal us when it's done
forkIO $ receiveMessages sock done
-- send pings, same as before
takeMVar done -- blocks until receiver thread is done
In the receiver thread, we will receive all the messages and then put a () in the MVar to signal that we're done receiving.
receiveMessages socket done = do
-- receive messages, same as before
putMVar done () -- allows the main thread to be unblocked
This solves the main issue, and the program runs fine on my Ubuntu laptop, but there are a couple more things you want to take care of.
sendTo does not guarantee that the whole string will be sent. You'll have to check the return value to see how much was sent, and retry if not all of it was sent. This can happen even for a short message like "ping" if the send buffer is full.
recv requires a connected socket. You'll want to use recvFrom instead. (Although it still works on my PC for some unknown reason).
Printing to standard output is not synchronized, so you might want to alter this so that the MVar will be used to communicate the number of received packets instead of just (). That way, you can do all the output from the main thread. Alternatively, use another MVar as a mutex to control access to standard output.
Finally, I recommend reading the documentation of Network.Socket, Control.Concurrent and Control.Concurrent.MVar carefully. Most of my answer is stitched together from information found there.

Resources