Set a TCP port > 65535 with pcap and dnet - sockets

I have been injecting packets on the network and watching the effects via wireshark. I am able to correctly set and change tcp ports and set the source and destination. However, I am now having an issue. One of the things I need to do is to set a source port from port 66,000. Every time I try it just puts the number to 1163 in wireshark which is because it is supposed to be a short integer. Does anyone know how to make it accept the big number. I know the big endian and htonl should work so I tried that as well but that didn't solve the issue.
Here is the code I am using
void extract(u_char *user, struct pcap_pkthdr *h, u_char *pack ) {
struct eth_hdr *ethhdr;
struct ip_hdr *iphdr;
struct tcp_hdr *tcphdr;
ethhdr = (struct eth_hdr *)pack;
iphdr = (struct ip_hdr *)(pack + ETH_HDR_LEN);
tcphdr = (struct tcp_hdr *) (pack + ETH_HDR_LEN + (4*iphdr->ip_hl));
//Set the ports
tcphdr->th_sport = htons(66666);
tcphdr->th_dport = htons(atoi(destString));

The port number is 16 bit. With 16 bit you can get only up to 65535. No way around it. See also the TCP header at http://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_segment_structure.

Related

Unicast/multicast packet using xdp/tc eBPF

I am trying to design a load balancer using ebpf. I want to transmit the incoming packet to different destinations (devices connected in the same network). Although I have used the clone_bpf_redirect() helper function to redirect the packet to real/ virtual interfaces and it's working fine, now I want to broadcast/unicast the packet to other devices connected in the same network.
XDP does not support it, as far as I know. Therefore, using tc bpf hook. Is there any helper function or which action should I use? Can anyone please guide me on how can I do this?
**eBpf load divider**: 192.168.98.178 (load divider)
**Receiver 1**: 192.168.98.131
**Receiver 2**: 192.168.98.138
iph->daddr = htonl(3232260739); //Dest: 192.168.98.131
iph->check = 0;
iph->check = checksum((unsigned short *)iph, sizeof(struct iphdr));
// Update upd packet checksum of
sum = old_daddr + (~ntohs(*(unsigned short *)&iph->daddr) & 0xffff);
sum += ntohs(udp->check);
sum = (sum & 0xffff) + (sum>>16);
udp->check = htons(sum + (sum>>16) - 1);
// clone the packet and redirect to infdex
bpf_clone_redirect(skb, skb->ifindex, 0);
//clone the packet and redirect to infdex (virtual interface 2)
bpf_clone_redirect(skb, skb->ifindex + 2, 0);
//clone the packet and redirect to infdex (virtual interface 4)
bpf_clone_redirect(skb, skb->ifindex + 4, 0);
return TC_ACT_OK;
// Or
// return TC_ACT_REDIRECT;
sudo tc filter add dev ens33 ingress bpf da obj bpf_loadbalancer.o sec ingress
after this, I am getting the 1 packet to 3 different ifindex but I want to get the same packet to other devices connected into the network. How can I redirect the packet out of the device, not the interfaces?

Reading MLDv2 queries using an IPv6 socket

I have mrd6 installed on my raspberry pi. It registers with a local interface (tun0) and periodically transmits MLDv2 queries over it.
According to [RFC3810], MLDv2 message types are a subset of ICMPv6 messages, and are identified in IPv6 packets by a preceding Next Header value of 58 (0x3a). They are sent with a link-local IPv6 Source Address, an IPv6 Hop Limit of 1, and an IPv6 Router Alert option [RFC2711] in a Hop-by-Hop Options header.
I can confirm that I'm seeing these packets periodically over tun0:
pi#machine:~ $ sudo tcpdump -i tun0 ip6 -vv -XX
01:22:52.125915 IP6 (flowlabel 0x71df6, hlim 1, next-header Options (0)
payload length: 36)
fe80::69bf:be2d:e087:9921 > ip6-allnodes: HBH (rtalert: 0x0000) (padn)
[icmp6 sum ok] ICMP6, multicast listener query v2 [max resp delay=10000]
[gaddr :: robustness=2 qqi=125]
0x0000: 6007 1df6 0024 0001 fe80 0000 0000 0000 `....$..........
0x0010: 69bf be2d e087 9921 ff02 0000 0000 0000 i..-...!........
0x0020: 0000 0000 0000 0001 3a00 0502 0000 0100 ........:.......
0x0030: 8200 b500 2710 0000 0000 0000 0000 0000 ....'...........
0x0040: 0000 0000 0000 0000 027d 0000 .........}..
I have a socket set up in my application on tun0 as follows, since I expect these to be ICMP packets:
int fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); // ICMP
// ... bind this socket to tun0
int interfaceIndex = // tun0 interface Index
int mcastTTL = 10;
int loopBack = 1;
if (setsockopt(listener->socket,
IPPROTO_IPV6,
IPV6_MULTICAST_IF,
&interfaceIndex,
sizeof(interfaceIndex))
< 0) {
perror("setsockopt:: IPV6_MULTICAST_IF:: ");
}
if (setsockopt(listener->socket,
IPPROTO_IPV6,
IPV6_MULTICAST_LOOP,
&loopBack,
sizeof(loopBack))
< 0) {
perror("setsockopt:: IPV6_MULTICAST_LOOP:: ");
}
if (setsockopt(listener->socket,
IPPROTO_IPV6,
IPV6_MULTICAST_HOPS,
&mcastTTL,
sizeof(mcastTTL))
< 0) {
perror("setsockopt:: IPV6_MULTICAST_HOPS:: ");
}
struct ipv6_mreq mreq6 = {{{{0}}}};
MEMCOPY(&mreq6.ipv6mr_multiaddr.s6_addr, sourceAddress, 16);
mreq6.ipv6mr_interface = interfaceIndex;
if (setsockopt(listener->socket,
IPPROTO_IPV6,
IPV6_JOIN_GROUP,
&mreq6,
sizeof(mreq6))
< 0) {
perror("setsockopt:: IPV6_JOIN_GROUP:: ");
}
Setting up the socket this way, I can receive ICMP echo requests, replies to my own address, and multicasts sent using the link-local multicast address. However, I don't see any MLDv2 queries.
Here's my receive loop:
uint8_t received[1000] = { 0 };
struct sockaddr_storage peerAddress = { 0 };
socklen_t addressLength = sizeof(peerAddress);
socklen_t addressLength = sizeof(peerAddress);
int receivedLength = recvfrom(sockfd,
received,
sizeof(received),
0,
(struct sockaddr *)&peerAddress,
&addressLength);
if (receivedLength > 0) {
// Never get here for MLDv2 queries.
}
Researching this a bit further, I discovered the IPV6_ROUTER_ALERT socket option, which the man page describes as follows:
IPV6_ROUTER_ALERT
Pass forwarded packets containing a router alert hop-by-hop option to this socket.
Only allowed for SOCK_RAW sockets. The tapped packets are not forwarded by the
kernel, it is the user's responsibility to send them out again. Argument is a
pointer to an integer. A positive integer indicates a router alert option value
to intercept. Packets carrying a router alert option with a value field
containing this integer will be delivered to the socket. A negative integer
disables delivery of packets with router alert options to this socket.
So I figured I was missing this option, and tried setting it as follows. [RFC2710] 0 means Multicast Listener Discovery message.
int routerAlertOption = 0;
if (setsockopt(listener->socket,
IPPROTO_IPV6,
IPV6_ROUTER_ALERT,
&routerAlertOption,
sizeof(routerAlertOption))
< 0) {
perror("setsockopt:: IPV6_ROUTER_ALERT:: ");
}
However, this gives me the ENOPROTOOPT error (errno 92). Some more Googling (http://www.atm.tut.fi/list-archive/usagi-users-2005/msg00317.html) led me to the fact that you can't set the IPV6_ROUTER_ALERT option with the IPPROTO_ICMPV6 protocol. It needs a socket defined using the IPPROTO_RAW protocol.
However, defining my socket as:
int fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
means I'm not able to receive any ICMP packets in my recvfrom anymore.
TL;DR: How do I read MLDv2 queries using an IPv6 socket?
edit (answer):
It appears conventional implementations of Linux will drop MLDv2 packets when passing them to an ICMPV6 socket. Why this is, I'm not sure. (Could be because of the next-header option.)
I followed the accepted answer below and went with an approach of reading raw packets on the tun0 interface. I followed the ping6_ll.c example here: http://www.pdbuchan.com/rawsock/rawsock.html.
It uses a socket with (SOCK_RAW, ETH_P_ALL). You can also set some SOL_PACKET options to filter on specific multicast rules on your interface.
From a quick look at RFCs things aren't looking good. Per RFC4443 (ICMPv6) 2.4:
2.4. Message Processing Rules
Implementations MUST observe the following rules when processing
ICMPv6 messages (from [RFC-1122]):
(b) If an ICMPv6 informational message of unknown type is received,
it MUST be silently discarded.
According to MLDv2 spec it makes use of types 130, 143, perhaps something else (not seeing more diagrams in the RFC), while valid ICMPv6 types are 1, 2, 3, 4, 101, 107, 127, 128, 129, 200, 201, 255.
It looks like the implementation (kernel) must drop MLDv2 packets if they are to be passed to an ICMPv6 socket. Personally I don't see much sense in making MLDv2 look like ICMPv6 if conventional implementations will drop the packet anyways, but I didn't see anything that contradicts this claim.
You can surely go deeper and use a raw socket, especially given that your stack doesn't recognize MLDv2 (perhaps there's a kernel patch to fix that?). But you'll have to parse IP and ICMP headers on your own then.

How can I do a tcp syn port scan with golang?

I'm trying to write a tcp syn port scanner with golang, I found a solution in C version here: http://www.binarytides.com/tcp-syn-portscan-in-c-with-linux-sockets/
I'd like to implement it in go, how can I send a tcp header like this in golang:
//TCP Header
tcph->source = htons ( source_port );
tcph->dest = htons (80);
tcph->seq = htonl(1105024978);
tcph->ack_seq = 0;
tcph->doff = sizeof(struct tcphdr) / 4; //Size of tcp header
tcph->fin=0;
tcph->syn=1;
tcph->rst=0;
tcph->psh=0;
tcph->ack=0;
tcph->urg=0;
tcph->window = htons ( 14600 ); // maximum allowed window size
tcph->check = 0; //if you set a checksum to zero, your kernel's IP stack should fill in the correct checksum during transmission
tcph->urg_ptr = 0;
Do I have to use syscall or cgo? I'm really appreciated if someone could help me out.
You're going to want to use syscall. However the syscall package is not necessarily portable across different Operating Systems so if that matters to you then you'll have to write per os versions and use the file_os.go naming scheme to hold the os specific code.

Car OBDII WLAN protocol

I am currently searching for the specification of the WLAN protocoll to get OBDII data. There are some ELM327 similar adapter on the market which enables iPhone to connect to a OBDII interface with WLAN. This because Bluetooth serial port is scrambled because of the accessories interface. Other programs like Torque for android can also use this communication protocol. However I did not find the specs for creating a network client.
Any help is welcomed,
Thanks
Ok, after some more research, I found two sources:
Michael Gile has an open source library for iOS devices, meant for communicating with OBDII WiFi as well as Bluetooth devices.
PLX devices (creators of the KiWi) have a description how to communicate with the KiWi. The description is too large to include here, but it boils down to:
Connect using WiFi (sockets)
Wait until the device returns >
Issue command and await response
Requesting information can be done by sending a command in this format (ASCII characters):
MM PP\r
where MM is the test mode, PP is the PID, and \r is a carriage return (hex: 0x0d). All whitespace characters are ignored by the Kiwi. *Test modes 03 and 04 do not require a PID value.
The 'test modes' that are spoken of, are the ten diagnostic modes as defined in the SAE J1979 standard:
Test mode Description
01 Show current data
02 Show freeze frame data
03 Show diagnostic trouble codes
04 Clear trouble codes and stored values
05 Test results, oxygen sensors
06 Test results, non-continuously monitored
07 Show 'pending' trouble codes
08 Special control mode
09 Request vehicle information
0A Request permanent trouble codes
The PID values are the codes for the sensors in the car. A (non-exhaustive)list of possible PID values is on Wikipedia.
here what i do in C and socket:
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
char *ip = "192.168.0.10";
char str [128];
int i;
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(35000);
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
printf ("reading...\n");
strcpy (str,"AT Z\x0d");
sleep(2);
write (sockfd, str, strlen (str));
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
printf ("received: ");
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
printf ("\r\ntype: ");
fgets (str, sizeof (str), stdin);
i = strlen (str);
if (str [i-1] == 0x0a)
str [i-1] = 0;
strcat (str, "\x0d");
write (sockfd, str, strlen (str));
printf ("\r\n");
}
type 1 or 2 enter, you should see the prompt: ELM327
then after that, type whatever you want, for ex.: AT RV (will show voltage)
then use this pdf for all code:
https://www.obd-2.de/carcode/dl/ELM327DS.pdf
Have a look at ELM327 datasheet
Wifi dongles transparently bind the ELM327 RS232 port to a TCP server.
There's not really a WIFI protocol. You can use the ELM327 protocol via a raw TCP connection instead.
You can sent AT commands and OBD2 commands known as PID's with the telnet command:
telnet 192.168.0.1 35000
On succesful connection you can try to send:
AT Z
and the server should respond with "ELM327" and a version number.

iPhone Unable to receive data using UDP recvfrom

I am writing an application which is continuously sending and receiving data. My initial send/receive is running successfully but when I am expecting data of size 512 bytes in the recvfrom I get its return value as -1 which is "Resource temporarily unavailable." and errno is set to EAGAIN. If I use a blocking call i.e. without Timeout the application just hangs in recvfrom. Is there any max limit on recvfrom on iPhone? Below is the function which receives data from the server. I am unable to figure out what can be going wrong.
{ struct timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 100000;
setsockopt (mSock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv);
NSLog(#"Receiving.. sock:%d",mSock);
recvBuff = (unsigned char *)malloc(1024);
if(recvBuff == NULL)
NSLog(#"Cannot allocate memory to recvBuff");
fromlen = sizeof(struct sockaddr_in);
n = recvfrom(mSock,recvBuff,1024,0,(struct sockaddr *)&from, &fromlen);
if (n == -1) {
[self error:#"Recv From"];
return;
}
else
{
NSLog(#"Recv Addr: %s Recv Port: %d",inet_ntoa(from.sin_addr), ntohs(from.sin_port));
strIPAddr = [[NSString alloc] initWithFormat:#"%s",inet_ntoa(from.sin_addr)];
portNumber = ntohs(from.sin_port);
lIPAddr = [KDefine StrIpToLong:strIPAddr];
write(1,recvBuff,n);
bcopy(recvBuff, data, n);
actualRecvBytes = n;
free(recvBuff);
}
}
Read the manpage:
If no messages are available at the socket, the receive call waits for a message to arrive, unless the socket is nonblocking (see fcntl(2)) in which case the value -1 is returned and the external variable errno set to EAGAIN.
I was writing a UDP application and think I came across a similar issue. Peter Hosey is correct in stating that the given result of recvfrom means that there is no data to be read; but you were wondering, how can there be no data?
If you are sending several UDP datagrams at a time from some host to your iphone, some of those datagrams may be discarded because the receive buffer size (on the iphone) is not large enough to accommodate that much data at once.
The robust way to fix the problem is to implement a feature that allows your application to request a retransmission of missing datagrams. A not as robust solution (that doesn't solve all the issues that the robust solution does) is to simply increase the receive buffer size using setsockopt(2).
The buffer size adjustment can be done as follows:
int rcvbuf_size = 128 * 1024; // That's 128Kb of buffer space.
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
&rcvbuf_size, sizeof(rcvbuf_size)) == -1) {
// put your error handling here...
}
You may have to play around with buffer size to find what's optimal for your application.
For me it was a casting issue. Essentially a was assigning the returned value to an int instead of size_t
int rtn = recvfrom(sockfd,... // wrong
instead of:
size_t rtn = recvfrom(sockfd,...// correct