C creating a raw UDP packet - c

I am interested in creating a DNS (using UDP protocol to send it) response packet, however I found limited information how to create your own packet.
Most tutorials are like this https://opensourceforu.com/2015/03/a-guide-to-using-raw-sockets/
They use structs to fill in the fields and connect them into 1 sequence. But I am concerned that the compiler can pad the struct, making it "corrupted" (make the packet longer then it should be)
I fully know that there are struct attributes, that don't allow the compiler to pad structs, but I don't want to use them
Can anyone point me some resources on packet creation. I can use Libpcap and raw sockets

You do it like this:
// helper function to add uint32_t to a buffer
char *append_uint32(char *buf_position, uint32_t value) {
// network protocols usually use network byte order for numbers,
// htonl is POSIX function so you may have to make your own on other platform
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html
value = htonl(value);
memcpy(buf_postion, &value, sizeof value);
return buf_position + sizeof value;
}
// example code using the function:
// generate packet with numbers 0...9 in network byte order
void func() {
char buf[sizeof(int32_t) * 10];
char *bptr = buf;
for(uint32_t i=0; i<10; ++i) {
bptr = append_uint32(bptr, i);
}
// do something with buf (use malloc instead of stack if you want return it!)
}

Related

How to properly utilize masks to send index information to perf event output?

According to the documentation for bpf_perf_event_output found here: http://man7.org/linux/man-pages/man7/bpf-helpers.7.html
"The flags are used to indicate the index in map for which the value must be put, masked with BPF_F_INDEX_MASK."
In the following code:
SEC("xdp_sniffer")
int xdp_sniffer_prog(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
if (data < data_end) {
/* If we have reached here, that means this
* is a useful packet for us. Pass on-the-wire
* size and our cookie via metadata.
*/
/* If we have reached here, that means this
* is a useful packet for us. Pass on-the-wire
* size and our cookie via metadata.
*/
__u64 flags = BPF_F_INDEX_MASK;
__u16 sample_size;
int ret;
struct S metadata;
metadata.cookie = 0xdead;
metadata.pkt_len = (__u16)(data_end - data);
/* To minimize writes to disk, only
* pass necessary information to userspace;
* that is just the header info.
*/
sample_size = min(metadata.pkt_len, SAMPLE_SIZE);
flags |= (__u64)sample_size << 32;
ret = bpf_perf_event_output(ctx, &my_map, flags,
&metadata, sizeof(metadata));
if (ret)
bpf_printk("perf_event_output failed: %d\n", ret);
}
return XDP_PASS;
}
It works as you would expect and stores the information for the given CPU number.
However, suppose I want all packets to be sent to index 1.
I swap
__u64 flags = BPF_F_INDEX_MASK;
for
__u64 flags = 0x1ULL;
The code compiles correctly and throws no errors, however no packets get saved at all anymore. What am I doing wrong if I want all of the packets to be sent to index 1?
Partial answer: I see no reason why the packets would not be sent to the perf buffer, but I suspect the error is on the user space code (not provided). It could be that you do not “open” the perf event for all CPUs when trying to read from the buffer. Have a look at the man page for perf_event_open(2): check that the combination of values for pid and cpu allows you to read data written for CPU 1.
As a side note, this:
__u64 flags = BPF_F_INDEX_MASK;
is misleading. The mask should be used to mask the index, not to set its value. BPF_F_CURRENT_CPU should be used instead, the former only happens to work because the two enum attributes have the same value.

IPC Socket latency fluctuation on Linux

I am working on a Client-Server Architecture on a single local machine with Linux 3.16 using AF_UNIX IPC Sockets. I have implemented a send_all and recv_all Functions to ensure sending/receiving all the wanted data and I use clock_gettime() with CLOCK_MONOTONIC to make time measurement just before the send-call on the client side and after the receive-call on the server side. Every packet I send is very small (11 Byte + the struct timespec). When I calc the delta of these two values after each transmission, I get fluctuating results by the factor ~15 while the shortest is around 150µs and the longest is above 2 milliseconds. While the <200µs would be fast enough for my needs, the >2ms are already very critical, so how can this varying latency be explained and is there a way to make the latency consistently as fast as possible for Sockets?
I am using SOCK_STREAM in the initialization and I thought that Nagle's Algorithm has to do something with the problem, but TCP_NODELAY is not settable via setsockopt() when using AF_UNIX (it seems to only work in AF_INET?). Also I'm thinking about using SOCK_DGRAM, but before I jump into that (for me) new area, I would like to know if I can even solve my problem with it.
My essential Functions for the Sockets are mostly inspired by Beej's Guide, but here some code anyway:
/* Packet Definition */
typedef struct Packet_ {
Byte opcode;
Byte from;
Byte to;
Byte payload[8];
timespec timestamp;
} Packet;
// Send
void send_all(SOCKET s, void* data, size_t len)
{
unsigned char* buffer_ptr = (unsigned char*)data;
unsigned int out_counter = 0;
while(out_counter < len)
{
out_counter += send(s, buffer_ptr, len - out_counter, 0);
}
}
// Receive
void recv_all(SOCKET s, void* buffer, size_t len)
{
unsigned char* buffer_ptr = (unsigned char*)buffer;
unsigned int in_counter = 0;
while(in_counter < len)
{
in_counter += recv(s, buffer_ptr + in_counter, len - in_counter, 0);
}
}
// Set Packet Header
void setPacketHeader(Packet* packet, Byte receivers, Byte opcode)
{
packet->from = this->get_ident();
packet->to = receivers;
packet->opcode = opcode;
}
// Set Packet Payload
void setPacketPayload(Packet* packet, void* payload, int pl_size)
{
clock_gettime(CLOCK_MONOTONIC, &(packet->timestamp));
memcpy(&(packet->payload), payload, pl_size);
}
Thanks for your time

Send UDP on specific connection in µIP

I'm using uIP on a Tiva C Launchpad board and want to send UDP Packages. But it seems that the uip_buf is not filled when i call the uip_udp_periodic function.
The code looks like this:
uint8_t my_udp_buf = {0x00, 0xAA, 0xBB, 0xCC};
uint32_t my_udp_buf_len = 4;
void main(main){
[...]
uip_ipaddr_t addr;
struct uip_udp_conn *c;
uip_ipaddr(&addr, 172,16,23,1);
c = uip_udp_new(&addr, HTONS(12345)); // setting up a new UDP connection to 172.16.23.1:12345 here
[...]
while(42==42){
uip_udp_conn = c; // set the current connection to our udp connection
uip_appdata = my_udp_buf; // asssign the uip_appdata pointer to our data pointer
uip_send(uip_appdata, my_udp_buf_len); // sending the data
[...]
// call the periodic function for all UDP connections
for(ui32Temp = 0; ui32Temp < UIP_UDP_CONNS; ui32Temp++)
{
uip_udp_periodic(ui32Temp);
// --> The uip_len is always 0! why?
//
// If the above function invocation resulted in data that
// should be sent out on the network, the global variable
// uip_len is set to a value > 0.
//
if(uip_len > 0)
{
uip_arp_out();
PacketTransmit(EMAC0_BASE, uip_buf, uip_len);
uip_len = 0;
}
}
}
}
The question is, do i set the connection correctly? In the header file i cannot find any macro or function to control on which connection i send out the data, so i assume that i need to set the connection pointer. Also do i need to save the data? probably the pointer to uip_appdata is overwritten somewhere else afterwards.
It seems like UDP is not well implemented in the bare uIP version. you need to do a lot of manual stuff:
uip_udp_conn = c; // set your connection
uip_slen = len; // set the length of data to send
memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data, len > UIP_BUFSIZE? UIP_BUFSIZE: len); // copy to the buffer
uip_process(UIP_UDP_SEND_CONN); // tell uip to construct the package
uip_arp_out(); // attack Ethernet header
PacketTransmit(EMAC0_BASE, uip_buf, uip_len); // send the package with the Tiva C function
uip_len = 0; // reset length to 0
in the contiki version of uIP is a lot more UDP convenient functionality.
When working with udp and the tiva, I have found that having a seperate function to handle the udp instances works much better. when you run it out of your main function, you will end up having multiple instances and that will cause instability

Modify header of a captured packet

I am trying to modify the IP header to include more IP options with the use of the libnetfiletr_queue. So far I have managed to come to the point where I obtain the packet as shown below.
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
fprintf(stderr, "Unable to set nfq_set_mode\n");
exit(1);
}
Then I managed to go far as shown below,
static int my_callBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,struct nfq_data *tb)
{
int id = 0;
int packet_len;
unsigned char *data;
struct nfqnl_msg_packet_hdr *packet_hdr;
unsigned char *data;
packet_hdr = nfq_get_msg_packet_hdr(tb);
if (packet_hdr) {
id = ntohl(packet_hdr->packet_id);
}
packet_len = nfq_get_payload(tb, &data);
if (packet_len >= 0) {
//print payload length
printf("payload_length = %d ", packet_len);
//modify packet ip header
}
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}
But from here onwards I am a bit confused on how to proceed on modifying the IP header of the captured packet at //modify packet ip header comment.Example on a modification to the IP header (such as traffic class(IPV6)/ IP options/ version/ flags/ destination address) is ok since I only need to understand how the modification works :).
I have tried many resources and could not succeed in proceeding any further. You expert advice and help on this query will be very much appreciated. :)
Thank you very much :)
To modify the values of an IP header, start by defining a structure to represent your header. You find what the structure should be by reading the RFC spec for the protocol you're trying to access.
Here's a link to the RFC for IPv6: https://www.rfc-editor.org/rfc/rfc2460#section-3
The first row of the IPv6 header is a bit tricky, because they aren't using byte-aligned fields. The Version field is 4-bits wide, the Traffic Class is 8-bits wide, and the Flow Label is 20-bits wide. The whole header is 320 bits (40 bytes) and 256 of those are src and dest address. Only 64-bits are used for the other fields, so it's probably easiest to define your struct like this:
struct ipv6_hdr {
uint32_t row1;
uint16_t payload_length;
uint8_t next_header;
uint8_t hop_limit;
uint16_t src[8];
uint16_t dest[8];
};
To extract the row one values, you can use some masking:
#define VERSION_MASK 0xF0000000
#define TRAFFIC_CLASS_MASK 0x0FF00000
#define FLOW_LABEL_MASK 0x000FFFFF
struct ipv6_hdr foo;
...
nfq_get_payload(tb, &foo); // Just an example; don't overflow your buffer!
// bit-wise AND gets masked field from row1
uint8_t version = (uint8_t) ((foo->row1 & VERSION_MASK) >> 28); // shift (32-4) bits
Once you point your struct to the data payload, assuming your byte array matches this format, modifying the header values becomes simple assignment:
version = 6;
// bit-wise OR puts our value in the right place in row1
foo->row1 &= ~(VERSION_MASK) // clear out the old value first
foo->row1 = ((uint32_t) version << 28) | foo->row1;
I chose to make the src and dest addresses in the struct an array of 16-bit values because IPv6 addresses are a series of 8, 16-bit values. This should make it easy to isolate any given pair of bytes.
You will have to determine what format your data payload is in before applying the proper struct to it.
For info on how to create an IPv4 header, check its RFC: https://www.rfc-editor.org/rfc/rfc791#section-3.1
Hope this helps (you may have to fiddle with my code samples to get the syntax right, it's been a few months).
editing with info about checksums as requested in comments
Follow this RFC for generating checksums after modifying your header: https://www.rfc-editor.org/rfc/rfc1071
The key take-away there is to zero the checksum field in the header before generating the new checksum.

Sending Message Over Tcp/IP using Sockets

I am trying to send data between a client/Server, the data looks like
typedef Struct Message
{ int id;
int message_length;
char* message_str;
}message;
I am trying to Write and Read this message between a client and server constantly updating the elements in this struct. I have heard Writev may do the trick. i want to send a
message to the server and then the server pulls out the elements and uses those elements as conditionals to execute the proper method?
Assuming you want to do the serialization yourself and not use Google Protocol Buffers or some library to handle it for you, I'd suggest writing a pair of functions like this:
// Serializes (msg) into a flat array of bytes, and returns the number of bytes written
// Note that (outBuf) must be big enough to hold any Message you might have, or there will
// be a buffer overrun! Modifying this function to check for that problem and
// error out instead is left as an exercise for the reader.
int SerializeMessage(const struct Message & msg, char * outBuf)
{
char * outPtr = outBuf;
int32_t sendID = htonl(msg.id); // htonl will make sure it gets sent in big-endian form
memcpy(outPtr, &sendID, sizeof(sendID));
outPtr += sizeof(sendID);
int32_t sendLen = htonl(msg.message_length);
memcpy(outPtr, &sendLen, sizeof(sendLen));
outPtr += sizeof(sendLen);
memcpy(outPtr, msg.message_str, msg.message_length); // I'm assuming message_length=strlen(message_str)+1 here
outPtr += msg.message_length;
return (outPtr-outBuf);
}
// Deserializes a flat array of bytes back into a Message object. Returns 0 on success, or -1 on failure.
int DeserializeMessage(const char * inBuf, int numBytes, struct Message & msg)
{
const char * inPtr = inBuf;
if (numBytes < sizeof(int32_t)) return -1; // buffer was too short!
int32_t recvID = ntohl(*((int32_t *)inPtr));
inPtr += sizeof(int32_t);
numBytes -= sizeof(int32_t);
msg.id = recvID;
if (numBytes < sizeof(int32_t)) return -1; // buffer was too short!
int32_t recvLen = ntohl(*((int32_t *)inPtr));
inPtr += sizeof(int32_t);
numBytes -= sizeof(int32_t);
msg.message_length = recvLen; if (msg.message_length > 1024) return -1; /* Sanity check, just in case something got munged we don't want to allocate a giant array */
msg.message_str = new char[msg.message_length];
memcpy(msg.message_str, inPtr, numBytes);
return 0;
}
With these functions, you are now able to convert a Message into a simple char-array and back at will. So now all you have to do is send the char-array over the TCP connection, receive it at the far end, and then Deserialize the array back into a Message struct there.
One wrinkle with this is that your char arrays will be variable-length (due to the presence of a string which can be different lengths), so your receiver will need some easy way to know how many bytes to receive before calling DeserializeMessage() on the array.
An easy way to handle that is to always send a 4-byte integer first, before sending the char-array. The 4-byte integer should always be the size of the upcoming array, in bytes. (Be sure to convert the integer to big-endian first, via htonl(), before sending it, and convert it back to native-endian on the receiver via htonl() before using it).
Okay, I'll take a stab at this. I'm going to assume that you have a "message" object on the sending side and what you want to do is somehow send it across to another machine and reconstruct the data there so you can do some computation on it. The part that you may not be clear on is how to encode the data for communications and then decode it on the receiving side to recover the information. The simplistic approach of just writing the bytes contained in a "message" object (i.e. write(fd, msg, sizeof(*msg), where "msg" is a pointer to an object of type "message") won't work because you will end up sending the value of a virtual address in the memory of one machine to different machine and there's not much you can do with that on the receiving end. So the problem is to design a way to pass an two integers and a character string bundled up in a way that you can fish them back out on the other end. There are, of course, many ways to do this. Does this describe what you are trying to do?
You can send structs over socket, but you have to serialize them before sending the struct using boost serialization.
Here is a sample code :
#include<iostream>
#include<unistd.h>
#include<cstring>
#include <sstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
using namespace std;
typedef struct {
public:
int id;
int message_length;
string message_str;
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &ar, const unsigned int vern)
{
ar & id;
ar & message_length;
ar & message_str;
}
} Message;
int main()
{
Message newMsg;
newMsg.id = 7;
newMsg.message_length = 14;
newMsg.message_str="Hi ya Whats up";
std::stringstream strData;
boost::archive::text_oarchive oa(strData);
oa << newMsg;
char *serObj = (char*) strData.str().c_str();
cout << "Serialized Data ::: " << serObj << "Len ::: " << strlen(serObj) << "\n";
/* Send serObj thru Sockets */
/* recv serObj from socket & deserialize it */
std::stringstream rcvdObj(serObj);
Message deserObj;
boost::archive::text_iarchive ia(rcvdObj);
ia >> deserObj;
cout<<"id ::: "<<deserObj.id<<"\n";
cout<<"len ::: "<<deserObj.message_length<<"\n";
cout<<"str ::: "<<deserObj.message_str<<"\n";
}
you can compile the program by
g++ -o serial boost.cpp /usr/local/lib/libboost_serialization.a
you must have libboost_serialization.a statically compiled in your machine.
Keeping the sockets 'blocking' will be good and you have to devise for reading these structs from recv buffer.

Resources