blob: dac8fe81d0427f592430df6a1eac1006147f9e0f [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
21char cur_ipaddr [16] = "";
22char cur_netmask [16] = "";
23char cur_gateway [16] = "";
24
25char new_ipaddr [16] = "";
26char new_netmask [16] = "";
27char new_gateway [16] = "";
28
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050029void register_netfn_transport_functions() __attribute__((constructor));
30
31ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
32 ipmi_request_t request, ipmi_response_t response,
33 ipmi_data_len_t data_len, ipmi_context_t context)
34{
35 printf("Handling TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
36 // Status code.
37 ipmi_ret_t rc = IPMI_CC_OK;
38 *data_len = 0;
39 return rc;
40}
41
42struct set_lan_t {
43 uint8_t channel;
44 uint8_t parameter;
45 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
46} __attribute__ ((packed));
47
48ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
49 ipmi_request_t request, ipmi_response_t response,
50 ipmi_data_len_t data_len, ipmi_context_t context)
51{
52 ipmi_ret_t rc = IPMI_CC_OK;
53 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050054
55 printf("IPMI SET_LAN\n");
56
57 set_lan_t *reqptr = (set_lan_t*) request;
58
59 // TODO Use dbus interface once available. For now use cmd line.
60 // TODO Add the rest of the parameters like setting auth type
61 // TODO Add error handling
62
63 if (reqptr->parameter == 3) // IP
64 {
Hariharasubramanian R83951912016-01-20 07:06:36 -060065 sprintf(new_ipaddr, "%d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050066 }
67 else if (reqptr->parameter == 6) // Subnet
68 {
Hariharasubramanian R83951912016-01-20 07:06:36 -060069 sprintf(new_netmask, "%d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050070 }
71 else if (reqptr->parameter == 12) // Gateway
72 {
Hariharasubramanian R83951912016-01-20 07:06:36 -060073 sprintf(new_gateway, "%d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]);
74 }
75 else if (reqptr->parameter == 0) // Apply config
76 {
77 int rc = 0;
78 sd_bus_message *req = NULL;
79 sd_bus_message *res = NULL;
80 sd_bus *bus = NULL;
81 sd_bus_error err = SD_BUS_ERROR_NULL;
82
83 if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, ""))
84 {
85 fprintf(stderr,"ERROR: Incomplete LAN Parameters\n");
86 return -1;
87 }
88
89 rc = sd_bus_open_system(&bus);
90 if(rc < 0)
91 {
92 fprintf(stderr,"ERROR: Getting a SYSTEM bus hook\n");
93 return -1;
94 }
95
96 if (strcmp(cur_ipaddr, ""))
97 {
98 sd_bus_error_free(&err);
99 sd_bus_message_unref(req);
100 sd_bus_message_unref(res);
101
102 rc = sd_bus_call_method(bus, // On the System Bus
103 app, // Service to contact
104 obj, // Object path
105 ifc, // Interface name
106 "DelAddress4", // Method to be called
107 &err, // object to return error
108 &res, // Response message on success
109 "ssss", // input message (dev,ip,nm,gw)
110 "eth0",
111 cur_ipaddr,
112 cur_netmask,
113 cur_gateway);
114 }
115
116 if(rc < 0)
117 {
118 fprintf(stderr, "Failed to remove existing IP %s: %s\n", cur_ipaddr, err.message);
119 return -1;
120 }
121
122 sd_bus_error_free(&err);
123 sd_bus_message_unref(req);
124 sd_bus_message_unref(res);
125
126 rc = sd_bus_call_method(bus, // On the System Bus
127 app, // Service to contact
128 obj, // Object path
129 ifc, // Interface name
130 "AddAddress4", // Method to be called
131 &err, // object to return error
132 &res, // Response message on success
133 "ssss", // input message (dev,ip,nm,gw)
134 "eth0",
135 new_ipaddr,
136 new_netmask,
137 new_gateway);
138 if(rc < 0)
139 {
140 fprintf(stderr, "Failed to set IP %s: %s\n", new_ipaddr, err.message);
141 return -1;
142 }
143
144 strcpy (cur_ipaddr, new_ipaddr);
145 strcpy (cur_netmask, new_netmask);
146 strcpy (cur_gateway, new_gateway);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500147 }
148 else
149 {
150 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
151 return IPMI_CC_PARM_NOT_SUPPORTED;
152 }
153
154 return rc;
155}
156
157struct get_lan_t {
158 uint8_t rev_channel;
159 uint8_t parameter;
160 uint8_t parameter_set;
161 uint8_t parameter_block;
162} __attribute__ ((packed));
163
164ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
165 ipmi_request_t request, ipmi_response_t response,
166 ipmi_data_len_t data_len, ipmi_context_t context)
167{
168 ipmi_ret_t rc = IPMI_CC_OK;
169 *data_len = 0;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600170 sd_bus_error err = SD_BUS_ERROR_NULL; /* fixme */
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500171 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Hariharasubramanian R83951912016-01-20 07:06:36 -0600172
173 int family;
174 unsigned char prefixlen;
175 unsigned char scope;
176 unsigned int flags;
177 char saddr [128];
178 char gateway [128];
179 uint8_t buf[11];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500180
181 printf("IPMI GET_LAN\n");
182
183 get_lan_t *reqptr = (get_lan_t*) request;
184
185 if (reqptr->rev_channel & 0x80) // Revision is bit 7
186 {
187 // Only current revision was requested
188 *data_len = sizeof(current_revision);
189 memcpy(response, &current_revision, *data_len);
190 return IPMI_CC_OK;
191 }
192
193 // TODO Use dbus interface once available. For now use ip cmd.
194 // TODO Add the rest of the parameters, like gateway
195
196 if (reqptr->parameter == 0) // In progress
197 {
198 uint8_t buf[] = {current_revision,0};
199 *data_len = sizeof(buf);
200 memcpy(response, &buf, *data_len);
201 return IPMI_CC_OK;
202 }
203 else if (reqptr->parameter == 1) // Authentication support
204 {
205 uint8_t buf[] = {current_revision,0x04};
206 *data_len = sizeof(buf);
207 memcpy(response, &buf, *data_len);
208 return IPMI_CC_OK;
209 }
210 else if (reqptr->parameter == 2) // Authentication enables
211 {
212 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
213 *data_len = sizeof(buf);
214 memcpy(response, &buf, *data_len);
215 return IPMI_CC_OK;
216 }
217 else if (reqptr->parameter == 3) // IP
218 {
Hariharasubramanian R83951912016-01-20 07:06:36 -0600219 const char* device = "eth0";
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500220
Hariharasubramanian R83951912016-01-20 07:06:36 -0600221 sd_bus_message *res = NULL;
222 sd_bus *bus = NULL;
223 sd_bus_error err = SD_BUS_ERROR_NULL;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500224
Hariharasubramanian R83951912016-01-20 07:06:36 -0600225 rc = sd_bus_open_system(&bus);
226 if(rc < 0)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500227 {
Hariharasubramanian R83951912016-01-20 07:06:36 -0600228 fprintf(stderr,"ERROR: Getting a SYSTEM bus hook\n");
229 return -1;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500230 }
231
Hariharasubramanian R83951912016-01-20 07:06:36 -0600232 rc = sd_bus_call_method(bus, // On the System Bus
233 app, // Service to contact
234 obj, // Object path
235 ifc, // Interface name
236 "GetAddress4", // Method to be called
237 &err, // object to return error
238 &res, // Response message on success
239 "s", // input message (dev,ip,nm,gw)
240 "eth0");
241 if(rc < 0)
242 {
243 fprintf(stderr, "Failed to Get IP on interface : %s\n", device);
244 return -1;
245 }
246
247 /* rc = sd_bus_message_read(res, "a(iyyus)s", ...); */
248 rc = sd_bus_message_enter_container (res, 'a', "(iyyus)");
249 if(rc < 0)
250 {
251 fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc));
252 return -1;
253 }
254
255 while ((rc = sd_bus_message_read(res, "(iyyus)", &family, &prefixlen, &scope, &flags, &saddr)) > 0) {
256 printf("%s:%d:%d:%d:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, scope, flags, saddr);
257 }
258
259 rc = sd_bus_message_read (res, "s", &gateway);
260 if(rc < 0)
261 {
262 fprintf(stderr, "Failed to parse gateway from response message:[%s]\n", strerror(-rc));
263 return -1;
264 }
265
266 memcpy((void*)&buf[0], &current_revision, 1);
267 sscanf (saddr, "%c.%c.%c.%c", &buf[1], &buf[2], &buf[3], &buf[4]);
268 buf[5] = family;
269 buf[6] = prefixlen;
270 sscanf (gateway, "%c.%c.%c.%c", &buf[7], &buf[8], &buf[9], &buf[10]);
271
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500272 *data_len = sizeof(buf);
273 memcpy(response, &buf, *data_len);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600274
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500275 return IPMI_CC_OK;
276 }
277 else if (reqptr->parameter == 5) // MAC
278 {
279 //string to parse: link/ether xx:xx:xx:xx:xx:xx
280
Hariharasubramanian R83951912016-01-20 07:06:36 -0600281 const char* device = "eth0";
282 char eaddr [12];
283 uint8_t buf[7];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500284
Hariharasubramanian R83951912016-01-20 07:06:36 -0600285 sd_bus_message *res = NULL;
286 sd_bus *bus = NULL;
287 sd_bus_error err = SD_BUS_ERROR_NULL;
288
289 rc = sd_bus_open_system(&bus);
290 if(rc < 0)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500291 {
Hariharasubramanian R83951912016-01-20 07:06:36 -0600292 fprintf(stderr,"ERROR: Getting a SYSTEM bus hook\n");
293 return -1;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500294 }
295
Hariharasubramanian R83951912016-01-20 07:06:36 -0600296 rc = sd_bus_call_method(bus, // On the System Bus
297 app, // Service to contact
298 obj, // Object path
299 ifc, // Interface name
300 "GetHwAddress", // Method to be called
301 &err, // object to return error
302 &res, // Response message on success
303 "s", // input message (dev,ip,nm,gw)
304 device);
305 if(rc < 0)
306 {
307 fprintf(stderr, "Failed to Get HW address of device : %s\n", device);
308 return -1;
309 }
310
311 rc = sd_bus_message_read (res, "s", &eaddr);
312 if(rc < 0)
313 {
314 fprintf(stderr, "Failed to parse gateway from response message:[%s]\n", strerror(-rc));
315 return -1;
316 }
317
318 memcpy((void*)&buf[0], &current_revision, 1);
319 sscanf (eaddr, "%x:%x:%x:%x:%x:%x", &buf[1], &buf[2], &buf[3], &buf[4], &buf[5], &buf[6]);
320
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500321 *data_len = sizeof(buf);
322 memcpy(response, &buf, *data_len);
Hariharasubramanian R83951912016-01-20 07:06:36 -0600323
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500324 return IPMI_CC_OK;
325 }
326 else
327 {
328 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
329 return IPMI_CC_PARM_NOT_SUPPORTED;
330 }
331
332 return rc;
333}
334
335void register_netfn_transport_functions()
336{
337 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD);
338 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard);
339
340 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN);
341 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan);
342
343 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN);
344 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan);
345
346 return;
347}