Blame pmc.c

Packit 9c3e7e
/**
Packit 9c3e7e
 * @file pmc.c
Packit 9c3e7e
 * @brief PTP management client program
Packit 9c3e7e
 * @note Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
Packit 9c3e7e
 *
Packit 9c3e7e
 * This program is free software; you can redistribute it and/or modify
Packit 9c3e7e
 * it under the terms of the GNU General Public License as published by
Packit 9c3e7e
 * the Free Software Foundation; either version 2 of the License, or
Packit 9c3e7e
 * (at your option) any later version.
Packit 9c3e7e
 *
Packit 9c3e7e
 * This program is distributed in the hope that it will be useful,
Packit 9c3e7e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9c3e7e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 9c3e7e
 * GNU General Public License for more details.
Packit 9c3e7e
 *
Packit 9c3e7e
 * You should have received a copy of the GNU General Public License along
Packit 9c3e7e
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit 9c3e7e
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 9c3e7e
 */
Packit 9c3e7e
#include <errno.h>
Packit 9c3e7e
#include <poll.h>
Packit 9c3e7e
#include <stdio.h>
Packit 9c3e7e
#include <stdlib.h>
Packit 9c3e7e
#include <string.h>
Packit 9c3e7e
#include <unistd.h>
Packit 9c3e7e
#include <inttypes.h>
Packit 9c3e7e
#include <arpa/inet.h>
Packit 9c3e7e
Packit 9c3e7e
#include "ds.h"
Packit 9c3e7e
#include "fsm.h"
Packit 9c3e7e
#include "pmc_common.h"
Packit 9c3e7e
#include "print.h"
Packit 9c3e7e
#include "tlv.h"
Packit 9c3e7e
#include "uds.h"
Packit 9c3e7e
#include "util.h"
Packit 9c3e7e
#include "version.h"
Packit 9c3e7e
Packit 9c3e7e
static struct pmc *pmc;
Packit 9c3e7e
Packit 9c3e7e
#define IFMT "\n\t\t"
Packit 9c3e7e
Packit 9c3e7e
static char *text2str(struct PTPText *text)
Packit 9c3e7e
{
Packit 9c3e7e
	static struct static_ptp_text s;
Packit 9c3e7e
	s.max_symbols = -1;
Packit 9c3e7e
	static_ptp_text_copy(&s, text);
Packit 9c3e7e
	return (char*)(s.text);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static char *bin2str(Octet *data, int len)
Packit 9c3e7e
{
Packit 9c3e7e
	static char buf[BIN_BUF_SIZE];
Packit 9c3e7e
	return bin2str_impl(data, len, buf, sizeof(buf));
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void pmc_show(struct ptp_message *msg, FILE *fp)
Packit 9c3e7e
{
Packit 9c3e7e
	int action;
Packit 9c3e7e
	struct TLV *tlv;
Packit 9c3e7e
	struct management_tlv *mgt;
Packit 9c3e7e
	struct management_tlv_datum *mtd;
Packit 9c3e7e
	struct defaultDS *dds;
Packit 9c3e7e
	struct currentDS *cds;
Packit 9c3e7e
	struct parentDS *pds;
Packit 9c3e7e
	struct timePropertiesDS *tp;
Packit 9c3e7e
	struct time_status_np *tsn;
Packit 9c3e7e
	struct grandmaster_settings_np *gsn;
Packit 9c3e7e
	struct mgmt_clock_description *cd;
Packit 9c3e7e
	struct tlv_extra *extra;
Packit 9c3e7e
	struct portDS *p;
Packit 9c3e7e
	struct port_ds_np *pnp;
Packit 9c3e7e
Packit 9c3e7e
	if (msg_type(msg) != MANAGEMENT) {
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
	action = management_action(msg);
Packit 9c3e7e
	if (action < GET || action > ACKNOWLEDGE) {
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
	fprintf(fp, "\t%s seq %hu %s ",
Packit 9c3e7e
		pid2str(&msg->header.sourcePortIdentity),
Packit 9c3e7e
		msg->header.sequenceId, pmc_action_string(action));
Packit 9c3e7e
	if (msg_tlv_count(msg) != 1) {
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	extra = TAILQ_FIRST(&msg->tlv_list);
Packit 9c3e7e
	tlv = (struct TLV *) msg->management.suffix;
Packit 9c3e7e
	if (tlv->type == TLV_MANAGEMENT) {
Packit 9c3e7e
		fprintf(fp, "MANAGEMENT ");
Packit 9c3e7e
	} else if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS) {
Packit 9c3e7e
		fprintf(fp, "MANAGEMENT_ERROR_STATUS ");
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	} else {
Packit 9c3e7e
		fprintf(fp, "unknown-tlv ");
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	mgt = (struct management_tlv *) msg->management.suffix;
Packit 9c3e7e
	if (mgt->length == 2 && mgt->id != TLV_NULL_MANAGEMENT) {
Packit 9c3e7e
		fprintf(fp, "empty-tlv ");
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	switch (mgt->id) {
Packit 9c3e7e
	case TLV_CLOCK_DESCRIPTION:
Packit 9c3e7e
		cd = &extra->cd;
Packit 9c3e7e
		fprintf(fp, "CLOCK_DESCRIPTION "
Packit 9c3e7e
			IFMT "clockType             0x%hx"
Packit 9c3e7e
			IFMT "physicalLayerProtocol %s"
Packit 9c3e7e
			IFMT "physicalAddress       %s"
Packit 9c3e7e
			IFMT "protocolAddress       %hu %s",
Packit 9c3e7e
			align16(cd->clockType),
Packit 9c3e7e
			text2str(cd->physicalLayerProtocol),
Packit 9c3e7e
			bin2str(cd->physicalAddress->address,
Packit 9c3e7e
				align16(&cd->physicalAddress->length)),
Packit 9c3e7e
			align16(&cd->protocolAddress->networkProtocol),
Packit 9c3e7e
			portaddr2str(cd->protocolAddress));
Packit 9c3e7e
		fprintf(fp, IFMT "manufacturerId        %s"
Packit 9c3e7e
			IFMT "productDescription    %s",
Packit 9c3e7e
			bin2str(cd->manufacturerIdentity, OUI_LEN),
Packit 9c3e7e
			text2str(cd->productDescription));
Packit 9c3e7e
		fprintf(fp, IFMT "revisionData          %s",
Packit 9c3e7e
			text2str(cd->revisionData));
Packit 9c3e7e
		fprintf(fp, IFMT "userDescription       %s"
Packit 9c3e7e
			IFMT "profileId             %s",
Packit 9c3e7e
			text2str(cd->userDescription),
Packit 9c3e7e
			bin2str(cd->profileIdentity, PROFILE_ID_LEN));
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_USER_DESCRIPTION:
Packit 9c3e7e
		fprintf(fp, "USER_DESCRIPTION "
Packit 9c3e7e
			IFMT "userDescription  %s",
Packit 9c3e7e
			text2str(extra->cd.userDescription));
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_DEFAULT_DATA_SET:
Packit 9c3e7e
		dds = (struct defaultDS *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "DEFAULT_DATA_SET "
Packit 9c3e7e
			IFMT "twoStepFlag             %d"
Packit 9c3e7e
			IFMT "slaveOnly               %d"
Packit 9c3e7e
			IFMT "numberPorts             %hu"
Packit 9c3e7e
			IFMT "priority1               %hhu"
Packit 9c3e7e
			IFMT "clockClass              %hhu"
Packit 9c3e7e
			IFMT "clockAccuracy           0x%02hhx"
Packit 9c3e7e
			IFMT "offsetScaledLogVariance 0x%04hx"
Packit 9c3e7e
			IFMT "priority2               %hhu"
Packit 9c3e7e
			IFMT "clockIdentity           %s"
Packit 9c3e7e
			IFMT "domainNumber            %hhu",
Packit 9c3e7e
			dds->flags & DDS_TWO_STEP_FLAG ? 1 : 0,
Packit 9c3e7e
			dds->flags & DDS_SLAVE_ONLY ? 1 : 0,
Packit 9c3e7e
			dds->numberPorts,
Packit 9c3e7e
			dds->priority1,
Packit 9c3e7e
			dds->clockQuality.clockClass,
Packit 9c3e7e
			dds->clockQuality.clockAccuracy,
Packit 9c3e7e
			dds->clockQuality.offsetScaledLogVariance,
Packit 9c3e7e
			dds->priority2,
Packit 9c3e7e
			cid2str(&dds->clockIdentity),
Packit 9c3e7e
			dds->domainNumber);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_CURRENT_DATA_SET:
Packit 9c3e7e
		cds = (struct currentDS *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "CURRENT_DATA_SET "
Packit 9c3e7e
			IFMT "stepsRemoved     %hd"
Packit 9c3e7e
			IFMT "offsetFromMaster %.1f"
Packit 9c3e7e
			IFMT "meanPathDelay    %.1f",
Packit 9c3e7e
			cds->stepsRemoved, cds->offsetFromMaster / 65536.0,
Packit 9c3e7e
			cds->meanPathDelay / 65536.0);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_PARENT_DATA_SET:
Packit 9c3e7e
		pds = (struct parentDS *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "PARENT_DATA_SET "
Packit 9c3e7e
			IFMT "parentPortIdentity                    %s"
Packit 9c3e7e
			IFMT "parentStats                           %hhu"
Packit 9c3e7e
			IFMT "observedParentOffsetScaledLogVariance 0x%04hx"
Packit 9c3e7e
			IFMT "observedParentClockPhaseChangeRate    0x%08x"
Packit 9c3e7e
			IFMT "grandmasterPriority1                  %hhu"
Packit 9c3e7e
			IFMT "gm.ClockClass                         %hhu"
Packit 9c3e7e
			IFMT "gm.ClockAccuracy                      0x%02hhx"
Packit 9c3e7e
			IFMT "gm.OffsetScaledLogVariance            0x%04hx"
Packit 9c3e7e
			IFMT "grandmasterPriority2                  %hhu"
Packit 9c3e7e
			IFMT "grandmasterIdentity                   %s",
Packit 9c3e7e
			pid2str(&pds->parentPortIdentity),
Packit 9c3e7e
			pds->parentStats,
Packit 9c3e7e
			pds->observedParentOffsetScaledLogVariance,
Packit 9c3e7e
			pds->observedParentClockPhaseChangeRate,
Packit 9c3e7e
			pds->grandmasterPriority1,
Packit 9c3e7e
			pds->grandmasterClockQuality.clockClass,
Packit 9c3e7e
			pds->grandmasterClockQuality.clockAccuracy,
Packit 9c3e7e
			pds->grandmasterClockQuality.offsetScaledLogVariance,
Packit 9c3e7e
			pds->grandmasterPriority2,
Packit 9c3e7e
			cid2str(&pds->grandmasterIdentity));
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_TIME_PROPERTIES_DATA_SET:
Packit 9c3e7e
		tp = (struct timePropertiesDS *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "TIME_PROPERTIES_DATA_SET "
Packit 9c3e7e
			IFMT "currentUtcOffset      %hd"
Packit 9c3e7e
			IFMT "leap61                %d"
Packit 9c3e7e
			IFMT "leap59                %d"
Packit 9c3e7e
			IFMT "currentUtcOffsetValid %d"
Packit 9c3e7e
			IFMT "ptpTimescale          %d"
Packit 9c3e7e
			IFMT "timeTraceable         %d"
Packit 9c3e7e
			IFMT "frequencyTraceable    %d"
Packit 9c3e7e
			IFMT "timeSource            0x%02hhx",
Packit 9c3e7e
			tp->currentUtcOffset,
Packit 9c3e7e
			tp->flags & LEAP_61 ? 1 : 0,
Packit 9c3e7e
			tp->flags & LEAP_59 ? 1 : 0,
Packit 9c3e7e
			tp->flags & UTC_OFF_VALID ? 1 : 0,
Packit 9c3e7e
			tp->flags & PTP_TIMESCALE ? 1 : 0,
Packit 9c3e7e
			tp->flags & TIME_TRACEABLE ? 1 : 0,
Packit 9c3e7e
			tp->flags & FREQ_TRACEABLE ? 1 : 0,
Packit 9c3e7e
			tp->timeSource);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_PRIORITY1:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "PRIORITY1 "
Packit 9c3e7e
			IFMT "priority1 %hhu", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_PRIORITY2:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "PRIORITY2 "
Packit 9c3e7e
			IFMT "priority2 %hhu", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_DOMAIN:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "DOMAIN "
Packit 9c3e7e
			IFMT "domainNumber %hhu", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_SLAVE_ONLY:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "SLAVE_ONLY "
Packit 9c3e7e
			IFMT "slaveOnly %d", mtd->val & DDS_SLAVE_ONLY ? 1 : 0);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_CLOCK_ACCURACY:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "CLOCK_ACCURACY "
Packit 9c3e7e
			IFMT "clockAccuracy 0x%02hhx", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_TRACEABILITY_PROPERTIES:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "TRACEABILITY_PROPERTIES "
Packit 9c3e7e
			IFMT "timeTraceable      %d"
Packit 9c3e7e
			IFMT "frequencyTraceable %d",
Packit 9c3e7e
			mtd->val & TIME_TRACEABLE ? 1 : 0,
Packit 9c3e7e
			mtd->val & FREQ_TRACEABLE ? 1 : 0);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_TIMESCALE_PROPERTIES:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "TIMESCALE_PROPERTIES "
Packit 9c3e7e
			IFMT "ptpTimescale %d", mtd->val & PTP_TIMESCALE ? 1 : 0);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_TIME_STATUS_NP:
Packit 9c3e7e
		tsn = (struct time_status_np *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "TIME_STATUS_NP "
Packit 9c3e7e
			IFMT "master_offset              %" PRId64
Packit 9c3e7e
			IFMT "ingress_time               %" PRId64
Packit 9c3e7e
			IFMT "cumulativeScaledRateOffset %+.9f"
Packit 9c3e7e
			IFMT "scaledLastGmPhaseChange    %d"
Packit 9c3e7e
			IFMT "gmTimeBaseIndicator        %hu"
Packit 9c3e7e
			IFMT "lastGmPhaseChange          0x%04hx'%016" PRIx64 ".%04hx"
Packit 9c3e7e
			IFMT "gmPresent                  %s"
Packit 9c3e7e
			IFMT "gmIdentity                 %s",
Packit 9c3e7e
			tsn->master_offset,
Packit 9c3e7e
			tsn->ingress_time,
Packit 9c3e7e
			(tsn->cumulativeScaledRateOffset + 0.0) / P41,
Packit 9c3e7e
			tsn->scaledLastGmPhaseChange,
Packit 9c3e7e
			tsn->gmTimeBaseIndicator,
Packit 9c3e7e
			tsn->lastGmPhaseChange.nanoseconds_msb,
Packit 9c3e7e
			tsn->lastGmPhaseChange.nanoseconds_lsb,
Packit 9c3e7e
			tsn->lastGmPhaseChange.fractional_nanoseconds,
Packit 9c3e7e
			tsn->gmPresent ? "true" : "false",
Packit 9c3e7e
			cid2str(&tsn->gmIdentity));
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_GRANDMASTER_SETTINGS_NP:
Packit 9c3e7e
		gsn = (struct grandmaster_settings_np *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "GRANDMASTER_SETTINGS_NP "
Packit 9c3e7e
			IFMT "clockClass              %hhu"
Packit 9c3e7e
			IFMT "clockAccuracy           0x%02hhx"
Packit 9c3e7e
			IFMT "offsetScaledLogVariance 0x%04hx"
Packit 9c3e7e
			IFMT "currentUtcOffset        %hd"
Packit 9c3e7e
			IFMT "leap61                  %d"
Packit 9c3e7e
			IFMT "leap59                  %d"
Packit 9c3e7e
			IFMT "currentUtcOffsetValid   %d"
Packit 9c3e7e
			IFMT "ptpTimescale            %d"
Packit 9c3e7e
			IFMT "timeTraceable           %d"
Packit 9c3e7e
			IFMT "frequencyTraceable      %d"
Packit 9c3e7e
			IFMT "timeSource              0x%02hhx",
Packit 9c3e7e
			gsn->clockQuality.clockClass,
Packit 9c3e7e
			gsn->clockQuality.clockAccuracy,
Packit 9c3e7e
			gsn->clockQuality.offsetScaledLogVariance,
Packit 9c3e7e
			gsn->utc_offset,
Packit 9c3e7e
			gsn->time_flags & LEAP_61 ? 1 : 0,
Packit 9c3e7e
			gsn->time_flags & LEAP_59 ? 1 : 0,
Packit 9c3e7e
			gsn->time_flags & UTC_OFF_VALID ? 1 : 0,
Packit 9c3e7e
			gsn->time_flags & PTP_TIMESCALE ? 1 : 0,
Packit 9c3e7e
			gsn->time_flags & TIME_TRACEABLE ? 1 : 0,
Packit 9c3e7e
			gsn->time_flags & FREQ_TRACEABLE ? 1 : 0,
Packit 9c3e7e
			gsn->time_source);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_PORT_DATA_SET:
Packit 9c3e7e
		p = (struct portDS *) mgt->data;
Packit 9c3e7e
		if (p->portState > PS_SLAVE) {
Packit 9c3e7e
			p->portState = 0;
Packit 9c3e7e
		}
Packit 9c3e7e
		fprintf(fp, "PORT_DATA_SET "
Packit 9c3e7e
			IFMT "portIdentity            %s"
Packit 9c3e7e
			IFMT "portState               %s"
Packit 9c3e7e
			IFMT "logMinDelayReqInterval  %hhd"
Packit 9c3e7e
			IFMT "peerMeanPathDelay       %" PRId64
Packit 9c3e7e
			IFMT "logAnnounceInterval     %hhd"
Packit 9c3e7e
			IFMT "announceReceiptTimeout  %hhu"
Packit 9c3e7e
			IFMT "logSyncInterval         %hhd"
Packit 9c3e7e
			IFMT "delayMechanism          %hhu"
Packit 9c3e7e
			IFMT "logMinPdelayReqInterval %hhd"
Packit 9c3e7e
			IFMT "versionNumber           %hhu",
Packit 9c3e7e
			pid2str(&p->portIdentity), ps_str[p->portState],
Packit 9c3e7e
			p->logMinDelayReqInterval, p->peerMeanPathDelay >> 16,
Packit 9c3e7e
			p->logAnnounceInterval, p->announceReceiptTimeout,
Packit 9c3e7e
			p->logSyncInterval, p->delayMechanism,
Packit 9c3e7e
			p->logMinPdelayReqInterval, p->versionNumber);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_PORT_DATA_SET_NP:
Packit 9c3e7e
		pnp = (struct port_ds_np *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "PORT_DATA_SET_NP "
Packit 9c3e7e
			IFMT "neighborPropDelayThresh %u"
Packit 9c3e7e
			IFMT "asCapable               %d",
Packit 9c3e7e
			pnp->neighborPropDelayThresh,
Packit 9c3e7e
			pnp->asCapable ? 1 : 0);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_LOG_ANNOUNCE_INTERVAL:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "LOG_ANNOUNCE_INTERVAL "
Packit 9c3e7e
			IFMT "logAnnounceInterval %hhd", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_ANNOUNCE_RECEIPT_TIMEOUT:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "ANNOUNCE_RECEIPT_TIMEOUT "
Packit 9c3e7e
			IFMT "announceReceiptTimeout %hhu", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_LOG_SYNC_INTERVAL:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "LOG_SYNC_INTERVAL "
Packit 9c3e7e
			IFMT "logSyncInterval %hhd", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_VERSION_NUMBER:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "VERSION_NUMBER "
Packit 9c3e7e
			IFMT "versionNumber %hhu", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_DELAY_MECHANISM:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "DELAY_MECHANISM "
Packit 9c3e7e
			IFMT "delayMechanism %hhu", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	case TLV_LOG_MIN_PDELAY_REQ_INTERVAL:
Packit 9c3e7e
		mtd = (struct management_tlv_datum *) mgt->data;
Packit 9c3e7e
		fprintf(fp, "LOG_MIN_PDELAY_REQ_INTERVAL "
Packit 9c3e7e
			IFMT "logMinPdelayReqInterval %hhd", mtd->val);
Packit 9c3e7e
		break;
Packit 9c3e7e
	}
Packit 9c3e7e
out:
Packit 9c3e7e
	fprintf(fp, "\n");
Packit 9c3e7e
	fflush(fp);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void usage(char *progname)
Packit 9c3e7e
{
Packit 9c3e7e
	fprintf(stderr,
Packit 9c3e7e
		"\nusage: %s [options] [commands]\n\n"
Packit 9c3e7e
		" Network Transport\n\n"
Packit 9c3e7e
		" -2        IEEE 802.3\n"
Packit 9c3e7e
		" -4        UDP IPV4 (default)\n"
Packit 9c3e7e
		" -6        UDP IPV6\n"
Packit 9c3e7e
		" -u        UDS local\n\n"
Packit 9c3e7e
		" Other Options\n\n"
Packit 9c3e7e
		" -b [num]  boundary hops, default 1\n"
Packit 9c3e7e
		" -d [num]  domain number, default 0\n"
Packit 9c3e7e
		" -f [file] read configuration from 'file'\n"
Packit 9c3e7e
		" -h        prints this message and exits\n"
Packit 9c3e7e
		" -i [dev]  interface device to use, default 'eth0'\n"
Packit 9c3e7e
		"           for network and '/var/run/pmc.$pid' for UDS.\n"
Packit 9c3e7e
		" -s [path] server address for UDS, default '/var/run/ptp4l'.\n"
Packit 9c3e7e
		" -t [hex]  transport specific field, default 0x0\n"
Packit 9c3e7e
		" -v        prints the software version and exits\n"
Packit 9c3e7e
		" -z        send zero length TLV values with the GET actions\n"
Packit 9c3e7e
		"\n",
Packit 9c3e7e
		progname);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int main(int argc, char *argv[])
Packit 9c3e7e
{
Packit 9c3e7e
	const char *iface_name = NULL;
Packit 9c3e7e
	char *config = NULL, *progname;
Packit 9c3e7e
	int c, cnt, index, length, tmo = -1, batch_mode = 0, zero_datalen = 0;
Packit 9c3e7e
	int ret = 0;
Packit 9c3e7e
	char line[1024], *command = NULL, uds_local[MAX_IFNAME_SIZE + 1];
Packit 9c3e7e
	enum transport_type transport_type = TRANS_UDP_IPV4;
Packit 9c3e7e
	UInteger8 boundary_hops = 1, domain_number = 0, transport_specific = 0;
Packit 9c3e7e
	struct ptp_message *msg;
Packit 9c3e7e
	struct option *opts;
Packit 9c3e7e
	struct config *cfg;
Packit 9c3e7e
#define N_FD 2
Packit 9c3e7e
	struct pollfd pollfd[N_FD];
Packit 9c3e7e
Packit 9c3e7e
	handle_term_signals();
Packit 9c3e7e
Packit 9c3e7e
	cfg = config_create();
Packit 9c3e7e
	if (!cfg) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	opts = config_long_options(cfg);
Packit 9c3e7e
Packit 9c3e7e
	/* Process the command line arguments. */
Packit 9c3e7e
	progname = strrchr(argv[0], '/');
Packit 9c3e7e
	progname = progname ? 1+progname : argv[0];
Packit 9c3e7e
	while (EOF != (c = getopt_long(argc, argv, "246u""b:d:f:hi:s:t:vz",
Packit 9c3e7e
				       opts, &index))) {
Packit 9c3e7e
		switch (c) {
Packit 9c3e7e
		case 0:
Packit 9c3e7e
			if (config_parse_option(cfg, opts[index].name, optarg)) {
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case '2':
Packit 9c3e7e
			if (config_set_int(cfg, "network_transport", TRANS_IEEE_802_3)) {
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case '4':
Packit 9c3e7e
			if (config_set_int(cfg, "network_transport", TRANS_UDP_IPV4)) {
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case '6':
Packit 9c3e7e
			if (config_set_int(cfg, "network_transport", TRANS_UDP_IPV6)) {
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'u':
Packit 9c3e7e
			if (config_set_int(cfg, "network_transport", TRANS_UDS)) {
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'b':
Packit 9c3e7e
			boundary_hops = atoi(optarg);
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'd':
Packit 9c3e7e
			if (config_set_int(cfg, "domainNumber", atoi(optarg))) {
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'f':
Packit 9c3e7e
			config = optarg;
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'i':
Packit 9c3e7e
			iface_name = optarg;
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 's':
Packit 9c3e7e
			if (strlen(optarg) > MAX_IFNAME_SIZE) {
Packit 9c3e7e
				fprintf(stderr, "path %s too long, max is %d\n",
Packit 9c3e7e
					optarg, MAX_IFNAME_SIZE);
Packit 9c3e7e
				config_destroy(cfg);
Packit 9c3e7e
				return -1;
Packit 9c3e7e
			}
Packit 9c3e7e
			if (config_set_string(cfg, "uds_address", optarg)) {
Packit 9c3e7e
				config_destroy(cfg);
Packit 9c3e7e
				return -1;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 't':
Packit 9c3e7e
			if (1 == sscanf(optarg, "%x", &c)) {
Packit 9c3e7e
				if (config_set_int(cfg, "transportSpecific", c)) {
Packit 9c3e7e
					ret = -1;
Packit 9c3e7e
					goto out;
Packit 9c3e7e
				}
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'v':
Packit 9c3e7e
			version_show(stdout);
Packit 9c3e7e
			config_destroy(cfg);
Packit 9c3e7e
			return 0;
Packit 9c3e7e
		case 'z':
Packit 9c3e7e
			zero_datalen = 1;
Packit 9c3e7e
			break;
Packit 9c3e7e
		case 'h':
Packit 9c3e7e
			usage(progname);
Packit 9c3e7e
			config_destroy(cfg);
Packit 9c3e7e
			return 0;
Packit 9c3e7e
		case '?':
Packit 9c3e7e
		default:
Packit 9c3e7e
			usage(progname);
Packit 9c3e7e
			config_destroy(cfg);
Packit 9c3e7e
			return -1;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (config && (c = config_read(config, cfg))) {
Packit 9c3e7e
		config_destroy(cfg);
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	transport_type = config_get_int(cfg, NULL, "network_transport");
Packit 9c3e7e
	transport_specific = config_get_int(cfg, NULL, "transportSpecific") << 4;
Packit 9c3e7e
	domain_number = config_get_int(cfg, NULL, "domainNumber");
Packit 9c3e7e
Packit 9c3e7e
	if (!iface_name) {
Packit 9c3e7e
		if (transport_type == TRANS_UDS) {
Packit 9c3e7e
			snprintf(uds_local, sizeof(uds_local),
Packit 9c3e7e
				 "/var/run/pmc.%d", getpid());
Packit 9c3e7e
			iface_name = uds_local;
Packit 9c3e7e
		} else {
Packit 9c3e7e
			iface_name = "eth0";
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	if (optind < argc) {
Packit 9c3e7e
		batch_mode = 1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	print_set_progname(progname);
Packit 9c3e7e
	print_set_syslog(1);
Packit 9c3e7e
	print_set_verbose(1);
Packit 9c3e7e
Packit 9c3e7e
	pmc = pmc_create(cfg, transport_type, iface_name, boundary_hops,
Packit 9c3e7e
			 domain_number, transport_specific, zero_datalen);
Packit 9c3e7e
	if (!pmc) {
Packit 9c3e7e
		fprintf(stderr, "failed to create pmc\n");
Packit 9c3e7e
		config_destroy(cfg);
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	pollfd[0].fd = batch_mode ? -1 : STDIN_FILENO;
Packit 9c3e7e
	pollfd[1].fd = pmc_get_transport_fd(pmc);
Packit 9c3e7e
Packit 9c3e7e
	while (is_running()) {
Packit 9c3e7e
		if (batch_mode && !command) {
Packit 9c3e7e
			if (optind < argc) {
Packit 9c3e7e
				command = argv[optind++];
Packit 9c3e7e
			} else {
Packit 9c3e7e
				/* No more commands, wait a bit for
Packit 9c3e7e
				   any outstanding replies and exit. */
Packit 9c3e7e
				tmo = 100;
Packit 9c3e7e
			}
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
		pollfd[0].events = 0;
Packit 9c3e7e
		pollfd[1].events = POLLIN | POLLPRI;
Packit 9c3e7e
Packit 9c3e7e
		if (!batch_mode && !command)
Packit 9c3e7e
			pollfd[0].events |= POLLIN | POLLPRI;
Packit 9c3e7e
		if (command)
Packit 9c3e7e
			pollfd[1].events |= POLLOUT;
Packit 9c3e7e
Packit 9c3e7e
		cnt = poll(pollfd, N_FD, tmo);
Packit 9c3e7e
		if (cnt < 0) {
Packit 9c3e7e
			if (EINTR == errno) {
Packit 9c3e7e
				continue;
Packit 9c3e7e
			} else {
Packit 9c3e7e
				pr_emerg("poll failed");
Packit 9c3e7e
				ret = -1;
Packit 9c3e7e
				break;
Packit 9c3e7e
			}
Packit 9c3e7e
		} else if (!cnt) {
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
		if (pollfd[0].revents & POLLHUP) {
Packit 9c3e7e
			if (tmo == -1) {
Packit 9c3e7e
				/* Wait a bit longer for outstanding replies. */
Packit 9c3e7e
				tmo = 100;
Packit 9c3e7e
				pollfd[0].fd = -1;
Packit 9c3e7e
				pollfd[0].events = 0;
Packit 9c3e7e
			} else {
Packit 9c3e7e
				break;
Packit 9c3e7e
			}
Packit 9c3e7e
		}
Packit 9c3e7e
		if (pollfd[0].revents & (POLLIN|POLLPRI)) {
Packit 9c3e7e
			if (!fgets(line, sizeof(line), stdin)) {
Packit 9c3e7e
				break;
Packit 9c3e7e
			}
Packit 9c3e7e
			length = strlen(line);
Packit 9c3e7e
			if (length < 2) {
Packit 9c3e7e
				continue;
Packit 9c3e7e
			}
Packit 9c3e7e
			line[length - 1] = 0;
Packit 9c3e7e
			command = line;
Packit 9c3e7e
		}
Packit 9c3e7e
		if (pollfd[1].revents & POLLOUT) {
Packit 9c3e7e
			if (pmc_do_command(pmc, command)) {
Packit 9c3e7e
				fprintf(stderr, "bad command: %s\n", command);
Packit 9c3e7e
			}
Packit 9c3e7e
			command = NULL;
Packit 9c3e7e
		}
Packit 9c3e7e
		if (pollfd[1].revents & (POLLIN|POLLPRI)) {
Packit 9c3e7e
			msg = pmc_recv(pmc);
Packit 9c3e7e
			if (msg) {
Packit 9c3e7e
				pmc_show(msg, stdout);
Packit 9c3e7e
				msg_put(msg);
Packit 9c3e7e
			}
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	pmc_destroy(pmc);
Packit 9c3e7e
	msg_cleanup();
Packit 9c3e7e
Packit 9c3e7e
out:
Packit 9c3e7e
	config_destroy(cfg);
Packit 9c3e7e
	return ret;
Packit 9c3e7e
}