Hops tracing ttl reciveform on ios - ios

I'm trying to implement simple traceroute for the iOS. Everything seems to work fine, except that somehow when I run my application on simulator or on the device it finds only a few (6-7) first routers on the way when the CLI traceroute finds all 14 routers.
const char *c = "www.gmail.com";
struct hostent *host_entry = gethostbyname(c);
char *ip_addr;
ip_addr = inet_ntoa(*((struct in_addr *)host_entry->h_addr_list[0]));
struct sockaddr_in destination, fromAddr;
int recv_sock;
int send_sock;
// Creting Sockets///
if ((recv_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) <
0) // using UDP socket.
{
NSLog(#"Could not cretae recv_sock.\n");
}
if ((send_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
NSLog(#"Could not cretae send_sock.\n");
}
memset(&destination, 0, sizeof(destination));
destination.sin_family = AF_INET;
destination.sin_addr.s_addr = inet_addr(ip_addr);
destination.sin_port = htons(80);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10000;
setsockopt(recv_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
sizeof(struct timeval));
char *cmsg = "GET / HTTP/1.1\r\n\r\n";
int max_ttl = 20;
int num_attempts = 5;
socklen_t n = sizeof(fromAddr);
char buf[100];
for (int ttl = 1; ttl <= max_ttl; ttl++) {
memset(&fromAddr, 0, sizeof(fromAddr));
if (setsockopt(send_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
NSLog(#"error in setsockopt\n");
for (int try = 0; try < num_attempts; try ++) {
if (sendto(send_sock, cmsg, sizeof(cmsg), 0,
(struct sockaddr *)&destination,
sizeof(destination)) != sizeof(cmsg))
NSLog(#"error in send to...\n#");
int res = 0;
if ((res = recvfrom(recv_sock, buf, 100, 0, (struct sockaddr *)&fromAddr,
&n)) < 0) {
NSLog(#"an error: %s; recvfrom returned %d\n", strerror(errno), res);
} else {
char display[16] = {0};
inet_ntop(AF_INET, &fromAddr.sin_addr.s_addr, display, sizeof(display));
NSLog(#"Received packet from%s for TTL=%d\n", display, ttl);
break;
}
}
}
I have tried to bind the send socket but have same results and I can't use Sock_raw on iOS. I tried to run it on my mac and got same results. The error I get is "Resource temporarily unavailable;" for the recvfrom(). Why is that? How can I fix it?

The EAGAIN error ( producing "Resource temporarily unavailable;" string) could be raised by the timeout of the receiving socket.
Since you set just 10000 microseconds as read timeout (that's really short IMHO) with this line...
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10000;
setsockopt(recv_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
... it's possibile that the longer the way (i mean the number of router you have to pass through), the more chance you have to incour in this situation.
Try to raise timeout value and let us know if it got better.
EDIT
I tried the source code under linux and i noticed two kind of problems.
As mentioned above: Timeouts
Problem with the 80 port
I just raised the timeout and used a port different than 80 (in my case i sent udp message to 40000 port) and i got back all the hops just like traceroute command.
I'm not sure why this behaviour occour. Maybe some kind of "possible malicious packet alarm" gets triggered by the router that discards it
FURTHER EDIT
Look at this link: man traceroute
In the List Of Available Methods section you can find many ways to achieve what you need. Your method is similar to the default one, stating:
Probe packets are udp datagrams with so-called "unlikely" destination ports. The "unlikely" port of the first probe is 33434, then for each next probe it is incremented by one. Since the ports are expected to be unused, the destination host normally returns "icmp unreach port" as a final response. (Nobody knows what happens when some application listens for such ports, though).
So, if you need to full emulate the behaviour of the common Linux traceroute you have to increase by 1 the destination port, everytime the TTL increase (or everytime you can't get a response IMHO)
MAYBE, sometimes your command doesn't work on certain ports because the router is listening to the latter (as suggested by Linux manual and underlined in bold by me).

Related

How to select which network interface to use in a ESP32

I'm currently using a Esp32 which presents, in addition to wifi, an ethernet interface.
I'm using the esp-idf v3.3 with FreeRTOS.
To use it I included the "esp_eth.h" library (https://docs.espressif.com/projects/esp-idf/en/release-v3.1/api-reference/ethernet/esp_eth.html#api-reference-phy-lan8720).
I'd like to use both Wifi and ethernet interfaces basing on what I want to do but selecting which one to use, is there a way?
The practical use is to receive a command through the ethernet interface (for example a site to ping), ping the server through the wifi interface and answer back to the ethernet interface the ping result.
How can I select which interface to use (i dont want that the ping is made through the ethernet or that the response go through the wifi).
#edit: i found the method netif_set_default(struct netif * netif), but i dont know if it is the best way to select the interface to use for the specific action(i should swap from one interface to another)
Just get the IP of the Ethernet interface, then bind a socket to that IP address.
struct in_addr iaddr = {0};
#if USE_ANY_IF
// Bind the socket to any address
iaddr.s_addr = htonl(INADDR_ANY);
#else
// bind only to the Ethernet interface
tcpip_adapter_ip_info_t ip_info = {0};
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip_info);
inet_addr_from_ip4addr(&iaddr, &ip_info.ip);
#endif
Then use it to bind a socket, for example:
static int create_multicast_ipv4_socket(struct in_addr bind_iaddr)
{
struct sockaddr_in saddr = {0};
int sock = -1;
int err = 0;
char addrbuf[32] = {0};
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock < 0)
{
ESP_LOGE(V4TAG, "Failed to create socket. Error %d", errno);
return -1;
}
saddr.sin_addr.s_addr = bind_iaddr.s_addr; // what interface IP to bind to. Can be htonl(INADDR_ANY)
saddr.sin_family = PF_INET;
saddr.sin_port = htons(UDP_PORT);
inet_ntoa_r(saddr.sin_addr.s_addr, addrbuf, sizeof(addrbuf) - 1);
ESP_LOGI(TAG, "Binding to interface %s...", addrbuf);
err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
if (err < 0)
{
ESP_LOGE(V4TAG, "Failed to bind socket. Error %d", errno);
goto err;
}
// Assign multicast TTL (set separately from normal interface TTL)
uint8_t ttl = MULTICAST_TTL;
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(uint8_t));
if (err < 0)
{
ESP_LOGE(V4TAG, "Failed to set IP_MULTICAST_TTL. Error %d", errno);
goto err;
}
// All set, socket is configured for sending
return sock;
err:
close(sock);
return -1;
}

How do I initialize LwIP to use MQTT library

I've looked and followed documentation from LwIP 2.0.2. My project contains the MQTT library supplied in the LwIP 2.0.2. I also found some help at https://dzone.com/articles/mqtt-with-lwip-and-the-nxp-frdm-k64f. I'm unable to get a connection, I've used free public MQTT broker but no hope in connection. I can ping my device. Am I doing something wrong?
static void mqtt_test(mqtt_client_t *mqtt_client)
if (mqtt_client_is_connected(&mqtt_client) == 1)
{
example_subscribe(&mqtt_client, NULL);
} else {
mqtt_do_connect(&mqtt_client);
}
}
when I call this method it always enters mqtt_do_connect() never connecting. Here is mqtt_do_connect
static void mqtt_do_connect(mqtt_client_t *mqtt_client)
{
ip4_addr_t broker_ipaddr;
struct mqtt_connect_client_info_t ci;
err_t err;
if (ipaddr_aton("52.58.177.181", &broker_ipaddr))
{
err = ERR_OK;
}
/* Setup an empty client info structure */
memset( & ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "test";
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(mqtt_client, & broker_ipaddr, 1883, mqtt_connection_cb, 0, & ci);
/* For now just print the result code if something goes wrong */
if (err != ERR_OK) {
printf("mqtt_connect return %d\n", err);
}
}
I've also noticed in the method mqtt_client_connect in mqtt.c that this exists:
/* Any local address, pick random local port number */
err = tcp_bind(client->conn, IP_ADDR_ANY, 0);
why is this needed? If I replace IP_ADDR_ANY to my local address of the static IP of the device it runs through without throwing a error but no callback mqtt_connection_cb is then called.
I've also initialized the TCP/IP stack as mentioned with static IP. I'm using NO_SYS as 1 but will move it over to FreeRTOS but baby steps first.
I haven't found much support on MQTT in LwIP implementation, am I missing something obvious, any help will be appreciated.
I've used MQTTfx to run a test or two on the broker with good response but nothing from my embedded device (Atmel SAME54).
I've found the solution. I ran my TCP setup in a FreeRTOS thread and opened a socket
static void mqtt_start(void *p)
{
struct sockaddr_in address;
int s_create, new_socket;
int addrlen = sizeof(address);
int opt = 1;
int socket_check;
sys_sem_t sem;
err_t err_sem;
err_sem = sys_sem_new(&sem, 0); /* Create a new semaphore. */
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(&sem); /* Block until the lwIP stack is initialized. */
sys_sem_free(&sem); /* Free the semaphore. */
/*Create a socket*/
s_create = socket(AF_INET, 1, 0);
setsockopt(s_create, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(IPADDR_ANY);
address.sin_port = htons(HTTP_PORT);
/* bind the connection to port */
socket_check = bind(s_create, (struct sockaddr *)&address, sizeof(address));
if (socket_check < 0) {
LWIP_DEBUGF(LWIP_DBG_ON, ("Bind error=%d\n", socket_check));
goto socket_close;
}
/* tell the connection to listen for incoming connection requests */
listen(s_create, 3);
mqtt_connect(&mqtt_client);
for (;;) {
new_socket = accept(s_create, (struct sockaddr *)&address, (socklen_t *)&addrlen);
socket_close:
close(new_socket);
}
}
I also had a problem with my initialization of my mqtt client, placed a watch on it and saw the struct wasn't initializing. I initialized it globally
mqtt_client_t mqtt_client;
Then use it later in mqtt_start.

RSS (Receive Side Scaling) on Intel XL710 Per port

I struggle with Intel XL710 card using DPDK to make it compute RSS hash using only SRC IPV4 or DST IPV4 on per port basis.
The card has 4 10GE ports and RSS config is global for them whatever i do. I tried to set SRC/DST IPV4 fields in PCTYPE and the configuration applied last only takes action.
So the behavior i want to achieve.
Let's say i have upstream packet arrived on port 0:
SRC: 10.10.10.1 and DST:10.10.10.2
And reply downstream packet arrived on port 1:
SRC: 10.10.10.2 and DST:10.10.10.1
I want port 0 (which in our case is upstream) on the card to compute RSS hash based on SRC address 10.10.10.1 and for, port 1 (which is downstream) to compute the hash using DST address which in our case also will be 10.10.10.1. So the idea is to distribute packets between RX queues in a way that only SRC/DST address respectively affects this distribution.
I'm not bound specifically to RSS. Whatever tech will do if it allows to achieve this.
The configuration i used:
void setFilter(uint16_t portId, uint32_t value){
//Value = RTE_ETH_FLOW_NONFRAG_IPV4_TCP in that case
struct rte_eth_hash_filter_info info;
uint32_t ftype, idx, offset;
int ret;
if (rte_eth_dev_filter_supported(portId,
RTE_ETH_FILTER_HASH) < 0) {
printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
portId);
return;
}
memset(&info, 0, sizeof(info));
info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
info.info.global_conf.hash_func =
RTE_ETH_HASH_FUNCTION_DEFAULT;
ftype = value;
idx = ftype / UINT64_BIT;
offset = ftype % UINT64_BIT;
info.info.global_conf.valid_bit_mask[idx] |= (1ULL << offset);
info.info.global_conf.sym_hash_enable_mask[idx] |=
(1ULL << offset);
ret = rte_eth_dev_filter_ctrl(portId, RTE_ETH_FILTER_HASH,
RTE_ETH_FILTER_SET, &info);
if (ret < 0)
printf("Cannot set global hash configurations by port %d\n",
portId);
else
printf("Global hash configurations have been set "
"succcessfully by port %d\n", portId);
}
void setPctypeRss(uint16_t portId, uint16_t fieldIdx) {
/* Note that AVF_FILTER_PCTYPE_NONF_IPV4_TCP is define for
* Virtual Function. Defines are the same for Physical Functions
*/
int ret = -ENOTSUP;
enum rte_pmd_i40e_inset_type inset_type = INSET_HASH;
struct rte_pmd_i40e_inset inset;
ret = rte_pmd_i40e_inset_get(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to get input set.\n");
return;
}
memset(&inset, 0, sizeof(inset));
ret = rte_pmd_i40e_inset_set(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to CLEAR input set.\n");
return;
}
else
{
printf("Successfull cleared input set\n");
}
ret = rte_pmd_i40e_inset_get(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to get input set.\n");
return;
}
ret = rte_pmd_i40e_inset_field_set(&inset.inset, fieldIdx);
if (ret) {
printf("Failed to configure input set field.\n");
return;
}
ret = rte_pmd_i40e_inset_set(portId, AVF_FILTER_PCTYPE_NONF_IPV4_TCP,
&inset, inset_type);
if (ret) {
printf("Failed to set input set.\n");
return;
}
if (ret == -ENOTSUP)
printf("Function not supported\n");
}
IMO it is worth trying a bit simpler solution. We can simply use rte_eth_dev_configure():
https://doc.dpdk.org/api/rte__ethdev_8h.html#a1a7d3a20b102fee222541fda50fd87bd
And just set eth_conf.rss_conf.rss_hf to ETH_RSS_IP as described here:
https://doc.dpdk.org/api/structrte__eth__rss__conf.html#ad70f17882a835e5d4e38c64a9f872fdc
There are few examples in DPDK using this functionality. and most of them work fine ;)

WinSock UDP socket creation order in loopback.

I have a network application meant for a private LAN. I am doing my testing using loopback. When I test on the LAN the socket creation order does not matter. If I test using loop back 127.0.0.1 then there is a socket creation ordering issue. Why is it different on loop back?
Here are more details...
There is one server, and many client instances. The server is broad casting data over UDP. The clients receive the data and process it.
I need to have the network layer not care about the order in which either the server or clients start. It is hard to administer process creation for my case. The application instances should be able to start on the network in any order and just see the data broadcasted on the UDP port when it is sent.
But there is something in the way I setting up my UDP sockets which is forcing ordering to take place. I must start the clients, THEN start the server. If I start the clients AFTER the server doing the UDP broadcast, the client sockets do not receive the data. If I force a running server instance to tear down and rebuild its UDP socket, suddenly all the clients start receiving data.
There must be something wrong with how I creating the socket. The client and server code use a shared function library to make the UDP socket. So the server is sending on m_fdOut. Each instance of the client is receiving on m_fdIn.
What am I doing wrong here?
SOCKET m_fdIn;
SOCKET m_fdOut;
if ((m_fdIn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
WARNF("socket failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
if ((m_fdOut = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
WARNF("socket failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
int sockopt = 1;
if (setsockopt(m_fdOut, SOL_SOCKET, SO_BROADCAST, (char *)&sockopt,
sizeof(sockopt)) < 0)
{
WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
sockopt = readPreference<int>("SOL_RCVBUF", 512*1024);
if (setsockopt(m_fdIn, SOL_SOCKET, SO_RCVBUF, (char *)&sockopt, sizeof(sockopt)) < 0)
{
WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
sockopt = 1;
if (setsockopt(m_fdIn, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)) < 0)
{
WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
sockopt = readPreference<int>("IP_MULTICAST_TTL", 32);
if (setsockopt(m_fdOut, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&sockopt, sizeof(sockopt)) < 0)
{
WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
String destAdd = "255.255.255.255"
int portNumber = 1234;
int n1, n2, n3 ,n4;
if (sscanf(destAddr, "%d.%d.%d.%d", &n1, &n2, &n3, &n4) != 4)
{
n1 = n2 = n3 = n4 = 255;
}
u_long bcastAddr = (n1<<24) | (n2<<16) | (n3<<8) | n4;
outAddr.sin_family = AF_INET;
outAddr.sin_port = htons(portNumber);
outAddr.sin_addr.s_addr = htonl(bcastAddr);
struct sockaddr_in in_name;
in_name.sin_family = AF_INET;
in_name.sin_addr.s_addr = INADDR_ANY;
in_name.sin_port = htons(portNumber);
if (bind(m_fdIn, (struct sockaddr *)&in_name, sizeof(in_name)) < 0)
{
WARNF("bind failed, winsock error %d\n", WSAGetLastError());
exit(1);
}
So I did change the implementation from UDP broadcast to multicast. That seems to work in loopback so multiple processes can share the port.

Libnet11 build IPv6 packet manually

I am trying to use Libnet11 function:
int libnet_write_raw_ipv6 (libnet_t *l, u_int8_t *packet, u_int32_t size)
to inject IPv6 packet on network layer.
I had created IPv6 packet and captured it
with Wireshark. Wireshark reported:
malformed packet(wireshark says that next
header value in IPv6 is wrong and payload
size is too big in my opinion)
I hope, someone could help me with minimal code example,
showing how to manually build IPv6 packet (with ICMPv6
extension header) with libnet11 (libnet_write_raw_ipv6()).
I assume that the minimal code might look like this:
packet_len = 40 + 16; // 40B ~ IPv6 packet, 16B ~ ICMPv6 header
u_char *buf = NULL;
struct ip6_hdr *ip6 = NULL;
struct icmp6_hdr *icmp6 = NULL;
l = libnet_init();
if ( (buf = malloc(packet_len)) == NULL ) {
// error
}
// create IPv6 header
ip6 = (struct ip6_hdr *) buf;
ip6->ip6_flow = 0;
ip6->ip6_vfc = 6 << 4;
ip6->ip6_plen = 16; // ICMPv6 packet size
ip6->ip6_nxt = IPPROTO_ICMPV6; // 0x3a
ip6->ip6_hlim = 64;
memcpy(&(ip6->ip6_src), &src_addr, sizeof(struct in6_addr));
memcpy(&(ip6->ip6_dst), &dst_addr, sizeof(struct in6_addr));
// create ICMPv6 header
icmp6 = (struct icmp6_hdr *) (buf + 40); // 40B ~ IPv6 packet size
icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
icmp6->icmp6_code = 0;
icmp6->icmp6_cksum= 0;
icmp6->icmp6_data32[0] = 0;
libnet_do_checksum(l, (u_int8_t *)buf, IPPROTO_ICMPV6, packet_len);
written = libnet_write_raw_ipv6(l, buf, packet_len);
if ( written != packet_len )
perror("Failed to send packet");
libnet_destroy(l);
free(buf);
I tried to find code examples but with no success.
Thank you in advance.
Martin
If you're using C++, then I'd recommend you libtins, a packet crafting a sniffing library. This short snippet does exactly what you want:
#include <tins/tins.h>
using namespace Tins;
void test(const IPv6Address &dst, const IPv6Address &src) {
PacketSender sender;
IPv6 ipv6 = IPv6(dst, src) / ICMPv6();
ipv6.hop_limit(64);
sender.send(ipv6);
}
int main() {
// now use it
test("f0ef:1234::1", "f000::1");
}
You can create it with raw sockets though. I also had to do something similar but couldn't find anything as a reference.
To do it with raw sockets, this link gives you a nice explanation

Resources