2 #include <netinet/tcp.h>
4 #include "asn1/asn1_message.h"
5 #include "der_encoder.h"
6 #include "ipuptanesecondary.h"
7 #include "logging/logging.h"
13 Uptane::SecondaryInterface::Ptr IpUptaneSecondary::connectAndCreate(
const std::string& address,
unsigned short port) {
14 LOG_INFO <<
"Connecting to and getting info about IP Secondary: " << address <<
":" << port <<
"...";
18 if (con_sock.connect() == 0) {
19 LOG_INFO <<
"Connected to IP Secondary: "
20 <<
"(" << address <<
":" << port <<
")";
22 LOG_WARNING <<
"Failed to connect to a secondary: " << std::strerror(errno);
26 return create(address, port, *con_sock);
29 Uptane::SecondaryInterface::Ptr IpUptaneSecondary::create(
const std::string& address,
unsigned short port,
int con_fd) {
31 req->present(AKIpUptaneMes_PR_getInfoReq);
33 auto m = req->getInfoReq();
35 auto resp = Asn1Rpc(req, con_fd);
37 if (resp->present() != AKIpUptaneMes_PR_getInfoResp) {
38 LOG_ERROR <<
"Failed to get info response message from secondary";
39 throw std::runtime_error(
"Failed to obtain information about a secondary: " + address + std::to_string(port));
41 auto r = resp->getInfoResp();
43 EcuSerial serial = EcuSerial(ToString(r->ecuSerial));
44 HardwareIdentifier hw_id = HardwareIdentifier(ToString(r->hwId));
45 std::string key = ToString(r->key);
46 auto type = static_cast<KeyType>(r->keyType);
49 LOG_INFO <<
"Got info on IP Secondary: "
50 <<
"hw-ID: " << hw_id <<
" serial: " << serial;
52 return std::make_shared<IpUptaneSecondary>(address, port, serial, hw_id, pub_key);
55 SecondaryInterface::Ptr IpUptaneSecondary::connectAndCheck(
const std::string& address,
unsigned short port,
56 EcuSerial serial, HardwareIdentifier hw_id,
62 auto sec = IpUptaneSecondary::connectAndCreate(address, port);
64 auto s = sec->getSerial();
66 LOG_ERROR <<
"Mismatch between secondary serials " << s <<
" and " << serial;
69 auto h = sec->getHwId();
71 LOG_ERROR <<
"Mismatch between hardware ids " << h <<
" and " << hw_id;
74 auto p = sec->getPublicKey();
75 if (pub_key.Type() == KeyType::kUnknown) {
76 LOG_INFO <<
"Secondary " << s <<
" do not have a known public key";
77 }
else if (p != pub_key) {
78 LOG_ERROR <<
"Mismatch between public keys " << p.Value() <<
" and " << pub_key.Value() <<
" for secondary "
84 }
catch (std::exception& e) {
85 LOG_WARNING <<
"Could not connect to secondary " << serial <<
" at " << address <<
":" << port
86 <<
", using previously known registration data";
89 return std::make_shared<IpUptaneSecondary>(address, port, std::move(serial), std::move(hw_id), std::move(pub_key));
92 IpUptaneSecondary::IpUptaneSecondary(
const std::string& address,
unsigned short port, EcuSerial serial,
93 HardwareIdentifier hw_id,
PublicKey pub_key)
94 : addr_{address, port}, serial_{std::move(serial)}, hw_id_{std::move(hw_id)}, pub_key_{std::move(pub_key)} {}
96 bool IpUptaneSecondary::putMetadata(
const RawMetaPack& meta_pack) {
97 LOG_INFO <<
"Sending Uptane metadata to the secondary";
99 req->present(AKIpUptaneMes_PR_putMetaReq);
101 auto m = req->putMetaReq();
102 m->image.present = image_PR_json;
103 SetString(&m->image.choice.json.root, meta_pack.image_root);
104 SetString(&m->image.choice.json.targets, meta_pack.image_targets);
105 SetString(&m->image.choice.json.snapshot, meta_pack.image_snapshot);
106 SetString(&m->image.choice.json.timestamp, meta_pack.image_timestamp);
108 m->director.present = director_PR_json;
109 SetString(&m->director.choice.json.root, meta_pack.director_root);
110 SetString(&m->director.choice.json.targets, meta_pack.director_targets);
112 auto resp = Asn1Rpc(req, getAddr());
114 if (resp->present() != AKIpUptaneMes_PR_putMetaResp) {
115 LOG_ERROR <<
"Failed to get response to sending manifest to secondary";
119 auto r = resp->putMetaResp();
120 return r->result == AKInstallationResult_success;
123 bool IpUptaneSecondary::sendFirmware(
const std::string&
data) {
124 std::lock_guard<std::mutex> l(install_mutex);
125 LOG_INFO <<
"Sending firmware to the secondary";
127 req->present(AKIpUptaneMes_PR_sendFirmwareReq);
129 auto m = req->sendFirmwareReq();
130 SetString(&m->firmware,
data);
131 auto resp = Asn1Rpc(req, getAddr());
133 if (resp->present() != AKIpUptaneMes_PR_sendFirmwareResp) {
134 LOG_ERROR <<
"Failed to get response to sending firmware to secondary";
138 auto r = resp->sendFirmwareResp();
139 return r->result == AKInstallationResult_success;
143 LOG_INFO <<
"Invoking an installation of the target on the secondary: " << target_name;
146 req->present(AKIpUptaneMes_PR_installReq);
149 auto req_mes = req->installReq();
150 SetString(&req_mes->hash, target_name);
152 auto resp = Asn1Rpc(req, getAddr());
155 if (resp->present() != AKIpUptaneMes_PR_installResp) {
156 LOG_ERROR <<
"Failed to get response to an installation request to secondary";
161 auto r = resp->installResp();
163 return static_cast<data::ResultCode::Numeric>(r->result);
166 Manifest IpUptaneSecondary::getManifest()
const {
167 LOG_DEBUG <<
"Getting the manifest from secondary with serial " << getSerial();
170 req->present(AKIpUptaneMes_PR_manifestReq);
172 auto resp = Asn1Rpc(req, getAddr());
174 if (resp->present() != AKIpUptaneMes_PR_manifestResp) {
175 LOG_ERROR <<
"Failed to get a response to a get manifest request to secondary";
176 return Json::Value();
178 auto r = resp->manifestResp();
180 if (r->manifest.present != manifest_PR_json) {
181 LOG_ERROR <<
"Manifest wasn't in json format";
182 return Json::Value();
184 std::string manifest = ToString(r->manifest.choice.json);
185 return Utils::parseJSON(manifest);
188 bool IpUptaneSecondary::ping()
const {
190 req->present(AKIpUptaneMes_PR_getInfoReq);
192 auto m = req->getInfoReq();
194 auto resp = Asn1Rpc(req, getAddr());
196 return resp->present() == AKIpUptaneMes_PR_getInfoResp;