Search code examples
clinuxsocketsxinetd

xinetd server return value is not readable


I have enabled all xinetd services and I am calling it from the c program. Everything works fine but when I call the time service, it returns 4 bytes value that is unreadable. Following is one sample output.

c program output

So, How do I convert this output into a readable format?


Solution

  • According to Wikipedia:

    The server then sends the time as a 32-bit unsigned integer in binary format and in network byte order, representing the number of seconds since 00:00 (midnight) 1 January, 1900 GMT, and closes the connection.

    After decoding to native byte order (Via ntohl() or friends), you can then do what you like with the value. Note that it won't work as-is with functions that take a time_t like ctime() because the normal Unix epoch (The 0 point) is a different date. Luckily, that can be worked around by subtracting the offset of the epoch from the time protocol's 0 point from the provided time.


    Here's an example program that connects to the time service of the given IP address or hostname passed as its sole command line argument and prints out both the value received and a human-readable date string (Using the above mentioned offset to convert to a normal Unix time value):

    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <unistd.h>
    
    // 00:00  1 Jan 1970 GMT in RFC 868 time format.
    #define EPOCH_OFFSET 2208988800U
    
    int main(int argc, char **argv) {
      if (argc != 2) {
        fprintf(stderr, "Usage: %s hostname\n", argv[0]);
        return EXIT_FAILURE;
      }
    
      struct addrinfo *res;
      struct addrinfo hints = {
        .ai_family = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM
      };
      int err;
    
      if ((err = getaddrinfo(argv[1], "time", &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
        return EXIT_FAILURE;
      }
    
      for (struct addrinfo *addr = res; addr; addr = addr->ai_next) {
        int s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (s >= 0) {
          if (connect(s, addr->ai_addr, addr->ai_addrlen) == 0) {
            uint32_t raw;
            if (read(s, &raw, sizeof raw) != sizeof raw) {
              fprintf(stderr, "Could not read complete time.\n");
              close(s);
              freeaddrinfo(res);
              return EXIT_FAILURE;
            }
            raw = ntohl(raw);
            printf("Got raw time: %" PRIu32 "\n", raw);
    
            time_t tval = raw - EPOCH_OFFSET;
            printf("Converted time: %s", ctime(&tval));
    
            close(s);
            freeaddrinfo(res);
            return 0;
          } else {
            close(s);
          }
        }
      }
      
      printf("Unable to connect to %s's time server.\n", argv[1]);
      freeaddrinfo(res);
      return EXIT_FAILURE;
    }