Exemplo n.º 1
0
/** UDP receive callback for the sntp pcb */
static void sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) {
    u8_t mode;
    u8_t stratum;
    u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE];
    err_t err;

    LWIP_UNUSED_ARG(arg);
    LWIP_UNUSED_ARG(pcb);

    /* packet received: stop retry timeout  */
    sys_untimeout(sntp_try_next_server, NULL);
    sys_untimeout(sntp_request, NULL);

    err = ERR_ARG;
#if SNTP_CHECK_RESPONSE >= 1
    /* Check server address and port */
    if (ip_addr_cmp(addr, &sntp_last_server_address) && (port == SNTP_PORT))
#else /* SNTP_CHECK_RESPONSE >= 1 */
    LWIP_UNUSED_ARG(addr);
    LWIP_UNUSED_ARG(port);
#endif /* SNTP_CHECK_RESPONSE >= 1 */
    {
        /* Process the response */
        if (p->tot_len == SNTP_MSG_LEN) {
            pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE);
            mode &= SNTP_MODE_MASK;
            /* If this is a SNTP response... */
            if ((mode == SNTP_MODE_SERVER) || (mode == SNTP_MODE_BROADCAST)) {
                pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM);
                if (stratum == SNTP_STRATUM_KOD) {
                    /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
                    err = SNTP_ERR_KOD;
                    LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
                } else {
#if SNTP_CHECK_RESPONSE >= 2
                    /* check originate_timetamp against sntp_last_timestamp_sent */
                    u32_t originate_timestamp[2];
                    pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME);
                    if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) ||
                            (originate_timestamp[1] != sntp_last_timestamp_sent[1])) {
                        LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n"));
                    } else
#endif /* SNTP_CHECK_RESPONSE >= 2 */
                        /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
                    {
                        /* Correct answer */
                        err = ERR_OK;
                        pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_RECEIVE_TIME);
                    }
                }
            } else {
                LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
            }
        } else {
            LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
        }
    }
    pbuf_free(p);

    if (err == ERR_OK) {
        /* Correct response, reset retry timeout */
        SNTP_RESET_RETRY_TIMEOUT();

        sntp_process(receive_timestamp);

        /* Set up timeout for next request */
        sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
        LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", (u32_t)SNTP_UPDATE_DELAY));
    } else if (err == SNTP_ERR_KOD) {
        /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
        sntp_try_next_server(NULL);
    } else {
        /* Another error, try the same server again */
        sntp_retry(NULL);
    }
}
Exemplo n.º 2
0
/**
 * SNTP request
 */
static void sntp_request()
{
	int                sock;
	struct sockaddr_in local;
	struct sockaddr_in to;
	int                tolen;
	int                size;
	int                timeout;
	u8_t               sntp_request [SNTP_MAX_DATA_LEN];
	u8_t               sntp_response[SNTP_MAX_DATA_LEN];
	u32_t              sntp_server_address;
	u32_t              timestamp;
	time_t             t;

	/* initialize SNTP server address */
	sntp_server_address = SNTP_SERVER_ADDRESS;

	/* if we got a valid SNTP server address... */
	if (sntp_server_address!=0)
	{
		/* create new socket */
		sock = socket( AF_INET, SOCK_DGRAM, 0);
		if (sock>=0)
		{
			/* prepare local address */
			memset(&local, 0, sizeof(local));
			local.sin_family      = AF_INET;
			local.sin_port        = htons(INADDR_ANY);
			local.sin_addr.s_addr = htonl(INADDR_ANY);

			/* bind to local address */
			if (bind( sock, (struct sockaddr *)&local, sizeof(local))==0)
			{
				/* set recv timeout */
				timeout = SNTP_RECV_TIMEOUT;
				setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));

				/* prepare SNTP request */
				memset( sntp_request, 0, sizeof(sntp_request));
				sntp_request[0] = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;

				/* prepare SNTP server address */
				memset(&to, 0, sizeof(to));
				to.sin_family      = AF_INET;
				to.sin_port        = htons(SNTP_PORT);
				to.sin_addr.s_addr = sntp_server_address;

				/* send SNTP request to server */
				if (sendto( sock, sntp_request, sizeof(sntp_request), 0, (struct sockaddr *)&to, sizeof(to))>=0)
				{
					/* receive SNTP server response */
					tolen = sizeof(to);
					size  = recvfrom( sock, sntp_response, sizeof(sntp_response), 0, (struct sockaddr *)&to, (socklen_t *)&tolen);

					/* if the response size is good */
					if (size == SNTP_MAX_DATA_LEN)
					{
						/* if this is a SNTP response... */
						if (((sntp_response[0] & SNTP_MODE_MASK) == SNTP_MODE_SERVER) || ((sntp_response[0] & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST))
						{
							/* extract GMT time from response */
							SMEMCPY( &timestamp, (sntp_response+SNTP_RCV_TIME_OFS), sizeof(timestamp));
							t = (ntohl(timestamp) - DIFF_SEC_1900_1970);

							/* do time processing */
							sntp_process(t);

						}
						else
						{
							LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not response frame code\n"));
						}
					}
					else
					{
						LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not recvfrom==%i\n", errno));
					}
				}
				else
				{
					LWIP_DEBUGF( SNTP_DEBUG, ("sntp_request: not sendto==%i\n", errno));
				}
			}
			/* close the socket */
			closesocket(sock);
		}
	}
}
Exemplo n.º 3
0
/**
 * Send an SNTP request via sockets.
 * This is a very minimal implementation that does not fully conform
 * to the SNTPv4 RFC, especially regarding server load and error procesing.
 */
void
sntp_request(void *arg)
{
  int                sock;
  struct sockaddr_in local;
  struct sockaddr_in to;
  int                tolen;
  int                size;
  int                timeout;
  struct sntp_msg    sntpmsg;
  ip_addr_t          sntp_server_address;

  LWIP_UNUSED_ARG(arg);

  /* if we got a valid SNTP server address... */
  if (ipaddr_aton(SNTP_SERVER_ADDRESS, &sntp_server_address)) {
    /* create new socket */
    sock = lwip_socket(AF_INET, SOCK_DGRAM, 0);
    if (sock >= 0) {
      /* prepare local address */
      memset(&local, 0, sizeof(local));
      local.sin_family      = AF_INET;
      local.sin_port        = PP_HTONS(INADDR_ANY);
      local.sin_addr.s_addr = PP_HTONL(INADDR_ANY);

      /* bind to local address */
      if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) {
        /* set recv timeout */
        timeout = SNTP_RECV_TIMEOUT;
        lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));

        /* prepare SNTP request */
        sntp_initialize_request(&sntpmsg);

        /* prepare SNTP server address */
        memset(&to, 0, sizeof(to));
        to.sin_family      = AF_INET;
        to.sin_port        = PP_HTONS(SNTP_PORT);
        inet_addr_from_ipaddr(&to.sin_addr, &sntp_server_address);
    
        /* send SNTP request to server */
        if (lwip_sendto(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, sizeof(to)) >= 0) {
          /* receive SNTP server response */
          tolen = sizeof(to);
          size  = lwip_recvfrom(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, (socklen_t *)&tolen);
          /* if the response size is good */
          if (size == SNTP_MSG_LEN) {
            /* if this is a SNTP response... */
            if (((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_SERVER) ||
                ((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST)) {
              /* do time processing */
              sntp_process(sntpmsg.receive_timestamp);
            } else {
              LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not response frame code\n"));
            }
          }
        } else {
          LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not sendto==%i\n", errno));
        }
      }
      /* close the socket */
      closesocket(sock);
    }
  }
}