How to change the don't fragment (DF) flag for UDP packet in Erlang? - erlang

In Erlang, it is very simple to send UDP packet, that is to use gen_udp:open() to create a socket, then use gen_udp:send() to send out the data.
However, by default, the Linux TCP/IP stack will set the don't fragment (DF)flag in IP header if the size of IP packet doesn't exceed the MTU size. If the size exceeds the MTU size, the UDP packet will be fragmented.
Is there some way to not set DF flag for UDP packet only?
I know in C language, the following code could be used to clear the DF flag. But i couldn't find a way in Erlang.
int optval=0;
if(-1 == setsockopt(sockfd,IPPROTO_IP,IP_MTU_DISCOVER,&optval,sizeof(optval))) {
printf("Error: setsockopt %d\n",errno);
exit(1);
}
Thanks

i found the solution after i posted this question :-(...:-)...
The solution is to set socket raw option by using inet:setopts() like what is done in C language, but the difference is that you need to know the definition of IPPROTO_IP and IP_MTU_DISCOVER.
The value of IPPROTO_IP is 0, defined in netinet/in.h
The value of IP_MTU_DISCOVER is 10, defined in linux/in.h
Below is example.
inet:setopts(Socket,[{raw,0,10,<<0:32/native>>}]).
I have tested it using small program, it is working.
You can find detail help for inet:setopts on erlang man page: http://www.erlang.org/doc/man/inet.html
Thanks.

Related

Wireshark display filter for Protocol != 802.11

I've set Wireshark's capture filter set to capture only packets from the MAC address of interest, but the result is dominated by zillions of packets whose Protocol is "802.11". I want to view all of the packets that are NOT 802.11, e.g. ARP, DCHP, DNS, TCP, etc.
For example, in the following, I'd like to hide all of the 802.11 packets and show the DHCP packets (and any others that are NOT 802.11):
I tried "wlan.fc.type != 0", but clearly that's not correct. What's the magic keyword for such a filter?
update
#ChristopherMaynard's comment is close, and I now understand that a simple filter of:
ip
is almost what I want, but it fails to display packets of type ARP, EAPOL, LLC, MDP and perhaps others.
[Converted comment to answer and added an alternate solution while I'm at it.]
If you just want data frames but those without un-dissected data (which would still show 802.11 in the Protocol column), then you could try wlan.fc.type == 2 and !data. Or you could try !(frame.protocols == "radiotap:wlan_radio:wlan:data" or frame.protocols == "radiotap:wlan_radio:wlan").
Another alternative is to download the filtcols.lua script written by Chuck Craft, save it to your plugins directory (Wireshark: Help -> About Wireshark -> Folders -> Personal Lua Plugins), the [re]start Wireshark. Now you can apply a display filter such as wlan and !(filtcols.protocol == "802.11").

How to handle buffer overflow in ndis driver

How can I handle buffer overflow in ndis driver. Can anybody tell some buffer overflow scenarios or some use cases of buffer overflow conditions.
For NDIS miniport drivers
If you receive a packet that is larger than the MTU, discard it. Do not indicate the packet up to NDIS (i.e., do not pass the packet to NdisMIndicateReceiveNetBufferLists). If possible, increment the ifInErrors statistical counter.
The above rule is not affected by the NDIS_PACKET_TYPE_PROMISCUOUS flag; do not indicate excessively-large packets even when in promiscuous mode. However, you should indicate excessively-small (aka "runt") packets when in promiscuous mode, if your hardware permits it.
If you are asked to transmit a packet that is larger than the MTU, do not attempt to transmit it. Assign NET_BUFFER_LIST::Status = NDIS_STATUS_INVALID_LENGTH and return the NBL back to NDIS with NdisMSendNetBufferListsComplete. (I wouldn't expect you to ever see such a packet; it would be a bug for NDIS to attempt to send you such a packet.)
For NDIS protocol drivers
If you receive a packet that is larger than the MTU, you are free to discard it.
Never attempt to send a packet that is larger than the MTU.
For NDIS filter drivers
If a filter receives a packet that is larger than the MTU (FilterReceiveNetBufferLists), the filter may immediately discard the packet (NdisFReturnNetBufferLists if the receive indication is not made with NDIS_RECEIVE_FLAGS_RESOURCES, or just returning immediately if the resources flag is set).
If a filter is asked to send a packet that is larger than the MTU (FilterSendNetBufferLists), the filter may assign NET_BUFFER_LIST::Status = NDIS_STATUS_INVALID_LENGTH and return the packet immediately (NdisFSendNetBufferListsComplete).
Filters are not obligated to validate the size of every packet that passes through them. However, your filter should validate the size of any packets where a malformed packet would otherwise cause your filter to trigger a buffer overflow. For example, if your filter copies all ARP replies into a pre-allocated buffer, first validate that the ARP reply isn't too large to fit into the buffer. (This is not strictly necessary, since the miniport "shouldn't" give you an excessively-large packet. However, you are on the network datapath, which means you're handling untrusted data being processed by a potentially-buggy miniport. A little extra defense-in-depth is a good idea.)
Filters must not originate packets that are larger than the MTU (on either the send or receive paths).

Finding the direction of packets while sniffing

I want to have a list of source IP addresses of an interface outbound traffic. How could I find the direction of a packet whether it's inbound or outbound reading traffic using libpcap? I don't know the subnet information of either side. And there are clients/servers on both sides, so I can't rely on port number ranges to filter traffic.
Why there is no information in libpcap packet header about direction, or filter option like inbound in pcap-filter?
Netsniff-NG, while not relying on libpcap, supports Linux kernel packet type extensions.
They're documented
here
One of the packet types is outgoing and commented as "outgoing of any type".
The following example will capture all packets leaving your interface.
$ netsniff-ng --in eth0 --out outgoing.pcap --type outgoing
Using this you can utilize other command-line tools to read the PCAP file and pull out all the source
addresses. Maybe something *nix-ey like this:
$ tcpdump -nnr outgoing.pcap | cut -d " " -f3 | cut -d . -f1-4
Note: I haven't tried this on a router.
you could use "ether src" or "ether dst" to filter packet direction. This require you to know the mac address of the interface.
You can select a direction that packets will be capture calling pcap_setdirection() before pcap_loop().
For example, to capture incoming packets only you need to write:
handle = pcap_open_live("eth0", 65535, 1, 0, errbuf);
pcap_setdirection(handle, PCAP_D_IN);
pcap_loop(handle, -1, process_packet, NULL);
Possible directions are: PCAP_D_IN, PCAP_D_OUT, PCAP_D_INOUT.
See tcpdump.org/manpages/pcap_setdirection.3pcap.txt
The PCAP file format does not contain a field that holds the interface used during the capture. With that said, the newer PCAP-NG file format, currently used by Wireshark & Tshark, supports it along with packet direction.
Existing pcap-ng features:
packet dropped count
annotations (comments)
local IP address
interface & direction
hostname <-> IP address database
PcapNg
It sounds like you're capturing from a router or firewall so something like the following
would not work.
ip src 192.168.1.1
Capturing the traffic into flows may be an option but it still will not provide you with direction information. Though, you will be able to determine the source and destinations address easily. If you have an existing pcap you can convert it to the ARGUS format:
argus -r capture.pcap -w capture.argus
ra -nnr capture.argus
Other tools, some w/ examples, that can easily obtain end-points/hosts are:
ntop -f capture.pcap
tcpprof -nr capture.pcap
Wireshark Endpoints
flow-tools
You'll have to parse out the information you want, but I don't think that's too much trouble. I recommend taking a look at PCAP-NG if you can't work with this.

Is transmitted bytes event exist in Linux kernel?

I need to write a rate limiter, that will perform some stuff each time X bytes were transmitted.
The straightforward is to check the length of each transmitted packet, but I think it will be to slow for me.
Is there a way to use some kind of network event, that will be triggered by transmitted packets/bytes?
I think you may look at netfilter.
Using its (kernel level) api, you can have your custom code triggered by network events, modify received messages before passing it to application, and so on.
http://www.netfilter.org/
It's protocol dependent, actually. But for TCP, you can setsockopt the SO_RCVLOWAT option to define the minimum number of bytes (watermark) to permit the read operation.
If you need to enforce the maximum size too, adjust the receive buffer size using SO_RCVBUF.

How to determine total data upload+download in TCP/IP

I need to calculate total data transfer while transferring a fixed size data from client to server in TCP/IP. It includes connecting to the server, sending request,header, receiving response, receiving data etc.
More precisely, how to get total data transfer while using POST and GET method?
Is there any formula for that? Even a theoretical one will do fine (not considering packet loss or connection retries etc)
FYI I tried RFC2616 and RFC1180. But those are going over my head.
Any suggestion?
Thanks in advance.
You can't know the total transfer size in advance, even ignoring retransmits. There are several things that will stop you:
TCP options are negotiated between the hosts when the connection is established. Some options (e.g., timestamp) add additional data to the TCP header
"total data transfer size" is not clear. Ethernet, for example, adds quite a few more bits on top of whatever IP used. 802.11 (wireless) will add even more. So do HDLC or PPP going over a T1. Don't even think about frame relay. Some links may use compression (which will reduce the total size). The total size depends on where you measure it, even for a single packet.
Assuming you're just interested in the total octet size at layer 2, and you know the TCP options that will be negotiated in advance, you still can't know the path MTU. Which may change, even while the connection is in progress. Or if you're not doing path MTU discovery (which would be wierd), then the packet may get fragmented somewhere, and the remote end will see a different amount of data transfer than you.
I'm not sure why you need to know this, but I suggest that:
If you just want an estimate, watch a typical connection in Wireshark. Calculate the percent overhead (vs. the size of data you gave to TCP, and received from TCP). Use that number to estimate: it will be close enough, except in pathological situations.
If you need to know for sure how much data your end saw transmitted and received, use libpcap to capture the packet stream and check.
i'd say on average that request and response have about 8 lines of headers each and about 30 chars per line. Then allow for the size increase of converting any uploaded binary to Base64.
You didn't say if you also want to count TCP packet headers, in which case you could assume an MTU of about 1500 so add 16 bytes (tcp header) per 1500 data bytes
Finally, you could always setup a packet sniffer and count actual bytes for a sample of data.
oh yeah, and you may need to allow for deflate/gzip encoding as well.

Resources