blob: 0fd25f9fcefba5e6f02ba62d14a5b6fe6a938122 [file] [log] [blame]
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001#include <stdio.h>
2#include <string.h>
3#include <stdint.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -06004#include <arpa/inet.h>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05005
6#include "ipmid-api.h"
7#include "ipmid.H"
8#include "transporthandler.h"
9
Hariharasubramanian R83951912016-01-20 07:06:36 -060010#define SYSTEMD_NETWORKD_DBUS 1
11
12#ifdef SYSTEMD_NETWORKD_DBUS
13#include <systemd/sd-bus.h>
14#endif
15
16// OpenBMC System Manager dbus framework
17const char *app = "org.openbmc.NetworkManager";
18const char *obj = "/org/openbmc/NetworkManager/Interface";
19const char *ifc = "org.openbmc.NetworkManager";
20
Adriana Kobylake08fbc62016-02-09 16:17:23 -060021const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx
22const int SIZE_LAN_PARM = 16; //xxx.xxx.xxx.xxx
23
Hariharasubramanian R83951912016-01-20 07:06:36 -060024char cur_ipaddr [16] = "";
25char cur_netmask [16] = "";
26char cur_gateway [16] = "";
27
28char new_ipaddr [16] = "";
29char new_netmask [16] = "";
30char new_gateway [16] = "";
31
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050032void register_netfn_transport_functions() __attribute__((constructor));
33
34ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
35 ipmi_request_t request, ipmi_response_t response,
36 ipmi_data_len_t data_len, ipmi_context_t context)
37{
38 printf("Handling TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
39 // Status code.
40 ipmi_ret_t rc = IPMI_CC_OK;
41 *data_len = 0;
42 return rc;
43}
44
45struct set_lan_t {
46 uint8_t channel;
47 uint8_t parameter;
48 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
49} __attribute__ ((packed));
50
51ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
52 ipmi_request_t request, ipmi_response_t response,
53 ipmi_data_len_t data_len, ipmi_context_t context)
54{
55 ipmi_ret_t rc = IPMI_CC_OK;
56 *data_len = 0;
Adriana Kobylake08fbc62016-02-09 16:17:23 -060057 sd_bus *bus = ipmid_get_sd_bus_connection();
vishwa1eaea4f2016-02-26 11:57:40 -060058 sd_bus_message *reply = NULL;
Adriana Kobylake08fbc62016-02-09 16:17:23 -060059 sd_bus_error error = SD_BUS_ERROR_NULL;
60 int r = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050061
62 printf("IPMI SET_LAN\n");
63
64 set_lan_t *reqptr = (set_lan_t*) request;
65
66 // TODO Use dbus interface once available. For now use cmd line.
67 // TODO Add the rest of the parameters like setting auth type
68 // TODO Add error handling
69
Adriana Kobylake08fbc62016-02-09 16:17:23 -060070 if (reqptr->parameter == LAN_PARM_IP)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050071 {
Adriana Kobylake08fbc62016-02-09 16:17:23 -060072 snprintf(new_ipaddr, SIZE_LAN_PARM, "%d.%d.%d.%d",
73 reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050074 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -060075 else if (reqptr->parameter == LAN_PARM_MAC)
Adriana Kobylakd54a9dd2016-02-03 17:25:54 -060076 {
Adriana Kobylake08fbc62016-02-09 16:17:23 -060077 char mac[SIZE_MAC];
Adriana Kobylakd54a9dd2016-02-03 17:25:54 -060078
Adriana Kobylake08fbc62016-02-09 16:17:23 -060079 snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x",
Adriana Kobylakd54a9dd2016-02-03 17:25:54 -060080 reqptr->data[0],
81 reqptr->data[1],
82 reqptr->data[2],
83 reqptr->data[3],
84 reqptr->data[4],
85 reqptr->data[5]);
86
vishwa1eaea4f2016-02-26 11:57:40 -060087 r = sd_bus_call_method(bus,app,obj,ifc,"SetHwAddress",
88 &error, &reply, "s", mac);
Adriana Kobylakd54a9dd2016-02-03 17:25:54 -060089 if (r < 0) {
90 fprintf(stderr, "Failed to call method: %s\n", strerror(-r));
Adriana Kobylakd54a9dd2016-02-03 17:25:54 -060091 }
92 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -060093 else if (reqptr->parameter == LAN_PARM_SUBNET)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050094 {
Adriana Kobylake08fbc62016-02-09 16:17:23 -060095 snprintf(new_netmask, SIZE_LAN_PARM, "%d.%d.%d.%d",
96 reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050097 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -060098 else if (reqptr->parameter == LAN_PARM_GATEWAY)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050099 {
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600100 snprintf(new_gateway, SIZE_LAN_PARM, "%d.%d.%d.%d",
101 reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600102 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600103 else if (reqptr->parameter == LAN_PARM_INPROGRESS) // Apply config
Hariharasubramanian R83951912016-01-20 07:06:36 -0600104 {
Hariharasubramanian R83951912016-01-20 07:06:36 -0600105 if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, ""))
106 {
107 fprintf(stderr,"ERROR: Incomplete LAN Parameters\n");
108 return -1;
109 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600110
111 if (strcmp(cur_ipaddr, ""))
112 {
vishwa1eaea4f2016-02-26 11:57:40 -0600113 r = sd_bus_call_method(bus, // On the System Bus
114 app, // Service to contact
115 obj, // Object path
116 ifc, // Interface name
117 "DelAddress4", // Method to be called
118 &error, // object to return error
119 &reply, // Response message on success
120 "ssss", // input message (dev,ip,nm,gw)
121 "eth0",
122 cur_ipaddr,
123 cur_netmask,
124 cur_gateway);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600125 }
126
vishwa1eaea4f2016-02-26 11:57:40 -0600127 if(r < 0)
Hariharasubramanian R83951912016-01-20 07:06:36 -0600128 {
vishwa1eaea4f2016-02-26 11:57:40 -0600129 fprintf(stderr, "Failed to remove existing IP %s: %s\n", cur_ipaddr, error.message);
130 goto finish;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600131 }
132
vishwa1eaea4f2016-02-26 11:57:40 -0600133 sd_bus_error_free(&error);
134 reply = sd_bus_message_unref(reply);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600135
vishwa1eaea4f2016-02-26 11:57:40 -0600136 r = sd_bus_call_method(bus, // On the System Bus
137 app, // Service to contact
138 obj, // Object path
139 ifc, // Interface name
140 "AddAddress4", // Method to be called
141 &error, // object to return error
142 &reply, // Response message on success
143 "ssss", // input message (dev,ip,nm,gw)
144 "eth0",
145 new_ipaddr,
146 new_netmask,
147 new_gateway);
148 if(r < 0)
Hariharasubramanian R83951912016-01-20 07:06:36 -0600149 {
vishwa1eaea4f2016-02-26 11:57:40 -0600150 fprintf(stderr, "Failed to set IP %s: %s\n", new_ipaddr, error.message);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600151 }
vishwa1eaea4f2016-02-26 11:57:40 -0600152 else
153 {
154 strcpy (cur_ipaddr, new_ipaddr);
155 strcpy (cur_netmask, new_netmask);
156 strcpy (cur_gateway, new_gateway);
157 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500158 }
159 else
160 {
161 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
vishwa1eaea4f2016-02-26 11:57:40 -0600162 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500163 }
164
vishwa1eaea4f2016-02-26 11:57:40 -0600165finish:
166 // Clenaup the resources allocated reply and error
167 sd_bus_error_free(&error);
168 reply = sd_bus_message_unref(reply);
169
170 return (r < 0) ? -1 : rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500171}
172
173struct get_lan_t {
174 uint8_t rev_channel;
175 uint8_t parameter;
176 uint8_t parameter_set;
177 uint8_t parameter_block;
178} __attribute__ ((packed));
179
180ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
181 ipmi_request_t request, ipmi_response_t response,
182 ipmi_data_len_t data_len, ipmi_context_t context)
183{
184 ipmi_ret_t rc = IPMI_CC_OK;
185 *data_len = 0;
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600186 sd_bus *bus = ipmid_get_sd_bus_connection();
vishwa1eaea4f2016-02-26 11:57:40 -0600187 sd_bus_message *reply = NULL;
Adriana Kobylak9355f612016-02-08 17:30:37 -0600188 sd_bus_error error = SD_BUS_ERROR_NULL;
189 int r = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500190 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Hariharasubramanian R83951912016-01-20 07:06:36 -0600191
192 int family;
193 unsigned char prefixlen;
194 unsigned char scope;
195 unsigned int flags;
Adriana Kobylak342df102016-02-10 13:48:16 -0600196 char *saddr = NULL;
Adriana Kobylak9355f612016-02-08 17:30:37 -0600197 int i = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500198
199 printf("IPMI GET_LAN\n");
200
201 get_lan_t *reqptr = (get_lan_t*) request;
202
203 if (reqptr->rev_channel & 0x80) // Revision is bit 7
204 {
205 // Only current revision was requested
206 *data_len = sizeof(current_revision);
207 memcpy(response, &current_revision, *data_len);
208 return IPMI_CC_OK;
209 }
210
211 // TODO Use dbus interface once available. For now use ip cmd.
212 // TODO Add the rest of the parameters, like gateway
213
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600214 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500215 {
216 uint8_t buf[] = {current_revision,0};
217 *data_len = sizeof(buf);
218 memcpy(response, &buf, *data_len);
219 return IPMI_CC_OK;
220 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600221 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500222 {
223 uint8_t buf[] = {current_revision,0x04};
224 *data_len = sizeof(buf);
225 memcpy(response, &buf, *data_len);
226 return IPMI_CC_OK;
227 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600228 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500229 {
230 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
231 *data_len = sizeof(buf);
232 memcpy(response, &buf, *data_len);
233 return IPMI_CC_OK;
234 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600235 else if (reqptr->parameter == LAN_PARM_IP)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500236 {
Hariharasubramanian R83951912016-01-20 07:06:36 -0600237 const char* device = "eth0";
Adriana Kobylak342df102016-02-10 13:48:16 -0600238 uint8_t buf[5]; // Size of expected IPMI response msg
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500239
vishwa1eaea4f2016-02-26 11:57:40 -0600240 r = sd_bus_call_method(bus,app,obj,ifc,"GetAddress4",
241 &error, &reply, "s", device);
242 if (r < 0)
243 {
Adriana Kobylak342df102016-02-10 13:48:16 -0600244 fprintf(stderr, "Failed to call method: %s\n", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600245 rc = -1;
246 goto finish;
Adriana Kobylak342df102016-02-10 13:48:16 -0600247 }
vishwa1eaea4f2016-02-26 11:57:40 -0600248 r = sd_bus_message_enter_container (reply, 'a', "(iyyus)");
249 if(r < 0)
Hariharasubramanian R83951912016-01-20 07:06:36 -0600250 {
251 fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc));
vishwa1eaea4f2016-02-26 11:57:40 -0600252 rc = -1;
253 goto finish;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600254 }
vishwa1eaea4f2016-02-26 11:57:40 -0600255 r = sd_bus_message_read(reply, "(iyyus)", &family, &prefixlen, &scope, &flags, &saddr);
256 if (r < 0)
Hariharasubramanian R83951912016-01-20 07:06:36 -0600257 {
Adriana Kobylak342df102016-02-10 13:48:16 -0600258 fprintf(stderr, "Failed to receive response: %s\n", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600259 rc = -1;
260 goto finish;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600261 }
262
Adriana Kobylak342df102016-02-10 13:48:16 -0600263 printf("%s:%d:%d:%d:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, scope, flags, saddr);
264
Hariharasubramanian R83951912016-01-20 07:06:36 -0600265 memcpy((void*)&buf[0], &current_revision, 1);
Adriana Kobylak342df102016-02-10 13:48:16 -0600266
267 // Parse IP address
268 char *tokptr = NULL;
269 char* digit = strtok_r(saddr, ".", &tokptr);
270 if (digit == NULL)
271 {
272 fprintf(stderr, "Unexpected IP format: %s", saddr);
vishwa1eaea4f2016-02-26 11:57:40 -0600273 rc = IPMI_CC_RESPONSE_ERROR;
274 goto finish;
Adriana Kobylak342df102016-02-10 13:48:16 -0600275 }
276 i = 0;
277 while (digit != NULL)
278 {
279 int resp_byte = strtoul(digit, NULL, 10);
280 memcpy((void*)&buf[i+1], &resp_byte, 1);
281 i++;
282 digit = strtok_r(NULL, ".", &tokptr);
283 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600284
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500285 *data_len = sizeof(buf);
286 memcpy(response, &buf, *data_len);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600287
vishwa1eaea4f2016-02-26 11:57:40 -0600288 rc = IPMI_CC_OK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500289 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600290 else if (reqptr->parameter == LAN_PARM_MAC)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500291 {
292 //string to parse: link/ether xx:xx:xx:xx:xx:xx
293
Hariharasubramanian R83951912016-01-20 07:06:36 -0600294 const char* device = "eth0";
Hariharasubramanian R83951912016-01-20 07:06:36 -0600295 uint8_t buf[7];
Adriana Kobylak9355f612016-02-08 17:30:37 -0600296 char *eaddr1 = NULL;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500297
vishwa1eaea4f2016-02-26 11:57:40 -0600298 r = sd_bus_call_method(bus,app,obj,ifc,"GetHwAddress",
299 &error, &reply, "s", device);
300 if (r < 0)
301 {
302 fprintf(stderr, "Failed to call GetHwAddress: %s\n", strerror(-r));
303 rc = -1;
304 goto finish;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600305 }
Adriana Kobylak9355f612016-02-08 17:30:37 -0600306 r = sd_bus_message_read(reply, "s", &eaddr1);
vishwa1eaea4f2016-02-26 11:57:40 -0600307 if (r < 0)
308 {
Adriana Kobylak9355f612016-02-08 17:30:37 -0600309 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600310 rc = IPMI_CC_RESPONSE_ERROR;
311 goto finish;
Adriana Kobylak9355f612016-02-08 17:30:37 -0600312 }
313 if (eaddr1 == NULL)
314 {
315 fprintf(stderr, "Failed to get a valid response: %s", strerror(-r));
vishwa1eaea4f2016-02-26 11:57:40 -0600316 rc = IPMI_CC_RESPONSE_ERROR;
317 goto finish;
Adriana Kobylak9355f612016-02-08 17:30:37 -0600318 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600319
320 memcpy((void*)&buf[0], &current_revision, 1);
Adriana Kobylak9355f612016-02-08 17:30:37 -0600321
322 char *tokptr = NULL;
323 char* digit = strtok_r(eaddr1, ":", &tokptr);
324 if (digit == NULL)
325 {
326 fprintf(stderr, "Unexpected MAC format: %s", eaddr1);
vishwa1eaea4f2016-02-26 11:57:40 -0600327 rc = IPMI_CC_RESPONSE_ERROR;
328 goto finish;
Adriana Kobylak9355f612016-02-08 17:30:37 -0600329 }
330
331 i=0;
332 while (digit != NULL)
333 {
334 int resp_byte = strtoul(digit, NULL, 16);
335 memcpy((void*)&buf[i+1], &resp_byte, 1);
336 i++;
337 digit = strtok_r(NULL, ":", &tokptr);
338 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600339
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500340 *data_len = sizeof(buf);
341 memcpy(response, &buf, *data_len);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600342
vishwa1eaea4f2016-02-26 11:57:40 -0600343 rc = IPMI_CC_OK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500344 }
345 else
346 {
347 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
vishwa1eaea4f2016-02-26 11:57:40 -0600348 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500349 }
350
vishwa1eaea4f2016-02-26 11:57:40 -0600351finish:
352 sd_bus_error_free(&error);
353 reply = sd_bus_message_unref(reply);
354
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500355 return rc;
356}
357
358void register_netfn_transport_functions()
359{
360 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD);
361 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard);
362
363 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN);
364 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan);
365
366 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN);
367 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan);
368
369 return;
370}