iPXE
Data Structures | Functions | Variables
ntp.c File Reference

Network Time Protocol. More...

#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <ipxe/malloc.h>
#include <ipxe/refcnt.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/retry.h>
#include <ipxe/timer.h>
#include <ipxe/time.h>
#include <ipxe/tcpip.h>
#include <ipxe/ntp.h>

Go to the source code of this file.

Data Structures

struct  ntp_client
 An NTP client. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static void ntp_close (struct ntp_client *ntp, int rc)
 Close NTP client.
static int ntp_request (struct ntp_client *ntp)
 Send NTP request.
static int ntp_deliver (struct ntp_client *ntp, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Handle NTP response.
static void ntp_window_changed (struct ntp_client *ntp)
 Handle data transfer window change.
static void ntp_expired (struct retry_timer *timer, int fail)
 Handle NTP timer expiry.
int start_ntp (struct interface *job, const char *hostname)
 Start NTP client.

Variables

static struct interface_operation ntp_xfer_op []
 Data transfer interface operations.
static struct interface_descriptor ntp_xfer_desc
 Data transfer interface descriptor.
static struct interface_operation ntp_job_op []
 Job control interface operations.
static struct interface_descriptor ntp_job_desc
 Job control interface descriptor.

Detailed Description

Network Time Protocol.

Definition in file ntp.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static void ntp_close ( struct ntp_client ntp,
int  rc 
) [static]

Close NTP client.

Parameters:
ntpNTP client
rcReason for close

Definition at line 65 of file ntp.c.

References intf_shutdown(), ntp_client::job, stop_timer(), ntp_client::timer, and ntp_client::xfer.

Referenced by ntp_deliver(), ntp_expired(), and start_ntp().

                                                         {

        /* Stop timer */
        stop_timer ( &ntp->timer );

        /* Shut down interfaces */
        intf_shutdown ( &ntp->xfer, rc );
        intf_shutdown ( &ntp->job, rc );
}
static int ntp_request ( struct ntp_client ntp) [static]

Send NTP request.

Parameters:
ntpNTP client
Return values:
rcReturn status code

Definition at line 81 of file ntp.c.

References DBGC, ntp_header::flags, ntp_timestamp::fraction, htonl, memset(), NTP_EPOCH, NTP_FL_LI_UNKNOWN, NTP_FL_MODE_CLIENT, NTP_FL_VN_1, NTP_FRACTION_MAGIC, NULL, rc, ntp_timestamp::seconds, strerror(), time, ntp_header::transmit, ntp_client::xfer, and xfer_deliver_raw().

Referenced by ntp_expired().

                                                  {
        struct ntp_header hdr;
        int rc;

        DBGC ( ntp, "NTP %p sending request\n", ntp );

        /* Construct header */
        memset ( &hdr, 0, sizeof ( hdr ) );
        hdr.flags = ( NTP_FL_LI_UNKNOWN | NTP_FL_VN_1 | NTP_FL_MODE_CLIENT );
        hdr.transmit.seconds = htonl ( time ( NULL ) + NTP_EPOCH );
        hdr.transmit.fraction = htonl ( NTP_FRACTION_MAGIC );

        /* Send request */
        if ( ( rc = xfer_deliver_raw ( &ntp->xfer, &hdr,
                                       sizeof ( hdr ) ) ) != 0 ) {
                DBGC ( ntp, "NTP %p could not send request: %s\n",
                       ntp, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int ntp_deliver ( struct ntp_client ntp,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Handle NTP response.

Parameters:
ntpNTP client
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 112 of file ntp.c.

References close(), io_buffer::data, DBGC, DBGC_HDA, EPROTO, ntp_header::flags, ntp_timestamp::fraction, free_iob(), hdr, htonl, htons, iob_len(), ntohl, ntp_close(), NTP_FL_MODE_MASK, NTP_FL_MODE_SERVER, NTP_FRACTION_MAGIC, NTP_PORT, ntp_header::originate, rc, ntp_header::receive, ntp_timestamp::seconds, xfer_metadata::src, sockaddr_tcpip::st_port, and ntp_header::stratum.

                                                      {
        struct ntp_header *hdr;
        struct sockaddr_tcpip *st_src;
        int32_t delta;
        int rc;

        /* Check source port */
        st_src = ( ( struct sockaddr_tcpip * ) meta->src );
        if ( st_src->st_port != htons ( NTP_PORT ) ) {
                DBGC ( ntp, "NTP %p received non-NTP packet:\n", ntp );
                DBGC_HDA ( ntp, 0, iobuf->data, iob_len ( iobuf ) );
                goto ignore;
        }

        /* Check packet length */
        if ( iob_len ( iobuf ) < sizeof ( *hdr ) ) {
                DBGC ( ntp, "NTP %p received malformed packet:\n", ntp );
                DBGC_HDA ( ntp, 0, iobuf->data, iob_len ( iobuf ) );
                goto ignore;
        }
        hdr = iobuf->data;

        /* Check mode */
        if ( ( hdr->flags & NTP_FL_MODE_MASK ) != NTP_FL_MODE_SERVER ) {
                DBGC ( ntp, "NTP %p received non-server packet:\n", ntp );
                DBGC_HDA ( ntp, 0, iobuf->data, iob_len ( iobuf ) );
                goto ignore;
        }

        /* Check magic value */
        if ( hdr->originate.fraction != htonl ( NTP_FRACTION_MAGIC ) ) {
                DBGC ( ntp, "NTP %p received unrecognised packet:\n", ntp );
                DBGC_HDA ( ntp, 0, iobuf->data, iob_len ( iobuf ) );
                goto ignore;
        }

        /* Check for Kiss-o'-Death packets */
        if ( ! hdr->stratum ) {
                DBGC ( ntp, "NTP %p received kiss-o'-death:\n", ntp );
                DBGC_HDA ( ntp, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EPROTO;
                goto close;
        }

        /* Calculate clock delta */
        delta = ( ntohl ( hdr->receive.seconds ) -
                  ntohl ( hdr->originate.seconds ) );
        DBGC ( ntp, "NTP %p delta %d seconds\n", ntp, delta );

        /* Adjust system clock */
        time_adjust ( delta );

        /* Success */
        rc = 0;

 close:
        ntp_close ( ntp, rc );
 ignore:
        free_iob ( iobuf );
        return 0;
}
static void ntp_window_changed ( struct ntp_client ntp) [static]

Handle data transfer window change.

Parameters:
ntpNTP client

Definition at line 180 of file ntp.c.

References start_timer_nodelay(), and ntp_client::timer.

                                                          {

        /* Start timer to send initial request */
        start_timer_nodelay ( &ntp->timer );
}
static void ntp_expired ( struct retry_timer timer,
int  fail 
) [static]

Handle NTP timer expiry.

Parameters:
timerRetransmission timer
failFailure indicator

Definition at line 213 of file ntp.c.

References container_of, ETIMEDOUT, ntp(), ntp_close(), ntp_request(), start_timer(), and ntp_client::timer.

Referenced by start_ntp().

                                                                {
        struct ntp_client *ntp =
                container_of ( timer, struct ntp_client, timer );

        /* Shut down client if we have failed */
        if ( fail ) {
                ntp_close ( ntp, -ETIMEDOUT );
                return;
        }

        /* Otherwise, restart timer and (re)transmit request */
        start_timer ( &ntp->timer );
        ntp_request ( ntp );
}
int start_ntp ( struct interface job,
const char *  hostname 
)

Start NTP client.

Parameters:
jobJob control interface
hostnameNTP server
Return values:
rcReturn status code

Definition at line 235 of file ntp.c.

References DBGC, ENOMEM, htons, intf_init(), intf_plug_plug(), ntp_client::job, memset(), ntp(), ntp_close(), ntp_expired(), NTP_MAX_TIMEOUT, NTP_MIN_TIMEOUT, NTP_PORT, NULL, rc, ref_init, ref_put, ntp_client::refcnt, SOCK_DGRAM, strerror(), ntp_client::timer, ntp_client::xfer, xfer_open_named_socket(), and zalloc().

Referenced by ntp().

                                                              {
        struct ntp_client *ntp;
        union {
                struct sockaddr_tcpip st;
                struct sockaddr sa;
        } server;
        int rc;

        /* Allocate and initialise structure*/
        ntp = zalloc ( sizeof ( *ntp ) );
        if ( ! ntp ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        ref_init ( &ntp->refcnt, NULL );
        intf_init ( &ntp->job, &ntp_job_desc, &ntp->refcnt );
        intf_init ( &ntp->xfer, &ntp_xfer_desc, &ntp->refcnt );
        timer_init ( &ntp->timer, ntp_expired, &ntp->refcnt );
        set_timer_limits ( &ntp->timer, NTP_MIN_TIMEOUT, NTP_MAX_TIMEOUT );

        /* Open socket */
        memset ( &server, 0, sizeof ( server ) );
        server.st.st_port = htons ( NTP_PORT );
        if ( ( rc = xfer_open_named_socket ( &ntp->xfer, SOCK_DGRAM, &server.sa,
                                             hostname, NULL ) ) != 0 ) {
                DBGC ( ntp, "NTP %p could not open socket: %s\n",
                       ntp, strerror ( rc ) );
                goto err_open;
        }

        /* Attach parent interface, mortalise self, and return */
        intf_plug_plug ( &ntp->job, job );
        ref_put ( &ntp->refcnt );
        return 0;

 err_open:
        ntp_close ( ntp, rc );
        ref_put ( &ntp->refcnt );
 err_alloc:
        return rc;
}

Variable Documentation

struct interface_operation ntp_xfer_op[] [static]
Initial value:

Data transfer interface operations.

Definition at line 187 of file ntp.c.

Initial value:
        INTF_DESC_PASSTHRU ( struct ntp_client, xfer, ntp_xfer_op, job )

Data transfer interface descriptor.

Definition at line 195 of file ntp.c.

struct interface_operation ntp_job_op[] [static]
Initial value:
 {
        INTF_OP ( intf_close, struct ntp_client *, ntp_close ),
}

Job control interface operations.

Definition at line 199 of file ntp.c.

Initial value:
        INTF_DESC_PASSTHRU ( struct ntp_client, job, ntp_job_op, xfer )

Job control interface descriptor.

Definition at line 204 of file ntp.c.