// See the file "COPYING" in the main distribution directory for copyright. #include "bro-config.h" #include "NetVar.h" #include "NTP.h" #include "Sessions.h" #include "Event.h" #include "events.bif.h" using namespace analyzer::ntp; NTP_Analyzer::NTP_Analyzer(Connection* conn) : Analyzer("NTP", conn) { ADD_ANALYZER_TIMER(&NTP_Analyzer::ExpireTimer, network_time + ntp_session_timeout, 1, TIMER_NTP_EXPIRE); } void NTP_Analyzer::Done() { Analyzer::Done(); Event(udp_session_done); } void NTP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); // Actually we could just get rid of the Request/Reply and simply use // the code of Message(). But for now we use it as an example of how // to convert an old-style UDP analyzer. if ( is_orig ) Request(data, len); else Reply(data, len); } int NTP_Analyzer::Request(const u_char* data, int len) { Message(data, len); return 1; } int NTP_Analyzer::Reply(const u_char* data, int len) { Message(data, len); return 1; } void NTP_Analyzer::Message(const u_char* data, int len) { if ( (unsigned) len < sizeof(struct ntpdata) ) { Weird("truncated_NTP"); return; } struct ntpdata* ntp_data = (struct ntpdata *) data; len -= sizeof *ntp_data; data += sizeof *ntp_data; if ( ! ntp_message ) return; RecordVal* msg = new RecordVal(ntp_msg); unsigned int code = ntp_data->status & 0x7; msg->Assign(0, val_mgr->GetCount((unsigned int) (ntohl(ntp_data->refid)))); msg->Assign(1, val_mgr->GetCount(code)); msg->Assign(2, val_mgr->GetCount((unsigned int) ntp_data->stratum)); msg->Assign(3, val_mgr->GetCount((unsigned int) ntp_data->ppoll)); msg->Assign(4, val_mgr->GetInt((unsigned int) ntp_data->precision)); msg->Assign(5, new Val(ShortFloat(ntp_data->distance), TYPE_INTERVAL)); msg->Assign(6, new Val(ShortFloat(ntp_data->dispersion), TYPE_INTERVAL)); msg->Assign(7, new Val(LongFloat(ntp_data->reftime), TYPE_TIME)); msg->Assign(8, new Val(LongFloat(ntp_data->org), TYPE_TIME)); msg->Assign(9, new Val(LongFloat(ntp_data->rec), TYPE_TIME)); msg->Assign(10, new Val(LongFloat(ntp_data->xmt), TYPE_TIME)); ConnectionEventFast(ntp_message, { BuildConnVal(), msg, new StringVal(new BroString(data, len, 0)), }); } double NTP_Analyzer::ShortFloat(struct s_fixedpt fp) { return ConvertToDouble(ntohs(fp.int_part), ntohs(fp.fraction), 65536.0); } double NTP_Analyzer::LongFloat(struct l_fixedpt fp) { double t = ConvertToDouble(ntohl(fp.int_part), ntohl(fp.fraction), 4294967296.0); return t ? t - JAN_1970 : 0.0; } double NTP_Analyzer::ConvertToDouble(unsigned int int_part, unsigned int fraction, double frac_base) { return double(int_part) + double(fraction) / frac_base; } void NTP_Analyzer::ExpireTimer(double /* t */) { Event(connection_timeout); sessions->Remove(Conn()); }