xinetd server return value is not readable

84 Views Asked by At

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?

1

There are 1 best solutions below

1
On BEST ANSWER

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;
}