#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

// Structure definition (with no padding)
#pragma pack(push, 1)
typedef struct {
    uint8_t li_vn_mode;        // Leap Indicator (2), Version Number (3), Mode (3)
    uint8_t r_e_m_opcode;      // Response (1), Error (1), More (1), Opcode (5)
    uint16_t sequence;
    uint16_t status;
    uint16_t assoc_id;
    uint16_t offset;
    uint16_t count;
    uint8_t data[480];         // Optional data for control messages
} ntp_control_message;
#pragma pack(pop)

// Create and return a UDP socket
int create_udp_socket() {
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        return -1;
    }
    return sock;
}

// Send an NTP control message to the specified server
void send_ntp_control_packet(const char* server_ip) {
    int sock = create_udp_socket();
    if (sock < 0) return;

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(123); // NTP uses port 123
    if (inet_pton(AF_INET, server_ip, &server_addr.sin_addr) != 1) {
        perror("Invalid IP address");
        close(sock);
        return;
    }

    ntp_control_message msg;
    memset(&msg, 0, sizeof(msg));

    // LI=0, VN=4, Mode=6 (Control)
    msg.li_vn_mode = (0 << 6) | (4 << 3) | 6;

    // Response=0, Error=0, More=0, Opcode=2 (Read Status)
    msg.r_e_m_opcode = 2;

    msg.sequence = htons(1);
    msg.status = htons(0);
    msg.assoc_id = htons(0);   // For system peer, assoc ID = 0
    msg.offset = htons(0);
    msg.count = htons(0);      // No payload

    ssize_t sent = sendto(sock, &msg, sizeof(msg) - sizeof(msg.data), 0,
                          (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (sent < 0) {
        perror("Send failed");
    } else {
        printf("Sent %ld bytes to %s (NTP Control Message, Opcode 2)\n", sent, server_ip);
    }

    close(sock);
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        printf("Usage: %s <NTP Server IP>\n", argv[0]);
        return 1;
    }

    send_ntp_control_packet(argv[1]);
    return 0;
}

