c-ares specifying network interface for the DNS resolves - c++

Is there a way in which you can set the network interface to which the DNS requests can be bound to.
We have a project which requires to use a highpriority streaming session go through one interface and all the other requests channeled through the second one.
example: setting 'eth0' so that all the ares requests will go through 'eth0' and not on 'wlan0'.
I was not able to find any API in c-ares (in ares_init_options() API) that gives this option of setting interface.
Can you please let me know if there is some way to achive this or if I missed something.
Thanks,
Arjun

If you have a fairly new c-ares (c-ares >= 1.7.4), check out ares.h (It's the only place I've actually found it referenced).
/* These next 3 configure local binding for the out-going socket
* connection. Use these to specify source IP and/or network device
* on multi-homed systems.
*/
CARES_EXTERN void ares_set_local_ip4(ares_channel channel, unsigned int local_ip);
/* local_ip6 should be 16 bytes in length */
CARES_EXTERN void ares_set_local_ip6(ares_channel channel,
const unsigned char* local_ip6);
/* local_dev_name should be null terminated. */
CARES_EXTERN void ares_set_local_dev(ares_channel channel,
const char* local_dev_name);

Related

EPP Server SSL_Read hang after greeting

I have strange problems in ssl_read/ssl_write function with EPP server
After connected I read greeting message successfully.
bytes = SSL_read(ssl, buf, sizeof(buf)); // get reply & decrypt
buf[bytes] = 0;
ball+= bytes;
cc = getInt(buf);
printf("header: %x\n",cc);
printf("Received: \"%s\"\n",buf+4);
First 4 bytes are 00, 00, 09, EB and read 2539 bytes in greeting message.
After that, all operations like hello or logins are hand when SSL_read();
xml= "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><eppxmlns=\"urn:ietf:params:xml:ns:epp-1.0\"><hello/></epp>";
char bb[1000] = {0};
makeChar(strlen(xml)+4, bb);
memcpy(bb+4, xml, strlen(xml)+4);
bytes = SSL_write(ssl,xml,strlen(xml)+4);
usleep(500000); //sleep 0.5 sec
memset(buf, 0, 1024);
printf("read starting.\n");
bytes = SSL_read(ssl, buf, 1024); //always hang here
buf[bytes]=0;
printf("%d : %s", bytes, buf);
I am confused. I read RFC documentations but I can not find answer.
in EPP documentation, they said "In order to verify the identity of the secure server you will need the ‘Verisign Class 3 Public Primary Certification Authority’ root certificate available free from www.verisign.com".
is it important?
is it important?
Yes, as outlined in RFC 5734 "Extensible Provisioning Protocol (EPP) Transport over TCP", the whole security of an EPP exchange is bound to 3 properties:
access list based on IP address
TLS communication and verification of certificates (mutually, which is why you - as registrar aka client in EPP communication - have often to send in advance the certificate you will use ot the registry)
the EPP credentials used at <login> command.
Failure to properly secure the connection can mean:
you as registrar sending confidential information (your own EPP login, various details on domains you sponsor or not, including <authInfo> values, etc.) to a third party not being the registry
and in reverse, someone mimicking you in the eyes of the registry hence doing operations on which you will have to get the burden of, including financially for all domains bought, and legally.
But even in general for all cases of TLS handshake, if you want to be sure to be connected, as client, to the server you think you are, you need to verify its certificate.
Besides trivial things (dates, etc.), the certificate:
should at least be signed by an AC you trust (your choice who you trust)
and/or is a specific certificate with specific fingerprint/serial and other characteristics (but you will have to maintain that when the other party changes its certificate)
and/or matches DNS TLSA records
In short, if you are new to both EPP and TLS and C/C++ (as you state yourself in your other question about Verisign certificate), I hugely recommend you do not try to do all of this by yourself at a so low level (for example you should never manipulate XML as you do above, it shouldn't be a string. Again, there are libraries to properly parse and generate XML documents). You should use an EPP library that leverage most of the things for you. Your registry may provide an "SDK" that you can use, you should ask it.
PS: your read is probably hanging because you are not sending the payload in the correct fashion (again, something an EPP library will do for you). You need to send the length, as 4 bytes (which you need to compute after converting your string to bytes using the UTF-8 encoding), and then the payload itself. I am not sure this is what your code does. Also your reading part is wrong: you should first read 4 bytes from server, this will give you the length (but do note they can theoretically arrive not necessarily in a single packet so one "ssl read" might not give all 4 of them, you need a loop), after which you know the length of the payload you will get which allows you to set up proper buffers, if needed, as well as detecting properly when you received everything.

How to copy int to u_char*

I have a u_char* dynamic array having binary data of some network packet. I want to change the destination port number in the packet with some integer value. Suppose that the port number offset within the packet is ofs, with length of 4 bytes.
I tried the following 2 methods:
u_char* packet = new u_char[packet_size]; // Packet still empty
// Read packet from network ...
int new_port = 1234;
Method #1:
std::copy((u_char*)&new_port, (u_char*)&new_port+4, packet+ofs);
Method #2:
std::string new_port_str = std::to_string(new_port);
auto new_port_bytes = new_port_str.c_str();
std::copy(new_port_bytes, new_port_bytes+4, packet+ofs);
Both methods give garbage value for port number (but the rest of the packet is OK). Could anyone help me ?
You have to convert the integer from whatever internal representation your platform happens to use to the format the particular network protocol you're using requires them to be in when sent over the network.
This depends on the particular network protocol you're trying to use -- check its documentation for precisely the format it requires ports to be expressed in. My bet will be it's network byte order. You probably have functions like htons to convert shorts to network byte order.
Another problem -- how many bytes is int on your platform? How many bytes does the network protocol use to express ports? I'll bet the numbers are 4 and 2 respectively. So that's another issue. (Or maybe it isn't. I don't know for sure how many bytes an int is on your platform nor do I know what protocol you're trying to work with, so I have to guess.)
You can't just write code randomly and expect it to work. You have to think about what you're trying to do and understand the requirements.
My recommendation would be to look at the specification for the network protocol you're working with and figure out exactly which bytes in the data have to change and what they have to change to. Then write code to change each byte to the correct value according to the network protocol specification. This will ensure your code works correctly on any platform.

Find valid trigger sources on DAQmx device

Using National Instruments' DAQmx via C++, I would like to present a list of possible physical trigger inputs available on the system to the user.
I can set a task to start on an external trigger by calling something like
char* trigger_source = "/Dev1/PFI0";
DAQmxCfgDigEdgeStartTrig(taskAO, trigger_source, DAQmx_Val_Rising);
Is there a way to get a list of the valid values for trigger_source? I have found DAQmxGetSystemInfoAttribute(DAQmx_Sys_DevNames, , ) to get a list of the devices available in the system, and I know that DAQmxGetDevDILines() and similar functions can give me lists of some of the types of ports on a device. However, I have found nothing that returns the PFIs.
If a list cannot be obtained, is there a sane way to test whether a given guessing string like "/Dev%d/PFI%d" is a valid trigger source?
There are two ways:
Dynamically on-demand
Guess-check-cache-query
Dynamic
You can build this list, but not with a single call into the driver. Use a combination of these properties:
DAQmxGetDevTerminals(const char device[], char *data, uInt32 bufferSize) which returns the PFI lines as well as internal terminals. It doesn't return any of the I/O terminals (like ai0).
DAQmxGetDevAIPhysicalChans(const char device[], char *data, uInt32 bufferSize) which returns the channel terminals for the AI subsystem; there are similar calls for the other DAQ subsystems.
DAQmxGetDevAnlgTrigSupported(const char device[], bool32 *data) which returns whether the device supports triggering from analog signals.
DAQmxGetDevDigTrigSupported(const char device[], bool32 *data) which returns whether the device supports triggering from digital signals.
DAQmxGetDevAITrigUsage(const char device[], int32 *data) which returns what trigger types the AI subsystem can use; there are similar calls for the other DAQ subsystems.
Cached
You could also create a dummy task and preview each terminal and trigger type combination.
You won't need to run the task, just "verify" it, which will prompt the driver to run its rules system on those settings and return an error if that configuration is not supported. If you cache these in memory or a file (or a DB or whatever), it might be easier to query that instead of the driver.
DAQmxTaskControl (TaskHandle taskHandle, int32 action) which moves the task in the DAQmx state model. Using DAQmx_Val_Task_Verify for the action parameter will verify that all task parameters are valid for the hardware.

How to reconstruct TCP stream from multiple IP packets?

I am working on a TUN-based VPN server whose goal is to analyze packets it receives before forwarding them to their destination. Currently I am receiving the IP packets from a TUN interface, and simply sending them off to their destination unmodified.
I understand that analyzing the content of UDP packets would be as simple as stripping the IP and UDP headers. However, to analyze the contents of TCP traffic, I would need to reconstruct the message from multiple IP packets. Is there an easy way to do this without re-implementing TCP? Are there any easily accessible C/C++ libraries meant for this task? I would prefer Linux system libraries and/or open-source, non-viral/non-copyleft libraries.
One thing I have already considered is making a copy of each IP packet, and changing the destination IP of the copy to localhost, so that a different part of my server may receive these TCP requests and responses fully reconstructed and without headers. However, I would not be able to associate destination IPs with traffic content, which is something that I desire.
It is likely functionality you need will be always tightly coupled with packet dissection. Good protocol dissectors are really needed to extract required information. So my suggestion is to use best open source tool available - wireshark.org
It provides "Follow TCP stream" functionality:
I doesn't look like you can easily extract part of Wireshark dissection logic, but at least there is a good example packet-tcp:
typedef struct _tcp_flow_t {
guint32 base_seq; /* base seq number (used by relative sequence numbers)
* or 0 if not yet known.
*/
tcp_unacked_t *segments;
guint32 fin; /* frame number of the final FIN */
guint32 lastack; /* last seen ack */
nstime_t lastacktime; /* Time of the last ack packet */
guint32 lastnondupack; /* frame number of last seen non dupack */
guint32 dupacknum; /* dupack number */
guint32 nextseq; /* highest seen nextseq */
guint32 maxseqtobeacked;/* highest seen continuous seq number (without hole in the stream) from the fwd party,
* this is the maximum seq number that can be acked by the rev party in normal case.
* If the rev party sends an ACK beyond this seq number it indicates TCP_A_ACK_LOST_PACKET contition */
guint32 nextseqframe; /* frame number for segment with highest
* sequence number
*/
Basically, there is separate conversation extraction logic, please notice find_conversation usage:
/* Attach process info to a flow */
/* XXX - We depend on the TCP dissector finding the conversation first */
void
add_tcp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command) {
conversation_t *conv;
struct tcp_analysis *tcpd;
tcp_flow_t *flow = NULL;
conv = find_conversation(frame_num, local_addr, remote_addr, PT_TCP, local_port, remote_port, 0);
if (!conv) {
return;
}
The actual logic is well documented and available here:
/*
* Given two address/port pairs for a packet, search for a conversation
* containing packets between those address/port pairs. Returns NULL if
* not found.
*
* We try to find the most exact match that we can, and then proceed to
* try wildcard matches on the "addr_b" and/or "port_b" argument if a more
* exact match failed.
* ...
*/
conversation_t *
find_conversation(const guint32 frame_num, const address *addr_a, const address *addr_b, const port_type ptype,
const guint32 port_a, const guint32 port_b, const guint options)
{
conversation_t *conversation;
/*
* First try an exact match, if we have two addresses and ports.
*/
if (!(options & (NO_ADDR_B|NO_PORT_B))) {
So what I'm actually suggesting is to use EPAN library. It is possible to extract this library and use it independently. Please be careful with the license.
Maybe you might be interested in libipq - iptables userspace packet queuing library.
#include <linux/netfilter.h>
#include <libipq.h>
Netfilter provides a mechanism for passing packets out of the stack
for queueing to userspace, then receiving these packets back into the
kernel with a verdict specifying what to do with the packets (such as
ACCEPT or DROP). These packets may also be modified in userspace prior
to reinjection back into the kernel. For each supported protocol, a
kernel module called a queue handler may register with Netfilter to
perform the mechanics of passing packets to and from userspace.
The standard queue handler for IPv4 is ip_queue. It is provided as an
experimental module with 2.4 kernels, and uses a Netlink socket for
kernel/userspace communication.
Once ip_queue is loaded, IP packets may be selected with iptables and
queued for userspace processing via the QUEUE target
here is brief example how to decompose tcp/ip packet:
ipq_packet_msg_t *m = ipq_get_packet(buf);
struct iphdr *ip = (struct iphdr*) m->payload;
struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl));
int port = htons(tcp->dest);
status = ipq_set_verdict(h, m->packet_id,
NF_ACCEPT, 0, NULL);
if (status < 0)
die(h);
quick intro
If this is not what you are looking for you might try to use wireshark EPAN library.

How to set the don't fragment (DF) flag on a socket?

I am trying to set the DF (don't fragment flag) for sending packets using UDP.
Looking at the Richard Steven's book Volume 1 Unix Network Programming; The Sockets Networking API, I am unable to find how to set this.
I suspect that I would do it with setsockopt() but can't find it in the table on page 193.
Please suggest how this is done.
You do it with the setsockopt() call, by using the IP_DONTFRAG option:
int val = 1;
setsockopt(sd, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val));
Here's a page explaining this in further detail.
For Linux, it appears you have to use the IP_MTU_DISCOVER option with the value IP_PMTUDISC_DO (or IP_PMTUDISC_DONT to turn it off):
int val = IP_PMTUDISC_DO;
setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));
I haven't tested this, just looked in the header files and a bit of a web search so you'll need to test it.
As to whether there's another way the DF flag could be set:
I find nowhere in my program where the "force DF flag" is set, yet tcpdump suggests it is. Is there any other way this could get set?
From this excellent page here:
IP_MTU_DISCOVER: Sets or receives the Path MTU Discovery setting for a socket. When enabled, Linux will perform Path MTU Discovery as defined in RFC 1191 on this socket. The don't fragment flag is set on all outgoing datagrams. The system-wide default is controlled by the ip_no_pmtu_disc sysctl for SOCK_STREAM sockets, and disabled on all others. For non SOCK_STREAM sockets it is the user's responsibility to packetize the data in MTU sized chunks and to do the retransmits if necessary. The kernel will reject packets that are bigger than the known path MTU if this flag is set (with EMSGSIZE).
This looks to me like you can set the system-wide default using sysctl:
sysctl ip_no_pmtu_disc
returns "error: "ip_no_pmtu_disc" is an unknown key" on my system but it may be set on yours. Other than that, I'm not aware of anything else (other than setsockopt() as previously mentioned) that can affect the setting.
If you are working in Userland with the intention to bypass the Kernel network stack and thus building your own packets and headers and hand them to a custom Kernel module, there is a better option than setsockopt().
You can actually set the DF flag just like any other field of struct iphdr defined in linux/ip.h. The 3-bit IP flags are in fact part of the frag_off
(Fragment Offset) member of the structure.
When you think about it, it makes sense to group those two things as the flags are fragmentation related. According to the RFC-791, the section describing the IP header structure states that Fragment Offset is 13-bit long and there are three 1-bit flags. The
frag_off member is of type __be16, which can hold 13 + 3 bits.
Long story short, here's a solution:
struct iphdr ip;
ip.frag_off |= ntohs(IP_DF);
We are here exactly setting the DF bit using the designed-for-that-particular-purpose IP_DF mask.
IP_DF is defined in net/ip.h (kernel headers, of course), whereas struct iphdr is defined in linux/ip.h.
I agree with the paxdiablo's answer.
setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))
where val is one of:
#define IP_PMTUDISC_DONT 0 /* Never send DF frames. */
#define IP_PMTUDISC_WANT 1 /* Use per route hints. */
#define IP_PMTUDISC_DO 2 /* Always DF. */
#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu. */
ip_no_pmtu_disc in kernel source:
if (ipv4_config.no_pmtu_disc)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;