blob: d43f1f960f24b3c872980084b57f13954d578b3f [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();
58 sd_bus_message *reply = NULL, *m = NULL;
59 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
87 r = sd_bus_message_new_method_call(bus,&m,app,obj,ifc,"SetHwAddress");
88 if (r < 0) {
89 fprintf(stderr, "Failed to add method object: %s\n", strerror(-r));
90 return -1;
91 }
92 r = sd_bus_message_append(m, "s", mac);
93 if (r < 0) {
94 fprintf(stderr, "Failed to append message data: %s\n", strerror(-r));
95 return -1;
96 }
97 r = sd_bus_call(bus, m, 0, &error, &reply);
98 if (r < 0) {
99 fprintf(stderr, "Failed to call method: %s\n", strerror(-r));
100 return -1;
101 }
102 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600103 else if (reqptr->parameter == LAN_PARM_SUBNET)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500104 {
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600105 snprintf(new_netmask, SIZE_LAN_PARM, "%d.%d.%d.%d",
106 reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500107 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600108 else if (reqptr->parameter == LAN_PARM_GATEWAY)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500109 {
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600110 snprintf(new_gateway, SIZE_LAN_PARM, "%d.%d.%d.%d",
111 reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600112 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600113 else if (reqptr->parameter == LAN_PARM_INPROGRESS) // Apply config
Hariharasubramanian R83951912016-01-20 07:06:36 -0600114 {
115 int rc = 0;
116 sd_bus_message *req = NULL;
117 sd_bus_message *res = NULL;
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600118 sd_bus *bus1 = NULL;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600119 sd_bus_error err = SD_BUS_ERROR_NULL;
120
121 if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, ""))
122 {
123 fprintf(stderr,"ERROR: Incomplete LAN Parameters\n");
124 return -1;
125 }
126
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600127 rc = sd_bus_open_system(&bus1);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600128 if(rc < 0)
129 {
130 fprintf(stderr,"ERROR: Getting a SYSTEM bus hook\n");
131 return -1;
132 }
133
134 if (strcmp(cur_ipaddr, ""))
135 {
136 sd_bus_error_free(&err);
137 sd_bus_message_unref(req);
138 sd_bus_message_unref(res);
139
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600140 rc = sd_bus_call_method(bus1, // On the System Bus
Hariharasubramanian R83951912016-01-20 07:06:36 -0600141 app, // Service to contact
142 obj, // Object path
143 ifc, // Interface name
144 "DelAddress4", // Method to be called
145 &err, // object to return error
146 &res, // Response message on success
147 "ssss", // input message (dev,ip,nm,gw)
148 "eth0",
149 cur_ipaddr,
150 cur_netmask,
151 cur_gateway);
152 }
153
154 if(rc < 0)
155 {
156 fprintf(stderr, "Failed to remove existing IP %s: %s\n", cur_ipaddr, err.message);
157 return -1;
158 }
159
160 sd_bus_error_free(&err);
161 sd_bus_message_unref(req);
162 sd_bus_message_unref(res);
163
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600164 rc = sd_bus_call_method(bus1, // On the System Bus
Hariharasubramanian R83951912016-01-20 07:06:36 -0600165 app, // Service to contact
166 obj, // Object path
167 ifc, // Interface name
168 "AddAddress4", // Method to be called
169 &err, // object to return error
170 &res, // Response message on success
171 "ssss", // input message (dev,ip,nm,gw)
172 "eth0",
173 new_ipaddr,
174 new_netmask,
175 new_gateway);
176 if(rc < 0)
177 {
178 fprintf(stderr, "Failed to set IP %s: %s\n", new_ipaddr, err.message);
179 return -1;
180 }
181
182 strcpy (cur_ipaddr, new_ipaddr);
183 strcpy (cur_netmask, new_netmask);
184 strcpy (cur_gateway, new_gateway);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500185 }
186 else
187 {
188 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
189 return IPMI_CC_PARM_NOT_SUPPORTED;
190 }
191
192 return rc;
193}
194
195struct get_lan_t {
196 uint8_t rev_channel;
197 uint8_t parameter;
198 uint8_t parameter_set;
199 uint8_t parameter_block;
200} __attribute__ ((packed));
201
202ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
203 ipmi_request_t request, ipmi_response_t response,
204 ipmi_data_len_t data_len, ipmi_context_t context)
205{
206 ipmi_ret_t rc = IPMI_CC_OK;
207 *data_len = 0;
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600208 sd_bus *bus = ipmid_get_sd_bus_connection();
Adriana Kobylak9355f612016-02-08 17:30:37 -0600209 sd_bus_message *reply = NULL, *m = NULL;
210 sd_bus_error error = SD_BUS_ERROR_NULL;
211 int r = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500212 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Hariharasubramanian R83951912016-01-20 07:06:36 -0600213
214 int family;
215 unsigned char prefixlen;
216 unsigned char scope;
217 unsigned int flags;
Adriana Kobylak342df102016-02-10 13:48:16 -0600218 char *saddr = NULL;
Adriana Kobylak9355f612016-02-08 17:30:37 -0600219 int i = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500220
221 printf("IPMI GET_LAN\n");
222
223 get_lan_t *reqptr = (get_lan_t*) request;
224
225 if (reqptr->rev_channel & 0x80) // Revision is bit 7
226 {
227 // Only current revision was requested
228 *data_len = sizeof(current_revision);
229 memcpy(response, &current_revision, *data_len);
230 return IPMI_CC_OK;
231 }
232
233 // TODO Use dbus interface once available. For now use ip cmd.
234 // TODO Add the rest of the parameters, like gateway
235
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600236 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500237 {
238 uint8_t buf[] = {current_revision,0};
239 *data_len = sizeof(buf);
240 memcpy(response, &buf, *data_len);
241 return IPMI_CC_OK;
242 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600243 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500244 {
245 uint8_t buf[] = {current_revision,0x04};
246 *data_len = sizeof(buf);
247 memcpy(response, &buf, *data_len);
248 return IPMI_CC_OK;
249 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600250 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500251 {
252 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
253 *data_len = sizeof(buf);
254 memcpy(response, &buf, *data_len);
255 return IPMI_CC_OK;
256 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600257 else if (reqptr->parameter == LAN_PARM_IP)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500258 {
Hariharasubramanian R83951912016-01-20 07:06:36 -0600259 const char* device = "eth0";
Adriana Kobylak342df102016-02-10 13:48:16 -0600260 uint8_t buf[5]; // Size of expected IPMI response msg
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500261
Adriana Kobylak342df102016-02-10 13:48:16 -0600262 r = sd_bus_message_new_method_call(bus,&m,app,obj,ifc,"GetAddress4");
263 if (r < 0) {
264 fprintf(stderr, "Failed to add method object: %s\n", strerror(-r));
Hariharasubramanian R83951912016-01-20 07:06:36 -0600265 return -1;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500266 }
Adriana Kobylak342df102016-02-10 13:48:16 -0600267 r = sd_bus_message_append(m, "s", device);
268 if (r < 0) {
269 fprintf(stderr, "Failed to append message data: %s\n", strerror(-r));
Hariharasubramanian R83951912016-01-20 07:06:36 -0600270 return -1;
271 }
Adriana Kobylak342df102016-02-10 13:48:16 -0600272 r = sd_bus_call(bus, m, 0, &error, &reply);
273 if (r < 0) {
274 fprintf(stderr, "Failed to call method: %s\n", strerror(-r));
275 return -1;
276 }
277 rc = sd_bus_message_enter_container (reply, 'a', "(iyyus)");
Hariharasubramanian R83951912016-01-20 07:06:36 -0600278 if(rc < 0)
279 {
280 fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc));
281 return -1;
282 }
Adriana Kobylak342df102016-02-10 13:48:16 -0600283 rc = sd_bus_message_read(reply, "(iyyus)", &family, &prefixlen, &scope, &flags, &saddr);
284 if (rc < 0)
Hariharasubramanian R83951912016-01-20 07:06:36 -0600285 {
Adriana Kobylak342df102016-02-10 13:48:16 -0600286 fprintf(stderr, "Failed to receive response: %s\n", strerror(-r));
Hariharasubramanian R83951912016-01-20 07:06:36 -0600287 return -1;
288 }
289
Adriana Kobylak342df102016-02-10 13:48:16 -0600290 printf("%s:%d:%d:%d:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, scope, flags, saddr);
291
Hariharasubramanian R83951912016-01-20 07:06:36 -0600292 memcpy((void*)&buf[0], &current_revision, 1);
Adriana Kobylak342df102016-02-10 13:48:16 -0600293
294 // Parse IP address
295 char *tokptr = NULL;
296 char* digit = strtok_r(saddr, ".", &tokptr);
297 if (digit == NULL)
298 {
299 fprintf(stderr, "Unexpected IP format: %s", saddr);
300 return IPMI_CC_RESPONSE_ERROR;
301 }
302 i = 0;
303 while (digit != NULL)
304 {
305 int resp_byte = strtoul(digit, NULL, 10);
306 memcpy((void*)&buf[i+1], &resp_byte, 1);
307 i++;
308 digit = strtok_r(NULL, ".", &tokptr);
309 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600310
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500311 *data_len = sizeof(buf);
312 memcpy(response, &buf, *data_len);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600313
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500314 return IPMI_CC_OK;
315 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600316 else if (reqptr->parameter == LAN_PARM_MAC)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500317 {
318 //string to parse: link/ether xx:xx:xx:xx:xx:xx
319
Hariharasubramanian R83951912016-01-20 07:06:36 -0600320 const char* device = "eth0";
Hariharasubramanian R83951912016-01-20 07:06:36 -0600321 uint8_t buf[7];
Adriana Kobylak9355f612016-02-08 17:30:37 -0600322 char *eaddr1 = NULL;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500323
Adriana Kobylak9355f612016-02-08 17:30:37 -0600324 r = sd_bus_message_new_method_call(bus,&m,app,obj,ifc,"GetHwAddress");
325 if (r < 0) {
326 fprintf(stderr, "Failed to add method object: %s\n", strerror(-r));
Hariharasubramanian R83951912016-01-20 07:06:36 -0600327 return -1;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500328 }
Adriana Kobylak9355f612016-02-08 17:30:37 -0600329 r = sd_bus_message_append(m, "s", device);
330 if (r < 0) {
331 fprintf(stderr, "Failed to append message data: %s\n", strerror(-r));
Hariharasubramanian R83951912016-01-20 07:06:36 -0600332 return -1;
333 }
Adriana Kobylak9355f612016-02-08 17:30:37 -0600334 r = sd_bus_call(bus, m, 0, &error, &reply);
335 if (r < 0) {
336 fprintf(stderr, "Failed to call method: %s\n", strerror(-r));
Hariharasubramanian R83951912016-01-20 07:06:36 -0600337 return -1;
338 }
Adriana Kobylak9355f612016-02-08 17:30:37 -0600339 r = sd_bus_message_read(reply, "s", &eaddr1);
340 if (r < 0) {
341 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
342 return IPMI_CC_RESPONSE_ERROR;
343 }
344 if (eaddr1 == NULL)
345 {
346 fprintf(stderr, "Failed to get a valid response: %s", strerror(-r));
347 return IPMI_CC_RESPONSE_ERROR;
348 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600349
350 memcpy((void*)&buf[0], &current_revision, 1);
Adriana Kobylak9355f612016-02-08 17:30:37 -0600351
352 char *tokptr = NULL;
353 char* digit = strtok_r(eaddr1, ":", &tokptr);
354 if (digit == NULL)
355 {
356 fprintf(stderr, "Unexpected MAC format: %s", eaddr1);
357 return IPMI_CC_RESPONSE_ERROR;
358 }
359
360 i=0;
361 while (digit != NULL)
362 {
363 int resp_byte = strtoul(digit, NULL, 16);
364 memcpy((void*)&buf[i+1], &resp_byte, 1);
365 i++;
366 digit = strtok_r(NULL, ":", &tokptr);
367 }
Hariharasubramanian R83951912016-01-20 07:06:36 -0600368
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500369 *data_len = sizeof(buf);
370 memcpy(response, &buf, *data_len);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600371
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500372 return IPMI_CC_OK;
373 }
374 else
375 {
376 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
377 return IPMI_CC_PARM_NOT_SUPPORTED;
378 }
379
380 return rc;
381}
382
383void register_netfn_transport_functions()
384{
385 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD);
386 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard);
387
388 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN);
389 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan);
390
391 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN);
392 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan);
393
394 return;
395}