How to Generate Network Packets with C/C++
Asked Answered
S

1

6

I want to generate a network packet to send over (for example) port 123 to an NTP server so I can receive and parse the returned packet. The goal is to better understand how packets are generated, read, and replied to by networked systems.

(1) Should a struct be used to generate the packet?

(2) I am not sure how to properly populate the various fields within the struct; for example, should the source and destination IP addresses be set with hex values? Or is there a more human-friendly way?

(3) Then, once the fields have been populated, can the struct be sent via send()/write() over a UDP connection to an NTP server? (or TCP, should the protocol demand it)

Is my approach reasonable? I've been reading the NTP RFC, but am still not sure what my client should be sending to the server (such as IP address; shouldn't this be taken care of by the Network Layer header?) I've modeled this NTP struct after the "transmit" example in Appendix A of RFC 5905. I apologize if my question is poorly worded or too long. Thank you in advance for any help. The code example below borrows from the example code in RFC 5905.

typedef unsigned long ipaddr;       //32 bits (4 bytes)
typedef signed char s_char;     //character type as number, -128..127
typedef unsigned int tdist;     //character type as number, 0..255
typedef unsigned long long tstamp;  //64 bits (8 bytes)
typedef unsigned long digest;       //32 bits (4 bytes)

struct Ntp {
    ipaddr  dstaddr;
    ipaddr  srcaddr;
    char    version;
    char    leap;
    char    mode;
    char    stratum;
    char    poll;
    s_char  precision;
    tdist   rootdelay;
    tdist   rootdisp;
    char    refid;
    tstamp  reftime;
    tstamp  org;
    tstamp  rec;
    tstamp  xmt;
    int     keyid;
    digest  dgst;
} Ntp;

int main()
{
    struct Ntp packet;

    //packet.dstaddr=WHAT_GOES_HERE;
    //...
    //...
    //packet.dgst=WHAT_GOES_HERE;

    return 0;
}
Suziesuzuki answered 24/6, 2011 at 23:52 Comment(10)
Are you sure your Ntp struct isn't padded in unpredictable ways?Wearing
"should the source and destination IP addresses be set with hex values" -- certainly not, though they would be preferred when using IPv6. C has decimal literals, decimals parsing functions and IP parsing functions (platform-dependent, check your OS manual).Hardden
You may need to adjust the endian-ness of any multi-byte quantities you send over the wire, which is another reason to avoid sending the whole struct in a single write.Faber
@Kerrek SB--No, I am not sure as I have not filled each section of the packet yet, though I am sure this is a problem I will run in to.Suziesuzuki
@Iarsmans--Thank you for the suggestion, I will look in to C-supported parsing functions.Suziesuzuki
@Jim Lewis--Are you referring to a situation where a packet might be fragmented? Could you please clarify what a 'multi-byte quantity' sent over the network is? Thank you for the feedbackSuziesuzuki
@shelladept, if you want a simple network protocol to code against, write for the echo protocolMomentum
@shelladept: No, fragmentation occurs at a level that you, as a network programmer, seldom need to consider. But the protocols you are trying to interoperate with generally have very specific requirements about how your data should be formatted, and it may not match the way your compiler lays out structures in memory. That's what Kerrek meant about padding, and what I meant about byte order (least significant or most significant byte first, over the wire, for a 16-bit or wider quantity). Good question!Faber
@Mike Pennington: Thank you for the suggestion, I will try writing for the simpler protocol.Suziesuzuki
@Jim Lewis: Thank you for expanding on your earlier suggestion; I appreciate the detail of your response. It is quite helpful.Suziesuzuki
G
2

You don't seem to have a lot of experience writing network protocols. Declaring a struct and writing it out isn't the way to go. I also point you to http://fixunix.com/ntp/257876-any-samples-ntp-sntp-client-code.html and specifically call out the following points:

  • Why do you want to roll your own as compared to run one of the existing packages?

  • One issue in writing a NTP client is getting the time right.

  • The other is not screwing up the rest of the network or putting an unreasonable load on the servers.

In any case, as discussed in the thread I pointed you to, you want to use SNTP and should take a look at the SNTP reference implementation in the ntp tarball to point the way and help you figure out what you should be doing.

Glasgo answered 25/6, 2011 at 0:15 Comment(1)
Thank you for the reply; my goal is to better understand how packets are sent, read, and replied to by systems over the network (at the most basic level). I am not trying to make a publicly usable client--I just want to successfully send a packet which adheres to a protocol. In this case NTP; I chose it because I thought [perhaps erroneously] that it would be a more realistic goal. I suppose my question does not accurately advertise my goal and I apologize for any confusion; thank you for your constructive response--I will edit my question accordingly.Suziesuzuki

© 2022 - 2024 — McMap. All rights reserved.