Facebook
From Edgy Tamarin, 3 Years ago, written in C.
Embed
Download Paste or View Raw
Hits: 77
  1.     // plik: ntpc.c
  2.     // Zobacz:
  3.     // https://en.wikipedia.org/wiki/Network_Time_Protocol
  4.     //
  5.     // https://github.com/SanketDG/c-projects/blob/master/ntp-client.c
  6.     // https://www.cbk.poznan.pl/
  7.     //
  8.     // Kompilacja: cygwin
  9.     // gcc ntpc.c -o ntpc
  10.     // $ ./ntpc
  11.     // Usage: ./ntpc <server> [port]
  12.     //  
  13.     //  $ ./ntpc 150.254.183.15
  14.     //  Time: Sat Mar 30 09:28:12 2019
  15.     //
  16.     // ./ntpc vega.cbk.poznan.pl
  17.     //
  18.     // ./ntpc 150.254.183.15 123
  19.     //---------------------------------------------------------------
  20.      
  21.     #include <stdio.h>
  22.     #include <stdlib.h>
  23.     #include <stdint.h>
  24.     #include <string.h>
  25.     #include <sys/types.h>
  26.     #include <sys/socket.h>
  27.     #include <netdb.h>
  28.     #include <arpa/inet.h>
  29.     #include <time.h>
  30.     #include <unistd.h>
  31.      
  32.     // Difference between Jan 1, 1900 and Jan 1, 1970
  33.     #define UNIX_OFFSET 2208988800L
  34.      
  35.     #define NTP_DEFAULT_PORT "123"
  36.      
  37.     // Flags 00|100|011 for li=0, vn=4, mode=3
  38.     #define NTP_FLAGS 0x23
  39.      
  40.     typedef struct {
  41.      
  42.         uint8_t flags;
  43.      
  44.         uint8_t stratum;
  45.         uint8_t poll;
  46.      
  47.         uint8_t precision;
  48.      
  49.         uint32_t root_delay;
  50.         uint32_t root_dispersion;
  51.      
  52.         uint8_t referenceID[4];
  53.      
  54.         uint32_t ref_ts_secs;
  55.         uint32_t ref_ts_frac;
  56.      
  57.         uint32_t origin_ts_secs;
  58.         uint32_t origin_ts_frac;
  59.      
  60.         uint32_t recv_ts_secs; // This is what we need mostly to get current time.
  61.         uint32_t recv_ts_fracs;
  62.      
  63.         uint32_t transmit_ts_secs;
  64.         uint32_t transmit_ts_frac;
  65.      
  66.     } ntp_packet;
  67.      
  68.      
  69.     int main(int argc, char *argv[]) {
  70.      
  71.         char *server;
  72.         char *port = NTP_DEFAULT_PORT;
  73.      
  74.         int server_sock, status;
  75.      
  76.         struct addrinfo hints, *servinfo, *ap;
  77.      
  78.         socklen_t addrlen = sizeof(struct sockaddr_storage);
  79.      
  80.         if(argc < 2) {
  81.             printf("Usage: %s <server> [port]\n", argv[0]);
  82.             exit(1);
  83.         }
  84.      
  85.         server = argv[1]; // if it is supplied as argument
  86.      
  87.         if(argc == 3) {
  88.             // Port is also passed in as argument
  89.             port = argv[2];
  90.         }
  91.      
  92.         ntp_packet packet = { .flags = NTP_FLAGS }; // populate the struct
  93.      
  94.         hints = (struct addrinfo) { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM };
  95.      
  96.         // Get the info of the NTP server
  97.      
  98.         if((status = getaddrinfo(server, port, &hints, &servinfo)) != 0) {
  99.             fprintf(stderr, "getaddrinfo() error: %s\n", gai_strerror(status));
  100.             exit(2);
  101.         }
  102.      
  103.         // Initalize the socket
  104.      
  105.         for(ap = servinfo; ap != NULL; ap = ap->ai_next) {
  106.             server_sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
  107.             if(server_sock == -1)
  108.                 continue;
  109.             break;
  110.         }
  111.      
  112.         if (ap == NULL) {
  113.             fprintf(stderr, "socket() error\n");
  114.             exit(2);
  115.         }
  116.      
  117.         // Send the structure to the server
  118.      
  119.         if((status = sendto(server_sock, &packet, sizeof(packet), 0, ap->ai_addr, addrlen)) == -1) {
  120.             perror("sendto() error");
  121.             exit(2);
  122.         }
  123.      
  124.         // Recive the structure from the server
  125.      
  126.         if((status = recvfrom(server_sock, &packet, sizeof(packet), 0, ap->ai_addr, &addrlen)) == -1) {
  127.             perror("recvfrom() error");
  128.             exit(2);
  129.         }
  130.      
  131.         freeaddrinfo(servinfo);
  132.         close(server_sock);
  133.      
  134.         // Convert from network's to host's endian order
  135.      
  136.         packet.recv_ts_secs = ntohl(packet.recv_ts_secs);
  137.      
  138.         // The number of seconds we get back from the server is equal to the no. of
  139.         // seconds since Jan 1, 1900. Since Unix time starts from Jan 1, 1970, we
  140.         // subtract 70 years worth of seconds from Jan 1, 1990.
  141.        
  142.         time_t time_struct = (time_t) packet.recv_ts_secs - UNIX_OFFSET;
  143.      
  144.         printf("Time s: %s", ctime(&time_struct));
  145.  
  146.         time_t rawtime;
  147.         struct tm * timeinfo;
  148.         time (&rawtime);
  149.         timeinfo = localtime (&rawtime);
  150.         printf("Time l: %s", asctime(timeinfo));
  151.     }
  152.  
  153.