FreeBSD/contrib/ntp/ntpdc/ntpdc.c
/*
 * sendrequest - format and send a request packet
 *
 * Historically, ntpdc has used a fixed-size request packet regardless
 * of the actual payload size.  When authenticating, the timestamp, key
 * ID, and digest have been placed just before the end of the packet.
 * With the introduction in late 2009 of support for authenticated
 * ntpdc requests using larger 20-octet digests (vs. 16 for MD5), we
 * come up four bytes short.
 *
 * To maintain interop while allowing for larger digests, the behavior
 * is unchanged when using 16-octet digests.  For larger digests, the
 * timestamp, key ID, and digest are placed immediately following the
 * request payload, with the overall packet size variable.  ntpd can
 * distinguish 16-octet digests by the overall request size being
 * REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled.  When using a
 * longer digest, that request size should be avoided.
 *
 * With the form used with 20-octet and larger digests, the timestamp,
 * key ID, and digest are located by ntpd relative to the start of the
 * packet, and the size of the digest is then implied by the packet
 * size.
 */
format and send a request packet
Historically, ntpdc has used a fixed-size request packet regardless
of the actual payload size.  When authenticating, the timestamp, key
ID, and digest have been placed just before the end of the packet.
With the introduction in late 2009 of support for authenticated
ntpdc requests using larger 20-octet digests (vs. 16 for MD5), we
come up four bytes short.

To maintain interop while allowing for larger digests, the behavior
is unchanged when using 16-octet digests.  For larger digests, the
timestamp, key ID, and digest are placed immediately following the
request payload, with the overall packet size variable.  ntpd can
distinguish 16-octet digests by the overall request size being
REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled.  When using a
longer digest, that request size should be avoided.

With the form used with 20-octet and larger digests, the timestamp,
key ID, and digest are located by ntpd relative to the start of the
packet, and the size of the digest is then implied by the packet
size.
format and send a request packet Historically ntpdc has used a fixed - size request packet regardless of the actual payload size . When authenticating the timestamp key ID and digest have been placed just before the end of the packet . With the introduction in late 2009 of support for authenticated ntpdc requests using larger 20 - octet digests ( vs . 16 for MD5 ) we come up four bytes short . To maintain interop while allowing for larger digests the behavior is unchanged when using 16 - octet digests . For larger digests the timestamp key ID and digest are placed immediately following the request payload with the overall packet size variable . ntpd can distinguish 16 - octet digests by the overall request size being REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled . When using a longer digest that request size should be avoided . With the form used with 20 - octet and larger digests the timestamp key ID and digest are located by ntpd relative to the start of the packet and the size of the digest is then implied by the packet size .
static int
sendrequest(
	int implcode,
	int reqcode,
	int auth,
	size_t qitems,
	size_t qsize,
	const char *qdata
	)
{
	struct req_pkt qpkt;
	size_t	datasize;
	size_t	reqsize;
	u_long	key_id;
	l_fp	ts;
	l_fp *	ptstamp;
	size_t	maclen;
	char *	pass;
	ZERO(qpkt);
	qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
	qpkt.implementation = (u_char)implcode;
	qpkt.request = (u_char)reqcode;
	datasize = qitems * qsize;
	if (datasize && qdata != NULL) {
		memcpy(qpkt.u.data, qdata, datasize);
		qpkt.err_nitems = ERR_NITEMS(0, qitems);
		qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);
	} else {
		qpkt.err_nitems = ERR_NITEMS(0, 0);
		qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);  
	}
	if (!auth || (keyid_entered && info_auth_keyid == 0)) {
		qpkt.auth_seq = AUTH_SEQ(0, 0);
		return sendpkt(&qpkt, req_pkt_size);
	}
	if (info_auth_keyid == 0) {
		key_id = getkeyid("Keyid: ");
		if (!key_id) {
			fprintf(stderr, "Invalid key identifier\n");
			return 1;
		}
		info_auth_keyid = key_id;
	}
	if (!authistrusted(info_auth_keyid)) {
		pass = getpass_keytype(info_auth_keytype);
		if ('\0' == pass[0]) {
			fprintf(stderr, "Invalid password\n");
			return 1;
		}
		authusekey(info_auth_keyid, info_auth_keytype,
			   (u_char *)pass);
		authtrust(info_auth_keyid, 1);
	}
	qpkt.auth_seq = AUTH_SEQ(1, 0);
	if (info_auth_hashlen > 16) {
		if (REQ_LEN_NOMAC != req_pkt_size)
			return 1;
		reqsize = REQ_LEN_HDR + datasize + sizeof(*ptstamp);
		reqsize = (reqsize + 3) & ~3;
	} else
		reqsize = req_pkt_size;
	ptstamp = (void *)((char *)&qpkt + reqsize);
	ptstamp--;
	get_systime(&ts);
	L_ADD(&ts, &delay_time);
	HTONL_FP(&ts, ptstamp);
	maclen = authencrypt(
		info_auth_keyid, (void *)&qpkt, size2int_chk(reqsize));
	if (!maclen) {  
		fprintf(stderr, "Key not found\n");
		return 1;
	} else if (maclen != (int)(info_auth_hashlen + sizeof(keyid_t))) {
		fprintf(stderr,
			"%zu octet MAC, %zu expected with %zu octet digest\n",
			maclen, (info_auth_hashlen + sizeof(keyid_t)),
			info_auth_hashlen);
		return 1;
	}
	return sendpkt(&qpkt, reqsize + maclen);
}
static int sendrequest ( int implcode , int reqcode , int auth , size_t qitems , size_t qsize , const char * qdata ) { struct req_pkt qpkt ; size_t datasize ; size_t reqsize ; u_long key_id ; l_fp ts ; l_fp * ptstamp ; size_t maclen ; char * pass ; ZERO ( qpkt ) ; qpkt . rm_vn_mode = RM_VN_MODE ( 0 , 0 , 0 ) ; qpkt . implementation = ( u_char ) implcode ; qpkt . request = ( u_char ) reqcode ; datasize = qitems * qsize ; if ( datasize && qdata != NULL ) { memcpy ( qpkt . u . data , qdata , datasize ) ; qpkt . err_nitems = ERR_NITEMS ( 0 , qitems ) ; qpkt . mbz_itemsize = MBZ_ITEMSIZE ( qsize ) ; } else { qpkt . err_nitems = ERR_NITEMS ( 0 , 0 ) ; qpkt . mbz_itemsize = MBZ_ITEMSIZE ( qsize ) ; } if ( ! auth || ( keyid_entered && info_auth_keyid == 0 ) ) { qpkt . auth_seq = AUTH_SEQ ( 0 , 0 ) ; return sendpkt ( & qpkt , req_pkt_size ) ; } if ( info_auth_keyid == 0 ) { key_id = getkeyid ( " " ) ; if ( ! key_id ) { fprintf ( stderr , " \n " ) ; return 1 ; } info_auth_keyid = key_id ; } if ( ! authistrusted ( info_auth_keyid ) ) { pass = getpass_keytype ( info_auth_keytype ) ; if ( ' \0 ' == pass [ 0 ] ) { fprintf ( stderr , " \n " ) ; return 1 ; } authusekey ( info_auth_keyid , info_auth_keytype , ( u_char * ) pass ) ; authtrust ( info_auth_keyid , 1 ) ; } qpkt . auth_seq = AUTH_SEQ ( 1 , 0 ) ; if ( info_auth_hashlen > 16 ) { if ( REQ_LEN_NOMAC != req_pkt_size ) return 1 ; reqsize = REQ_LEN_HDR + datasize + sizeof ( * ptstamp ) ; reqsize = ( reqsize + 3 ) & ~ 3 ; } else reqsize = req_pkt_size ; ptstamp = ( void * ) ( ( char * ) & qpkt + reqsize ) ; ptstamp -- ; get_systime ( & ts ) ; L_ADD ( & ts , & delay_time ) ; HTONL_FP ( & ts , ptstamp ) ; maclen = authencrypt ( info_auth_keyid , ( void * ) & qpkt , size2int_chk ( reqsize ) ) ; if ( ! maclen ) { fprintf ( stderr , " \n " ) ; return 1 ; } else if ( maclen != ( int ) ( info_auth_hashlen + sizeof ( keyid_t ) ) ) { fprintf ( stderr , " \n " , maclen , ( info_auth_hashlen + sizeof ( keyid_t ) ) , info_auth_hashlen ) ; return 1 ; } return sendpkt ( & qpkt , reqsize + maclen ) ; }
sendrequest - format and send a request packet
 Historically, ntpdc has used a fixed-size request packet regardless
 of the actual payload size.
sendrequest - format and send a request packet Historically ntpdc has used a fixed - size request packet regardless of the actual payload size .
/* allow for optional first item */ /*
		 * Only ntpd which expects REQ_LEN_NOMAC plus maclen
		 * octets in an authenticated request using a 16 octet
		 * digest (that is, a newer ntpd) will handle digests
		 * larger than 16 octets, so for longer digests, do
		 * not attempt to shorten the requests for downlevel
		 * ntpd compatibility.
		 */ /* align to 32 bits */