1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include "srvcfg_manager.hpp"
17 
18 #include <boost/asio/spawn.hpp>
19 
20 #ifdef USB_CODE_UPDATE
21 #include <cereal/archives/json.hpp>
22 #include <cereal/types/tuple.hpp>
23 #include <cereal/types/unordered_map.hpp>
24 
25 #include <cstdio>
26 #endif
27 
28 #include <fstream>
29 #include <regex>
30 
31 extern std::unique_ptr<boost::asio::steady_timer> timer;
32 extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
33     srvMgrObjects;
34 static bool updateInProgress = false;
35 
36 namespace phosphor
37 {
38 namespace service
39 {
40 
41 static constexpr const char* overrideConfFileName = "override.conf";
42 static constexpr const size_t restartTimeout = 15; // seconds
43 
44 static constexpr const char* systemd1UnitBasePath =
45     "/org/freedesktop/systemd1/unit/";
46 static constexpr const char* systemdOverrideUnitBasePath =
47     "/etc/systemd/system/";
48 
49 #ifdef USB_CODE_UPDATE
50 static constexpr const char* usbCodeUpdateStateFilePath =
51     "/var/lib/srvcfg_manager";
52 static constexpr const char* usbCodeUpdateStateFile =
53     "/var/lib/srvcfg_manager/usb-code-update-state";
54 static constexpr const char* emptyUsbCodeUpdateRulesFile =
55     "/etc/udev/rules.d/70-bmc-usb.rules";
56 
57 using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;
58 
setUSBCodeUpdateState(const bool & state)59 void ServiceConfig::setUSBCodeUpdateState(const bool& state)
60 {
61     // Enable usb code update
62     if (state)
63     {
64         if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
65         {
66             lg2::info("Enable usb code update");
67             std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
68         }
69         return;
70     }
71 
72     // Disable usb code update
73     if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
74     {
75         std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
76     }
77     std::error_code ec;
78     std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
79                                     ec);
80     if (ec)
81     {
82         lg2::error("Disable usb code update failed");
83         return;
84     }
85     lg2::info("Disable usb code update");
86 }
87 
saveUSBCodeUpdateStateToFile(const bool & maskedState,const bool & enabledState)88 void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
89                                                  const bool& enabledState)
90 {
91     if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
92     {
93         std::filesystem::create_directories(usbCodeUpdateStateFilePath);
94     }
95 
96     UsbCodeUpdateStateMap usbCodeUpdateState;
97     usbCodeUpdateState[srvCfgPropMasked] = maskedState;
98     usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
99 
100     std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
101     cereal::JSONOutputArchive archive(file);
102     archive(CEREAL_NVP(usbCodeUpdateState));
103 }
104 
getUSBCodeUpdateStateFromFile()105 void ServiceConfig::getUSBCodeUpdateStateFromFile()
106 {
107     if (!std::filesystem::exists(usbCodeUpdateStateFile))
108     {
109         lg2::info("usb-code-update-state file does not exist");
110 
111         unitMaskedState = false;
112         unitEnabledState = true;
113         unitRunningState = true;
114         setUSBCodeUpdateState(unitEnabledState);
115         return;
116     }
117 
118     std::ifstream file(usbCodeUpdateStateFile);
119     cereal::JSONInputArchive archive(file);
120     UsbCodeUpdateStateMap usbCodeUpdateState;
121     archive(usbCodeUpdateState);
122 
123     auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
124     if (iterMask != usbCodeUpdateState.end())
125     {
126         unitMaskedState = iterMask->second;
127         if (unitMaskedState)
128         {
129             unitEnabledState = !unitMaskedState;
130             unitRunningState = !unitMaskedState;
131             setUSBCodeUpdateState(unitEnabledState);
132             return;
133         }
134 
135         auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
136         if (iterEnable != usbCodeUpdateState.end())
137         {
138             unitEnabledState = iterEnable->second;
139             unitRunningState = iterEnable->second;
140             setUSBCodeUpdateState(unitEnabledState);
141         }
142     }
143 }
144 #endif
145 
updateSocketProperties(const boost::container::flat_map<std::string,VariantType> & propertyMap)146 void ServiceConfig::updateSocketProperties(
147     const boost::container::flat_map<std::string, VariantType>& propertyMap)
148 {
149     auto listenIt = propertyMap.find("Listen");
150     if (listenIt != propertyMap.end())
151     {
152         auto listenVal =
153             std::get<std::vector<std::tuple<std::string, std::string>>>(
154                 listenIt->second);
155         if (listenVal.size())
156         {
157             protocol = std::get<0>(listenVal[0]);
158             std::string port = std::get<1>(listenVal[0]);
159             auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
160                                   nullptr, 10);
161             if (tmp > std::numeric_limits<uint16_t>::max())
162             {
163                 throw std::out_of_range("Out of range");
164             }
165             portNum = tmp;
166             if (sockAttrIface && sockAttrIface->is_initialized())
167             {
168                 internalSet = true;
169                 sockAttrIface->set_property(sockAttrPropPort, portNum);
170                 internalSet = false;
171             }
172         }
173     }
174 }
175 
updateServiceProperties(const boost::container::flat_map<std::string,VariantType> & propertyMap)176 void ServiceConfig::updateServiceProperties(
177     const boost::container::flat_map<std::string, VariantType>& propertyMap)
178 {
179     auto stateIt = propertyMap.find("UnitFileState");
180     if (stateIt != propertyMap.end())
181     {
182         stateValue = std::get<std::string>(stateIt->second);
183         unitEnabledState = unitMaskedState = false;
184         if (stateValue == stateMasked)
185         {
186             unitMaskedState = true;
187         }
188         else if (stateValue == stateEnabled)
189         {
190             unitEnabledState = true;
191         }
192         if (srvCfgIface && srvCfgIface->is_initialized())
193         {
194             internalSet = true;
195             srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
196             srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
197             internalSet = false;
198         }
199     }
200     auto subStateIt = propertyMap.find("SubState");
201     if (subStateIt != propertyMap.end())
202     {
203         subStateValue = std::get<std::string>(subStateIt->second);
204         if (subStateValue == subStateRunning ||
205             subStateValue == subStateListening)
206         {
207             unitRunningState = true;
208         }
209         if (srvCfgIface && srvCfgIface->is_initialized())
210         {
211             internalSet = true;
212             srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
213             internalSet = false;
214         }
215     }
216 
217 #ifdef USB_CODE_UPDATE
218     if (baseUnitName == usbCodeUpdateUnitName)
219     {
220         getUSBCodeUpdateStateFromFile();
221     }
222 #endif
223 }
224 
queryAndUpdateProperties()225 void ServiceConfig::queryAndUpdateProperties()
226 {
227     std::string objectPath =
228         isSocketActivatedService ? socketObjectPath : serviceObjectPath;
229     if (objectPath.empty())
230     {
231         return;
232     }
233 
234     conn->async_method_call(
235         [this](boost::system::error_code ec,
236                const boost::container::flat_map<std::string, VariantType>&
237                    propertyMap) {
238             if (ec)
239             {
240                 lg2::error(
241                     "async_method_call error: Failed to service unit properties: {EC}",
242                     "EC", ec.value());
243                 return;
244             }
245             try
246             {
247                 updateServiceProperties(propertyMap);
248                 if (!socketObjectPath.empty())
249                 {
250                     conn->async_method_call(
251                         [this](boost::system::error_code ec,
252                                const boost::container::flat_map<
253                                    std::string, VariantType>& propertyMap) {
254                             if (ec)
255                             {
256                                 lg2::error(
257                                     "async_method_call error: Failed to get all property: {EC}",
258                                     "EC", ec.value());
259                                 return;
260                             }
261                             try
262                             {
263                                 updateSocketProperties(propertyMap);
264                                 if (!srvCfgIface)
265                                 {
266                                     registerProperties();
267                                 }
268                             }
269                             catch (const std::exception& e)
270                             {
271                                 lg2::error(
272                                     "Exception in getting socket properties: {ERROR}",
273                                     "ERROR", e);
274                                 return;
275                             }
276                         },
277                         sysdService, socketObjectPath, dBusPropIntf,
278                         dBusGetAllMethod, sysdSocketIntf);
279                 }
280                 else if (!srvCfgIface)
281                 {
282                     registerProperties();
283                 }
284             }
285             catch (const std::exception& e)
286             {
287                 lg2::error("Exception in getting socket properties: {ERROR}",
288                            "ERROR", e);
289                 return;
290             }
291         },
292         sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
293     return;
294 }
295 
createSocketOverrideConf()296 void ServiceConfig::createSocketOverrideConf()
297 {
298     if (!socketObjectPath.empty())
299     {
300         std::string socketUnitName(instantiatedUnitName + ".socket");
301         /// Check override socket directory exist, if not create it.
302         std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
303         ovrUnitFileDir += socketUnitName;
304         ovrUnitFileDir += ".d";
305         if (!std::filesystem::exists(ovrUnitFileDir))
306         {
307             if (!std::filesystem::create_directories(ovrUnitFileDir))
308             {
309                 lg2::error("Unable to create the {DIR} directory.", "DIR",
310                            ovrUnitFileDir);
311                 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
312                                             Common::Error::InternalFailure>();
313             }
314         }
315         overrideConfDir = std::string(ovrUnitFileDir);
316     }
317 }
318 
ServiceConfig(sdbusplus::asio::object_server & srv_,std::shared_ptr<sdbusplus::asio::connection> & conn_,const std::string & objPath_,const std::string & baseUnitName_,const std::string & instanceName_,const std::string & serviceObjPath_,const std::string & socketObjPath_)319 ServiceConfig::ServiceConfig(
320     sdbusplus::asio::object_server& srv_,
321     std::shared_ptr<sdbusplus::asio::connection>& conn_,
322     const std::string& objPath_, const std::string& baseUnitName_,
323     const std::string& instanceName_, const std::string& serviceObjPath_,
324     const std::string& socketObjPath_) :
325     conn(conn_), server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
326     instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
327     socketObjectPath(socketObjPath_)
328 {
329     isSocketActivatedService = serviceObjectPath.empty();
330     instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
331     updatedFlag = 0;
332     queryAndUpdateProperties();
333     return;
334 }
335 
getSocketUnitName()336 std::string ServiceConfig::getSocketUnitName()
337 {
338     return instantiatedUnitName + ".socket";
339 }
340 
getServiceUnitName()341 std::string ServiceConfig::getServiceUnitName()
342 {
343     return instantiatedUnitName + ".service";
344 }
345 
isMaskedOut()346 bool ServiceConfig::isMaskedOut()
347 {
348     // return true  if state is masked & no request to update the maskedState
349     return (
350         stateValue == "masked" &&
351         !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
352 }
353 
stopAndApplyUnitConfig(boost::asio::yield_context yield)354 void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
355 {
356     if (!updatedFlag || isMaskedOut())
357     {
358         // No updates / masked - Just return.
359         return;
360     }
361     lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
362     if (subStateValue == subStateRunning || subStateValue == subStateListening)
363     {
364         if (!socketObjectPath.empty())
365         {
366             systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
367         }
368         if (!isSocketActivatedService)
369         {
370             systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
371         }
372         else
373         {
374             // For socket-activated service, each connection will spawn a
375             // service instance from template. Need to find all spawned service
376             // `<unitName>@<attribute>.service` and stop them through the
377             // systemdUnitAction method
378             boost::system::error_code ec;
379             auto listUnits =
380                 conn->yield_method_call<std::vector<ListUnitsType>>(
381                     yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
382                     "ListUnits");
383 
384             checkAndThrowInternalFailure(
385                 ec, "yield_method_call error: ListUnits failed");
386 
387             for (const auto& unit : listUnits)
388             {
389                 const auto& service =
390                     std::get<static_cast<int>(ListUnitElements::name)>(unit);
391                 const auto& status =
392                     std::get<static_cast<int>(ListUnitElements::subState)>(
393                         unit);
394                 if (service.find(baseUnitName + "@") != std::string::npos &&
395                     service.find(".service") != std::string::npos &&
396                     status == subStateRunning)
397                 {
398                     systemdUnitAction(conn, yield, service, sysdStopUnit);
399                 }
400             }
401         }
402     }
403 
404     if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
405     {
406         createSocketOverrideConf();
407         // Create override config file and write data.
408         std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
409         std::string tmpFile{ovrCfgFile + "_tmp"};
410         std::ofstream cfgFile(tmpFile, std::ios::out);
411         if (!cfgFile.good())
412         {
413             lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
414                        tmpFile);
415             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
416                                         Error::InternalFailure>();
417         }
418 
419         // Write the socket header
420         cfgFile << "[Socket]\n";
421         // Listen
422         cfgFile << "Listen" << protocol << "="
423                 << "\n";
424         cfgFile << "Listen" << protocol << "=" << portNum << "\n";
425         cfgFile.close();
426 
427         if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
428         {
429             lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
430                        "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
431             std::remove(tmpFile.c_str());
432             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
433                                         Error::InternalFailure>();
434         }
435     }
436 
437     if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
438                        (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
439     {
440         std::vector<std::string> unitFiles;
441         if (socketObjectPath.empty())
442         {
443             unitFiles = {getServiceUnitName()};
444         }
445         else if (serviceObjectPath.empty())
446         {
447             unitFiles = {getSocketUnitName()};
448         }
449         else
450         {
451             unitFiles = {getSocketUnitName(), getServiceUnitName()};
452         }
453         systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
454                                     unitMaskedState, unitEnabledState);
455     }
456     return;
457 }
restartUnitConfig(boost::asio::yield_context yield)458 void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
459 {
460     if (!updatedFlag || isMaskedOut())
461     {
462         // No updates. Just return.
463         return;
464     }
465 
466     if (unitRunningState)
467     {
468         if (!socketObjectPath.empty())
469         {
470             systemdUnitAction(conn, yield, getSocketUnitName(),
471                               sysdRestartUnit);
472         }
473         if (!serviceObjectPath.empty())
474         {
475             systemdUnitAction(conn, yield, getServiceUnitName(),
476                               sysdRestartUnit);
477         }
478     }
479 
480     // Reset the flag
481     updatedFlag = 0;
482 
483     lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
484 
485     queryAndUpdateProperties();
486     return;
487 }
488 
startServiceRestartTimer()489 void ServiceConfig::startServiceRestartTimer()
490 {
491     timer->expires_after(std::chrono::seconds(restartTimeout));
492     timer->async_wait([this](const boost::system::error_code& ec) {
493         if (ec == boost::asio::error::operation_aborted)
494         {
495             // Timer reset.
496             return;
497         }
498         else if (ec)
499         {
500             lg2::error("async wait error: {EC}", "EC", ec.value());
501             return;
502         }
503         updateInProgress = true;
504         boost::asio::spawn(conn->get_io_context(),
505                            [this](boost::asio::yield_context yield) {
506                                // Stop and apply configuration for all objects
507                                for (auto& srvMgrObj : srvMgrObjects)
508                                {
509                                    auto& srvObj = srvMgrObj.second;
510                                    if (srvObj->updatedFlag)
511                                    {
512                                        srvObj->stopAndApplyUnitConfig(yield);
513                                    }
514                                }
515                                // Do system reload
516                                systemdDaemonReload(conn, yield);
517                                // restart unit config.
518                                for (auto& srvMgrObj : srvMgrObjects)
519                                {
520                                    auto& srvObj = srvMgrObj.second;
521                                    if (srvObj->updatedFlag)
522                                    {
523                                        srvObj->restartUnitConfig(yield);
524                                    }
525                                }
526                                updateInProgress = false;
527                            });
528     });
529 }
530 
registerProperties()531 void ServiceConfig::registerProperties()
532 {
533     srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
534 
535     if (!socketObjectPath.empty())
536     {
537         sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
538         sockAttrIface->register_property(
539             sockAttrPropPort, portNum,
540             [this](const uint16_t& req, uint16_t& res) {
541                 if (!internalSet)
542                 {
543                     if (req == res)
544                     {
545                         return 1;
546                     }
547                     if (updateInProgress)
548                     {
549                         return 0;
550                     }
551                     portNum = req;
552                     updatedFlag |=
553                         (1 << static_cast<uint8_t>(UpdatedProp::port));
554                     startServiceRestartTimer();
555                 }
556                 res = req;
557                 return 1;
558             });
559     }
560 
561     srvCfgIface->register_property(
562         srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
563             if (!internalSet)
564             {
565 #ifdef USB_CODE_UPDATE
566                 if (baseUnitName == usbCodeUpdateUnitName)
567                 {
568                     unitMaskedState = req;
569                     unitEnabledState = !unitMaskedState;
570                     unitRunningState = !unitMaskedState;
571                     internalSet = true;
572                     srvCfgIface->set_property(srvCfgPropEnabled,
573                                               unitEnabledState);
574                     srvCfgIface->set_property(srvCfgPropRunning,
575                                               unitRunningState);
576                     srvCfgIface->set_property(srvCfgPropMasked,
577                                               unitMaskedState);
578                     internalSet = false;
579                     setUSBCodeUpdateState(unitEnabledState);
580                     saveUSBCodeUpdateStateToFile(unitMaskedState,
581                                                  unitEnabledState);
582                     return 1;
583                 }
584 #endif
585                 if (req == res)
586                 {
587                     return 1;
588                 }
589                 if (updateInProgress)
590                 {
591                     return 0;
592                 }
593                 unitMaskedState = req;
594                 unitEnabledState = !unitMaskedState;
595                 unitRunningState = !unitMaskedState;
596                 updatedFlag |=
597                     (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
598                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
599                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
600                 internalSet = true;
601                 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
602                 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
603                 internalSet = false;
604                 startServiceRestartTimer();
605             }
606             res = req;
607             return 1;
608         });
609 
610     srvCfgIface->register_property(
611         srvCfgPropEnabled, unitEnabledState,
612         [this](const bool& req, bool& res) {
613             if (!internalSet)
614             {
615 #ifdef USB_CODE_UPDATE
616                 if (baseUnitName == usbCodeUpdateUnitName)
617                 {
618                     if (unitMaskedState)
619                     { // block updating if masked
620                         lg2::error("Invalid value specified");
621                         return -EINVAL;
622                     }
623                     unitEnabledState = req;
624                     unitRunningState = req;
625                     internalSet = true;
626                     srvCfgIface->set_property(srvCfgPropEnabled,
627                                               unitEnabledState);
628                     srvCfgIface->set_property(srvCfgPropRunning,
629                                               unitRunningState);
630                     internalSet = false;
631                     setUSBCodeUpdateState(unitEnabledState);
632                     saveUSBCodeUpdateStateToFile(unitMaskedState,
633                                                  unitEnabledState);
634                     res = req;
635                     return 1;
636                 }
637 #endif
638                 if (req == res)
639                 {
640                     return 1;
641                 }
642                 if (updateInProgress)
643                 {
644                     return 0;
645                 }
646                 if (unitMaskedState)
647                 { // block updating if masked
648                     lg2::error("Invalid value specified");
649                     return -EINVAL;
650                 }
651                 unitEnabledState = req;
652                 updatedFlag |=
653                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
654                 startServiceRestartTimer();
655             }
656             res = req;
657             return 1;
658         });
659 
660     srvCfgIface->register_property(
661         srvCfgPropRunning, unitRunningState,
662         [this](const bool& req, bool& res) {
663             if (!internalSet)
664             {
665 #ifdef USB_CODE_UPDATE
666                 if (baseUnitName == usbCodeUpdateUnitName)
667                 {
668                     if (unitMaskedState)
669                     { // block updating if masked
670                         lg2::error("Invalid value specified");
671                         return -EINVAL;
672                     }
673                     unitEnabledState = req;
674                     unitRunningState = req;
675                     internalSet = true;
676                     srvCfgIface->set_property(srvCfgPropEnabled,
677                                               unitEnabledState);
678                     srvCfgIface->set_property(srvCfgPropRunning,
679                                               unitRunningState);
680                     internalSet = false;
681                     setUSBCodeUpdateState(unitEnabledState);
682                     saveUSBCodeUpdateStateToFile(unitMaskedState,
683                                                  unitEnabledState);
684                     res = req;
685                     return 1;
686                 }
687 #endif
688                 if (req == res)
689                 {
690                     return 1;
691                 }
692                 if (updateInProgress)
693                 {
694                     return 0;
695                 }
696                 if (unitMaskedState)
697                 { // block updating if masked
698                     lg2::error("Invalid value specified");
699                     return -EINVAL;
700                 }
701                 unitRunningState = req;
702                 updatedFlag |=
703                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
704                 startServiceRestartTimer();
705             }
706             res = req;
707             return 1;
708         });
709 
710     srvCfgIface->initialize();
711     if (!socketObjectPath.empty())
712     {
713         sockAttrIface->initialize();
714     }
715     return;
716 }
717 
718 } // namespace service
719 } // namespace phosphor
720