1 #include <chrono> 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdint.h> 5 #include <arpa/inet.h> 6 #include <string> 7 #include <experimental/filesystem> 8 9 #include "host-ipmid/ipmid-api.h" 10 #include "ipmid.hpp" 11 #include "timer.hpp" 12 #include "transporthandler.hpp" 13 #include "utils.hpp" 14 #include "net.hpp" 15 16 #include <phosphor-logging/log.hpp> 17 #include <phosphor-logging/elog-errors.hpp> 18 #include "xyz/openbmc_project/Common/error.hpp" 19 20 #define SYSTEMD_NETWORKD_DBUS 1 21 22 #ifdef SYSTEMD_NETWORKD_DBUS 23 #include <systemd/sd-bus.h> 24 #include <mapper.h> 25 #endif 26 27 extern std::unique_ptr<phosphor::ipmi::Timer> networkTimer; 28 29 const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx 30 constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4"; 31 32 std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig; 33 34 using namespace phosphor::logging; 35 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 36 37 namespace fs = std::experimental::filesystem; 38 39 void register_netfn_transport_functions() __attribute__((constructor)); 40 41 struct ChannelConfig_t* getChannelConfig(int channel) 42 { 43 auto item = channelConfig.find(channel); 44 if (item == channelConfig.end()) 45 { 46 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>(); 47 } 48 49 return channelConfig[channel].get(); 50 } 51 52 // Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network Manager or 53 // Cache based on Set-In-Progress State 54 ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel) 55 { 56 ipmi_ret_t rc = IPMI_CC_OK; 57 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 58 59 auto ethdevice = ipmi::network::ChanneltoEthernet(channel); 60 // if ethdevice is an empty string they weren't expecting this channel. 61 if (ethdevice.empty()) 62 { 63 // TODO: return error from getNetworkData() 64 return IPMI_CC_INVALID_FIELD_REQUEST; 65 } 66 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE; 67 auto channelConf = getChannelConfig(channel); 68 69 try 70 { 71 switch (lan_param) 72 { 73 case LAN_PARM_IP: 74 { 75 std::string ipaddress; 76 if (channelConf->lan_set_in_progress == SET_COMPLETE) 77 { 78 try 79 { 80 auto ipObjectInfo = ipmi::getIPObject( 81 bus, 82 ipmi::network::IP_INTERFACE, 83 ipmi::network::ROOT, 84 ethIP); 85 86 auto properties = ipmi::getAllDbusProperties( 87 bus, 88 ipObjectInfo.second, 89 ipObjectInfo.first, 90 ipmi::network::IP_INTERFACE); 91 92 ipaddress = properties["Address"].get<std::string>(); 93 } 94 // ignore the exception, as it is a valid condtion that 95 // system is not confiured with any ip. 96 catch (InternalFailure& e) 97 { 98 // nothing to do. 99 } 100 } 101 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) 102 { 103 ipaddress = channelConf->ipaddr; 104 } 105 106 inet_pton(AF_INET, ipaddress.c_str(), 107 reinterpret_cast<void*>(data)); 108 } 109 break; 110 111 case LAN_PARM_IPSRC: 112 { 113 std::string networkInterfacePath; 114 115 if (channelConf->lan_set_in_progress == SET_COMPLETE) 116 { 117 try 118 { 119 ipmi::ObjectTree ancestorMap; 120 // if the system is having ip object,then 121 // get the IP object. 122 auto ipObject = ipmi::getDbusObject( 123 bus, 124 ipmi::network::IP_INTERFACE, 125 ipmi::network::ROOT, 126 ethIP); 127 128 // Get the parent interface of the IP object. 129 try 130 { 131 ipmi::InterfaceList interfaces; 132 interfaces.emplace_back( 133 ipmi::network::ETHERNET_INTERFACE); 134 135 ancestorMap = ipmi::getAllAncestors( 136 bus, 137 ipObject.first, 138 std::move(interfaces)); 139 } 140 catch (InternalFailure& e) 141 { 142 // if unable to get the parent interface 143 // then commit the error and return. 144 log<level::ERR>("Unable to get the parent interface", 145 entry("PATH=%s", ipObject.first.c_str()), 146 entry("INTERFACE=%s", 147 ipmi::network::ETHERNET_INTERFACE)); 148 break; 149 150 } 151 // for an ip object there would be single parent 152 // interface. 153 networkInterfacePath = ancestorMap.begin()->first; 154 } 155 catch (InternalFailure& e) 156 { 157 // if there is no ip configured on the system,then 158 // get the network interface object. 159 auto networkInterfaceObject = ipmi::getDbusObject( 160 bus, 161 ipmi::network::ETHERNET_INTERFACE, 162 ipmi::network::ROOT, 163 ethdevice); 164 165 networkInterfacePath = networkInterfaceObject.first; 166 } 167 168 auto variant = ipmi::getDbusProperty( 169 bus, 170 ipmi::network::SERVICE, 171 networkInterfacePath, 172 ipmi::network::ETHERNET_INTERFACE, 173 "DHCPEnabled"); 174 175 auto dhcpEnabled = variant.get<bool>(); 176 // As per IPMI spec 2=>DHCP, 1=STATIC 177 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP : 178 ipmi::network::IPOrigin::STATIC; 179 180 memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE); 181 } 182 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) 183 { 184 memcpy(data, &(channelConf->ipsrc), 185 ipmi::network::IPSRC_SIZE_BYTE); 186 } 187 } 188 break; 189 190 case LAN_PARM_SUBNET: 191 { 192 unsigned long mask {}; 193 if (channelConf->lan_set_in_progress == SET_COMPLETE) 194 { 195 try 196 { 197 auto ipObjectInfo = ipmi::getIPObject( 198 bus, 199 ipmi::network::IP_INTERFACE, 200 ipmi::network::ROOT, 201 ipmi::network::IP_TYPE); 202 203 auto properties = ipmi::getAllDbusProperties( 204 bus, 205 ipObjectInfo.second, 206 ipObjectInfo.first, 207 ipmi::network::IP_INTERFACE); 208 209 auto prefix = properties["PrefixLength"].get<uint8_t>(); 210 mask = ipmi::network::MASK_32_BIT; 211 mask = htonl(mask << (ipmi::network::BITS_32 - prefix)); 212 } 213 // ignore the exception, as it is a valid condtion that 214 // system is not confiured with any ip. 215 catch (InternalFailure& e) 216 { 217 // nothing to do 218 } 219 memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE); 220 } 221 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) 222 { 223 inet_pton(AF_INET, channelConf->netmask.c_str(), 224 reinterpret_cast<void*>(data)); 225 } 226 227 } 228 break; 229 230 case LAN_PARM_GATEWAY: 231 { 232 std::string gateway; 233 234 if (channelConf->lan_set_in_progress == SET_COMPLETE) 235 { 236 try 237 { 238 auto systemObject = ipmi::getDbusObject( 239 bus, 240 ipmi::network::SYSTEMCONFIG_INTERFACE, 241 ipmi::network::ROOT); 242 243 auto systemProperties = ipmi::getAllDbusProperties( 244 bus, 245 systemObject.second, 246 systemObject.first, 247 ipmi::network::SYSTEMCONFIG_INTERFACE); 248 249 gateway = systemProperties["DefaultGateway"].get< 250 std::string>(); 251 } 252 // ignore the exception, as it is a valid condtion that 253 // system is not confiured with any ip. 254 catch (InternalFailure& e) 255 { 256 // nothing to do 257 } 258 259 } 260 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) 261 { 262 gateway = channelConf->gateway; 263 } 264 265 inet_pton(AF_INET, gateway.c_str(), 266 reinterpret_cast<void*>(data)); 267 } 268 break; 269 270 case LAN_PARM_MAC: 271 { 272 std::string macAddress; 273 if (channelConf->lan_set_in_progress == SET_COMPLETE) 274 { 275 auto macObjectInfo = ipmi::getDbusObject( 276 bus, 277 ipmi::network::MAC_INTERFACE, 278 ipmi::network::ROOT, 279 ethdevice); 280 281 auto variant = ipmi::getDbusProperty( 282 bus, 283 macObjectInfo.second, 284 macObjectInfo.first, 285 ipmi::network::MAC_INTERFACE, 286 "MACAddress"); 287 288 macAddress = variant.get<std::string>(); 289 290 } 291 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) 292 { 293 macAddress = channelConf->macAddress; 294 } 295 296 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT, 297 (data), 298 (data + 1), 299 (data + 2), 300 (data + 3), 301 (data + 4), 302 (data + 5)); 303 } 304 break; 305 306 case LAN_PARM_VLAN: 307 { 308 uint16_t vlanID {}; 309 if (channelConf->lan_set_in_progress == SET_COMPLETE) 310 { 311 try 312 { 313 auto ipObjectInfo = ipmi::getIPObject( 314 bus, 315 ipmi::network::IP_INTERFACE, 316 ipmi::network::ROOT, 317 ipmi::network::IP_TYPE); 318 319 vlanID = static_cast<uint16_t>( 320 ipmi::network::getVLAN(ipObjectInfo.first)); 321 322 vlanID = htole16(vlanID); 323 324 if (vlanID) 325 { 326 //Enable the 16th bit 327 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK); 328 } 329 } 330 // ignore the exception, as it is a valid condtion that 331 // system is not confiured with any ip. 332 catch (InternalFailure& e) 333 { 334 // nothing to do 335 } 336 337 memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE); 338 } 339 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS) 340 { 341 memcpy(data, &(channelConf->vlanID), 342 ipmi::network::VLAN_SIZE_BYTE); 343 } 344 } 345 break; 346 347 default: 348 rc = IPMI_CC_PARM_OUT_OF_RANGE; 349 } 350 } 351 catch (InternalFailure& e) 352 { 353 commit<InternalFailure>(); 354 rc = IPMI_CC_UNSPECIFIED_ERROR; 355 return rc; 356 } 357 return rc; 358 } 359 360 ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 361 ipmi_request_t request, ipmi_response_t response, 362 ipmi_data_len_t data_len, ipmi_context_t context) 363 { 364 // Status code. 365 ipmi_ret_t rc = IPMI_CC_INVALID; 366 *data_len = 0; 367 return rc; 368 } 369 370 struct set_lan_t 371 { 372 uint8_t channel; 373 uint8_t parameter; 374 uint8_t data[8]; // Per IPMI spec, not expecting more than this size 375 } __attribute__((packed)); 376 377 ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, 378 ipmi_cmd_t cmd, 379 ipmi_request_t request, 380 ipmi_response_t response, 381 ipmi_data_len_t data_len, 382 ipmi_context_t context) 383 { 384 ipmi_ret_t rc = IPMI_CC_OK; 385 *data_len = 0; 386 387 using namespace std::chrono_literals; 388 389 // time to wait before applying the network changes. 390 constexpr auto networkTimeout = 10000000us; // 10 sec 391 392 char ipaddr[INET_ADDRSTRLEN]; 393 char netmask[INET_ADDRSTRLEN]; 394 char gateway[INET_ADDRSTRLEN]; 395 396 auto reqptr = reinterpret_cast<const set_lan_t*>(request); 397 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 398 399 // channel number is the lower nibble 400 int channel = reqptr->channel & CHANNEL_MASK; 401 auto ethdevice = ipmi::network::ChanneltoEthernet(channel); 402 if (ethdevice.empty()) 403 { 404 return IPMI_CC_INVALID_FIELD_REQUEST; 405 } 406 auto channelConf = getChannelConfig(channel); 407 408 switch (reqptr->parameter) 409 { 410 case LAN_PARM_IP: 411 { 412 snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT, 413 reqptr->data[0], reqptr->data[1], 414 reqptr->data[2], reqptr->data[3]); 415 416 channelConf->ipaddr.assign(ipaddr); 417 } 418 break; 419 420 case LAN_PARM_IPSRC: 421 { 422 uint8_t ipsrc{}; 423 memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE); 424 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc); 425 } 426 break; 427 428 case LAN_PARM_MAC: 429 { 430 char mac[SIZE_MAC]; 431 432 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT, 433 reqptr->data[0], 434 reqptr->data[1], 435 reqptr->data[2], 436 reqptr->data[3], 437 reqptr->data[4], 438 reqptr->data[5]); 439 440 auto macObjectInfo = ipmi::getDbusObject( 441 bus, 442 ipmi::network::MAC_INTERFACE, 443 ipmi::network::ROOT, 444 ethdevice); 445 446 ipmi::setDbusProperty(bus, 447 macObjectInfo.second, 448 macObjectInfo.first, 449 ipmi::network::MAC_INTERFACE, 450 "MACAddress", 451 std::string(mac)); 452 453 channelConf->macAddress = mac; 454 } 455 break; 456 457 case LAN_PARM_SUBNET: 458 { 459 snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT, 460 reqptr->data[0], reqptr->data[1], 461 reqptr->data[2], reqptr->data[3]); 462 channelConf->netmask.assign(netmask); 463 } 464 break; 465 466 case LAN_PARM_GATEWAY: 467 { 468 snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT, 469 reqptr->data[0], reqptr->data[1], 470 reqptr->data[2], reqptr->data[3]); 471 channelConf->gateway.assign(gateway); 472 } 473 break; 474 475 case LAN_PARM_VLAN: 476 { 477 uint16_t vlan {}; 478 memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE); 479 // We are not storing the enable bit 480 // We assume that ipmitool always send enable 481 // bit as 1. 482 vlan = le16toh(vlan); 483 channelConf->vlanID = vlan; 484 } 485 break; 486 487 case LAN_PARM_INPROGRESS: 488 { 489 if (reqptr->data[0] == SET_COMPLETE) 490 { 491 channelConf->lan_set_in_progress = SET_COMPLETE; 492 493 log<level::INFO>("Network data from Cache", 494 entry("PREFIX=%s", channelConf->netmask.c_str()), 495 entry("ADDRESS=%s", channelConf->ipaddr.c_str()), 496 entry("GATEWAY=%s", channelConf->gateway.c_str()), 497 entry("VLAN=%d", channelConf->vlanID)); 498 499 if (!networkTimer) 500 { 501 log<level::ERR>("Network timer is not instantiated"); 502 return IPMI_CC_UNSPECIFIED_ERROR; 503 } 504 505 // start/restart the timer 506 networkTimer->startTimer(networkTimeout); 507 } 508 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress 509 { 510 channelConf->lan_set_in_progress = SET_IN_PROGRESS; 511 channelConf->flush = true; 512 } 513 } 514 break; 515 516 default: 517 { 518 rc = IPMI_CC_PARM_NOT_SUPPORTED; 519 } 520 } 521 522 return rc; 523 } 524 525 struct get_lan_t 526 { 527 uint8_t rev_channel; 528 uint8_t parameter; 529 uint8_t parameter_set; 530 uint8_t parameter_block; 531 } __attribute__((packed)); 532 533 ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, 534 ipmi_cmd_t cmd, 535 ipmi_request_t request, 536 ipmi_response_t response, 537 ipmi_data_len_t data_len, 538 ipmi_context_t context) 539 { 540 ipmi_ret_t rc = IPMI_CC_OK; 541 *data_len = 0; 542 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 543 544 get_lan_t *reqptr = (get_lan_t*) request; 545 // channel number is the lower nibble 546 int channel = reqptr->rev_channel & CHANNEL_MASK; 547 548 if (reqptr->rev_channel & 0x80) // Revision is bit 7 549 { 550 // Only current revision was requested 551 *data_len = sizeof(current_revision); 552 memcpy(response, ¤t_revision, *data_len); 553 return IPMI_CC_OK; 554 } 555 556 auto ethdevice = ipmi::network::ChanneltoEthernet(channel); 557 if (ethdevice.empty()) 558 { 559 return IPMI_CC_INVALID_FIELD_REQUEST; 560 } 561 auto channelConf = getChannelConfig(channel); 562 563 if (reqptr->parameter == LAN_PARM_INPROGRESS) 564 { 565 uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress}; 566 *data_len = sizeof(buf); 567 memcpy(response, &buf, *data_len); 568 } 569 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT) 570 { 571 uint8_t buf[] = {current_revision,0x04}; 572 *data_len = sizeof(buf); 573 memcpy(response, &buf, *data_len); 574 } 575 else if (reqptr->parameter == LAN_PARM_AUTHENABLES) 576 { 577 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04}; 578 *data_len = sizeof(buf); 579 memcpy(response, &buf, *data_len); 580 } 581 else if ((reqptr->parameter == LAN_PARM_IP) || 582 (reqptr->parameter == LAN_PARM_SUBNET) || 583 (reqptr->parameter == LAN_PARM_GATEWAY) || 584 (reqptr->parameter == LAN_PARM_MAC)) 585 { 586 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {}; 587 588 *data_len = sizeof(current_revision); 589 memcpy(buf, ¤t_revision, *data_len); 590 591 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK) 592 { 593 if (reqptr->parameter == LAN_PARM_MAC) 594 { 595 *data_len = sizeof(buf); 596 } 597 else 598 { 599 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1; 600 } 601 memcpy(response, &buf, *data_len); 602 } 603 else 604 { 605 rc = IPMI_CC_UNSPECIFIED_ERROR; 606 } 607 } 608 else if (reqptr->parameter == LAN_PARM_VLAN) 609 { 610 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {}; 611 612 *data_len = sizeof(current_revision); 613 memcpy(buf, ¤t_revision, *data_len); 614 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK) 615 { 616 *data_len = sizeof(buf); 617 memcpy(response, &buf, *data_len); 618 } 619 } 620 else if (reqptr->parameter == LAN_PARM_IPSRC) 621 { 622 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {}; 623 *data_len = sizeof(current_revision); 624 memcpy(buff, ¤t_revision, *data_len); 625 if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK) 626 { 627 *data_len = sizeof(buff); 628 memcpy(response, &buff, *data_len); 629 } 630 } 631 else 632 { 633 log<level::ERR>("Unsupported parameter", 634 entry("PARAMETER=0x%x", reqptr->parameter)); 635 rc = IPMI_CC_PARM_NOT_SUPPORTED; 636 } 637 638 return rc; 639 } 640 641 void applyChanges(int channel) 642 { 643 std::string ipaddress; 644 std::string gateway; 645 uint8_t prefix {}; 646 uint32_t vlanID {}; 647 std::string networkInterfacePath; 648 ipmi::DbusObjectInfo ipObject; 649 ipmi::DbusObjectInfo systemObject; 650 651 auto ethdevice = ipmi::network::ChanneltoEthernet(channel); 652 if (ethdevice.empty()) 653 { 654 log<level::ERR>("Unable to get the interface name", 655 entry("CHANNEL=%d", channel)); 656 return; 657 } 658 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE; 659 auto channelConf = getChannelConfig(channel); 660 661 try 662 { 663 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 664 665 log<level::INFO>("Network data from Cache", 666 entry("PREFIX=%s", channelConf->netmask.c_str()), 667 entry("ADDRESS=%s", channelConf->ipaddr.c_str()), 668 entry("GATEWAY=%s", channelConf->gateway.c_str()), 669 entry("VLAN=%d", channelConf->vlanID), 670 entry("IPSRC=%d", channelConf->ipsrc)); 671 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK) 672 { 673 //get the first twelve bits which is vlan id 674 //not interested in rest of the bits. 675 channelConf->vlanID = le32toh(channelConf->vlanID); 676 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK; 677 } 678 679 // if the asked ip src is DHCP then not interested in 680 // any given data except vlan. 681 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP) 682 { 683 // always get the system object 684 systemObject = ipmi::getDbusObject( 685 bus, 686 ipmi::network::SYSTEMCONFIG_INTERFACE, 687 ipmi::network::ROOT); 688 689 // the below code is to determine the mode of the interface 690 // as the handling is same, if the system is configured with 691 // DHCP or user has given all the data. 692 try 693 { 694 ipmi::ObjectTree ancestorMap; 695 696 ipmi::InterfaceList interfaces { 697 ipmi::network::ETHERNET_INTERFACE }; 698 699 // if the system is having ip object,then 700 // get the IP object. 701 ipObject = ipmi::getIPObject(bus, 702 ipmi::network::IP_INTERFACE, 703 ipmi::network::ROOT, 704 ethIp); 705 706 // Get the parent interface of the IP object. 707 try 708 { 709 ancestorMap = ipmi::getAllAncestors(bus, 710 ipObject.first, 711 std::move(interfaces)); 712 } 713 catch (InternalFailure& e) 714 { 715 // if unable to get the parent interface 716 // then commit the error and return. 717 log<level::ERR>("Unable to get the parent interface", 718 entry("PATH=%s", ipObject.first.c_str()), 719 entry("INTERFACE=%s", 720 ipmi::network::ETHERNET_INTERFACE)); 721 commit<InternalFailure>(); 722 channelConf->clear(); 723 return; 724 } 725 726 networkInterfacePath = ancestorMap.begin()->first; 727 } 728 catch (InternalFailure& e) 729 { 730 // TODO Currently IPMI supports single interface,need to handle 731 // Multiple interface through 732 // https://github.com/openbmc/openbmc/issues/2138 733 734 // if there is no ip configured on the system,then 735 // get the network interface object. 736 auto networkInterfaceObject = ipmi::getDbusObject( 737 bus, 738 ipmi::network::ETHERNET_INTERFACE, 739 ipmi::network::ROOT, 740 ethdevice); 741 742 networkInterfacePath = std::move(networkInterfaceObject.first); 743 } 744 745 // get the configured mode on the system. 746 auto enableDHCP = ipmi::getDbusProperty( 747 bus, 748 ipmi::network::SERVICE, 749 networkInterfacePath, 750 ipmi::network::ETHERNET_INTERFACE, 751 "DHCPEnabled").get<bool>(); 752 753 // if ip address source is not given then get the ip source mode 754 // from the system so that it can be applied later. 755 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED) 756 { 757 channelConf->ipsrc = (enableDHCP) ? 758 ipmi::network::IPOrigin::DHCP : 759 ipmi::network::IPOrigin::STATIC; 760 } 761 762 // check whether user has given all the data 763 // or the configured system interface is dhcp enabled, 764 // in both of the cases get the values from the cache. 765 if ((!channelConf->ipaddr.empty() && 766 !channelConf->netmask.empty() && 767 !channelConf->gateway.empty()) || 768 (enableDHCP)) // configured system interface mode = DHCP 769 { 770 //convert mask into prefix 771 ipaddress = channelConf->ipaddr; 772 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask); 773 gateway = channelConf->gateway; 774 } 775 else // asked ip src = static and configured system src = static 776 // or partially given data. 777 { 778 // We have partial filled cache so get the remaining 779 // info from the system. 780 781 // Get the network data from the system as user has 782 // not given all the data then use the data fetched from the 783 // system but it is implementation dependent,IPMI spec doesn't 784 // force it. 785 786 // if system is not having any ip object don't throw error, 787 try 788 { 789 auto properties = ipmi::getAllDbusProperties( 790 bus, 791 ipObject.second, 792 ipObject.first, 793 ipmi::network::IP_INTERFACE); 794 795 ipaddress = channelConf->ipaddr.empty() ? 796 properties["Address"].get<std::string>() : 797 channelConf->ipaddr; 798 799 prefix = channelConf->netmask.empty() ? 800 properties["PrefixLength"].get<uint8_t>() : 801 ipmi::network::toPrefix(AF_INET, 802 channelConf->netmask); 803 } 804 catch (InternalFailure& e) 805 { 806 log<level::INFO>("Failed to get IP object which matches", 807 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE), 808 entry("MATCH=%s", ethIp)); 809 } 810 811 auto systemProperties = ipmi::getAllDbusProperties( 812 bus, 813 systemObject.second, 814 systemObject.first, 815 ipmi::network::SYSTEMCONFIG_INTERFACE); 816 817 gateway = channelConf->gateway.empty() ? 818 systemProperties["DefaultGateway"].get<std::string>() : 819 channelConf->gateway; 820 } 821 } 822 823 // Currently network manager doesn't support purging of all the 824 // ip addresses and the vlan interfaces from the parent interface, 825 // TODO once the support is there, will make the change here. 826 // https://github.com/openbmc/openbmc/issues/2141. 827 828 // TODO Currently IPMI supports single interface,need to handle 829 // Multiple interface through 830 // https://github.com/openbmc/openbmc/issues/2138 831 832 // instead of deleting all the vlan interfaces and 833 // all the ipv4 address,we will call reset method. 834 //delete all the vlan interfaces 835 836 ipmi::deleteAllDbusObjects(bus, 837 ipmi::network::ROOT, 838 ipmi::network::VLAN_INTERFACE); 839 840 // set the interface mode to static 841 auto networkInterfaceObject = ipmi::getDbusObject( 842 bus, 843 ipmi::network::ETHERNET_INTERFACE, 844 ipmi::network::ROOT, 845 ethdevice); 846 847 // setting the physical interface mode to static. 848 ipmi::setDbusProperty(bus, 849 ipmi::network::SERVICE, 850 networkInterfaceObject.first, 851 ipmi::network::ETHERNET_INTERFACE, 852 "DHCPEnabled", 853 false); 854 855 networkInterfacePath = networkInterfaceObject.first; 856 857 //delete all the ipv4 addresses 858 ipmi::deleteAllDbusObjects(bus, 859 ipmi::network::ROOT, 860 ipmi::network::IP_INTERFACE, 861 ethIp); 862 863 if (vlanID) 864 { 865 ipmi::network::createVLAN(bus, 866 ipmi::network::SERVICE, 867 ipmi::network::ROOT, 868 ethdevice, 869 vlanID); 870 871 auto networkInterfaceObject = ipmi::getDbusObject( 872 bus, 873 ipmi::network::VLAN_INTERFACE, 874 ipmi::network::ROOT); 875 876 networkInterfacePath = networkInterfaceObject.first; 877 } 878 879 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP) 880 { 881 ipmi::setDbusProperty(bus, 882 ipmi::network::SERVICE, 883 networkInterfacePath, 884 ipmi::network::ETHERNET_INTERFACE, 885 "DHCPEnabled", 886 true); 887 } 888 else 889 { 890 //change the mode to static 891 ipmi::setDbusProperty(bus, 892 ipmi::network::SERVICE, 893 networkInterfacePath, 894 ipmi::network::ETHERNET_INTERFACE, 895 "DHCPEnabled", 896 false); 897 898 if (!ipaddress.empty()) 899 { 900 ipmi::network::createIP(bus, 901 ipmi::network::SERVICE, 902 networkInterfacePath, 903 ipv4Protocol, 904 ipaddress, 905 prefix); 906 } 907 908 if (!gateway.empty()) 909 { 910 ipmi::setDbusProperty(bus, 911 systemObject.second, 912 systemObject.first, 913 ipmi::network::SYSTEMCONFIG_INTERFACE, 914 "DefaultGateway", 915 std::string(gateway)); 916 } 917 } 918 919 } 920 catch (InternalFailure& e) 921 { 922 log<level::ERR>("Failed to set network data", 923 entry("PREFIX=%d", prefix), 924 entry("ADDRESS=%s", ipaddress.c_str()), 925 entry("GATEWAY=%s", gateway.c_str()), 926 entry("VLANID=%d", vlanID), 927 entry("IPSRC=%d", channelConf->ipsrc)); 928 929 commit<InternalFailure>(); 930 } 931 932 channelConf->clear(); 933 } 934 935 void commitNetworkChanges() 936 { 937 for (const auto &channel : channelConfig) 938 { 939 if (channel.second->flush) 940 { 941 applyChanges(channel.first); 942 } 943 } 944 } 945 946 void createNetworkTimer() 947 { 948 if (!networkTimer) 949 { 950 std::function<void()> networkTimerCallback( 951 std::bind(&commitNetworkChanges)); 952 953 networkTimer = 954 std::make_unique<phosphor::ipmi::Timer>( 955 ipmid_get_sd_event_connection(), 956 networkTimerCallback); 957 } 958 959 } 960 961 void register_netfn_transport_functions() 962 { 963 // As this timer is only for transport handler 964 // so creating it here. 965 createNetworkTimer(); 966 // <Wildcard Command> 967 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard, 968 PRIVILEGE_USER); 969 970 // <Set LAN Configuration Parameters> 971 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan, 972 PRIVILEGE_ADMIN); 973 974 // <Get LAN Configuration Parameters> 975 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan, 976 PRIVILEGE_OPERATOR); 977 978 return; 979 } 980