Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
ipmi/linux/main.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
214 lines (170 sloc)
6.58 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright Jordan Sissel, 2018 | |
This file is part of jordansissel/ipmi. | |
jordansissel/ipmi is free software: you can redistribute it and/or modify | |
it under the terms of the GNU Affero General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
jordansissel/ipmi is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU Affero General Public License for more details. | |
You should have received a copy of the GNU Affero General Public License | |
along with jordansissel/ipmi. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include "insist.h" | |
#include "ipmi_mongoose.h" | |
#include "mongoose.h" | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include "client.h" | |
#include "ipmi.h" | |
int mgos(int argc, char **argv) { | |
if (argc != 3) { | |
printf("Usage: %s <host> <password>\n", argv[0]); | |
return 1; | |
} | |
const auto hostname = argv[1]; | |
uint8_t password[16] = {}; | |
strncpy((char *)password, argv[2], 16); | |
auto client = new IPMI::Client(password); | |
struct mg_mgr mgr; | |
mg_mgr_init(&mgr, NULL); | |
struct mg_connect_opts opts = {.user_data = client}; | |
char *address; | |
asprintf(&address, "udp://%s:623", hostname); | |
auto conn = | |
mg_connect_opt(&mgr, address, ipmi_client_connection_handler, opts); | |
free(address); | |
client->setConnection(conn); | |
client->chassisControl(IPMI::ChassisControlCommand::PowerUp); | |
for (;;) { // Start infinite event loop | |
// if (client->getState() == IPMI::ClientState::NeedChassisControlResponse) | |
// { break; | |
// } | |
mg_mgr_poll(&mgr, 1000); | |
} | |
mg_mgr_free(&mgr); | |
delete client; | |
return 0; | |
} | |
int posix(int argc, char **argv) { | |
if (argc != 3) { | |
printf("Usage: %s <host> <password>\n", argv[0]); | |
return 1; | |
} | |
srandom(time(NULL)); | |
const auto hostname = argv[1]; | |
uint8_t password[16] = {}; | |
strncpy((char *)password, argv[2], 16); | |
struct addrinfo *addresses, hints; | |
memset(&hints, 0, sizeof(hints)); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_socktype = SOCK_DGRAM; | |
hints.ai_protocol = 0; | |
const int rc = getaddrinfo(hostname, "623", &hints, &addresses); | |
insist_return(rc == 0, 1, "getaddrinfo() failed: %d: %s", rc, | |
gai_strerror(rc)); | |
int fd = socket(addresses->ai_family, addresses->ai_socktype, | |
addresses->ai_protocol); | |
insist_return(fd >= 0, 1, "socket() failed: %d: %s", errno, strerror(errno)); | |
char name[50]; | |
inet_ntop(addresses->ai_family, | |
(addresses->ai_family == AF_INET) | |
? (const void *)&( | |
((struct sockaddr_in *)addresses->ai_addr)->sin_addr) | |
: (const void *)&( | |
((struct sockaddr_in6 *)addresses->ai_addr)->sin6_addr), | |
name, 50); | |
printf("%s == %s\n", hostname, name); | |
struct mbuf buf; | |
mbuf_init(&buf, 20); | |
// Send Get Channel Authentication Capabilities | |
IPMI::getChannelAuthenticationCapabilities(buf); | |
printf("Sending: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
sendto(fd, buf.buf, buf.len, 0, addresses->ai_addr, addresses->ai_addrlen); | |
mbuf_remove(&buf, buf.len); | |
// Receive Get Channel Authentication Capabilities Response | |
char recv[1500]; | |
int b = recvfrom(fd, recv, 1500, 0, NULL, NULL); | |
mbuf_append(&buf, recv, b); | |
printf("Received: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
IPMI::RMCP rmcp; | |
IPMI::IPMB ipmb; | |
IPMI::Session session; | |
IPMI::GetChannelAuthenticationCapabilities::Response response; | |
IPMI::decode(buf, rmcp, ipmb, session, response); | |
if (response.completion_code != 0) { | |
printf("ChannelAuthenticationCapabilities request failed.\n"); | |
return 1; | |
} | |
if (!response.hasMD5()) { | |
printf("Remote claims no support for MD5 authcode. Cannot continue.\n"); | |
return 1; | |
} | |
// Send Get Session Challenge | |
IPMI::getSessionChallenge(buf); | |
printf("Sending: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
sendto(fd, buf.buf, buf.len, 0, addresses->ai_addr, addresses->ai_addrlen); | |
mbuf_remove(&buf, buf.len); | |
// Receive Get Session Challenge Response | |
b = recvfrom(fd, recv, 1500, 0, NULL, NULL); | |
printf("Before read len: %zd\n", buf.len); | |
mbuf_append(&buf, recv, b); | |
printf("After read len: %zd\n", buf.len); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
IPMI::GetSessionChallenge::Response challengeResponse; | |
IPMI::decode(buf, rmcp, ipmb, session, challengeResponse); | |
// All future commands need an auth_code of: | |
// md5(password + session id + data + sequence + password) | |
// XXX: Add password. | |
uint32_t sequence = (uint32_t)random(); | |
IPMI::activateSession(buf, password, sequence, challengeResponse.session_id, | |
challengeResponse.challenge); | |
printf("! Sending: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
sendto(fd, buf.buf, buf.len, 0, addresses->ai_addr, addresses->ai_addrlen); | |
mbuf_remove(&buf, buf.len); | |
// Receive ActivateSession Response | |
b = recvfrom(fd, recv, 1500, 0, NULL, NULL); | |
mbuf_append(&buf, recv, b); | |
printf("Received: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
IPMI::ActivateSession::Response activateResponse; | |
IPMI::decode(buf, password, rmcp, ipmb, session, activateResponse); | |
uint32_t session_id = activateResponse.session; | |
sequence = activateResponse.sequence; | |
// Send SetSessionPrivilege | |
IPMI::setSessionPrivilege(buf, session_id, sequence, password, | |
IPMI::AuthenticationCapability::Administrator); | |
sequence++; | |
printf("!! Sending: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
sendto(fd, buf.buf, buf.len, 0, addresses->ai_addr, addresses->ai_addrlen); | |
mbuf_remove(&buf, buf.len); | |
// Receive SetSessionPrivilege response | |
b = recvfrom(fd, recv, 1500, 0, NULL, NULL); | |
mbuf_append(&buf, recv, b); | |
printf("Received: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
IPMI::SetSessionPrivilege::Response privilegeResponse; | |
IPMI::decode(buf, password, rmcp, ipmb, session, privilegeResponse); | |
// Send Chassis Control | |
IPMI::chassisControl(buf, challengeResponse.session_id, sequence, password, | |
IPMI::ChassisControlCommand::PowerUp); | |
sequence++; | |
printf("!! Sending: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
sendto(fd, buf.buf, buf.len, 0, addresses->ai_addr, addresses->ai_addrlen); | |
// Receive Chassis Control response | |
b = recvfrom(fd, recv, 1500, 0, NULL, NULL); | |
mbuf_append(&buf, recv, b); | |
printf("Received: \n"); | |
mg_hexdumpf(stdout, buf.buf, buf.len); | |
return 0; | |
} | |
int main(int argc, char **argv) { return mgos(argc, argv); } |