1*11756SRobert.Johnston@Sun.COM /*
2*11756SRobert.Johnston@Sun.COM * CDDL HEADER START
3*11756SRobert.Johnston@Sun.COM *
4*11756SRobert.Johnston@Sun.COM * The contents of this file are subject to the terms of the
5*11756SRobert.Johnston@Sun.COM * Common Development and Distribution License (the "License").
6*11756SRobert.Johnston@Sun.COM * You may not use this file except in compliance with the License.
7*11756SRobert.Johnston@Sun.COM *
8*11756SRobert.Johnston@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11756SRobert.Johnston@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*11756SRobert.Johnston@Sun.COM * See the License for the specific language governing permissions
11*11756SRobert.Johnston@Sun.COM * and limitations under the License.
12*11756SRobert.Johnston@Sun.COM *
13*11756SRobert.Johnston@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*11756SRobert.Johnston@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11756SRobert.Johnston@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*11756SRobert.Johnston@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*11756SRobert.Johnston@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*11756SRobert.Johnston@Sun.COM *
19*11756SRobert.Johnston@Sun.COM * CDDL HEADER END
20*11756SRobert.Johnston@Sun.COM */
21*11756SRobert.Johnston@Sun.COM /*
22*11756SRobert.Johnston@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23*11756SRobert.Johnston@Sun.COM * Use is subject to license terms.
24*11756SRobert.Johnston@Sun.COM */
25*11756SRobert.Johnston@Sun.COM
26*11756SRobert.Johnston@Sun.COM /*
27*11756SRobert.Johnston@Sun.COM * Query and configure LAN interfaces over IPMI. This is done through the
28*11756SRobert.Johnston@Sun.COM * complicated get/set LAN Configuration Parameters command. This queries or
29*11756SRobert.Johnston@Sun.COM * sets the parameters one per command in series. We hide this implementation
30*11756SRobert.Johnston@Sun.COM * detail and instead export a single structure to consumers.
31*11756SRobert.Johnston@Sun.COM */
32*11756SRobert.Johnston@Sun.COM
33*11756SRobert.Johnston@Sun.COM #include <stddef.h>
34*11756SRobert.Johnston@Sun.COM #include <strings.h>
35*11756SRobert.Johnston@Sun.COM
36*11756SRobert.Johnston@Sun.COM #include <libipmi.h>
37*11756SRobert.Johnston@Sun.COM
38*11756SRobert.Johnston@Sun.COM #include "ipmi_impl.h"
39*11756SRobert.Johnston@Sun.COM
40*11756SRobert.Johnston@Sun.COM typedef struct ipmi_cmd_lan_get_config {
41*11756SRobert.Johnston@Sun.COM DECL_BITFIELD3(
42*11756SRobert.Johnston@Sun.COM ilgc_number :4,
43*11756SRobert.Johnston@Sun.COM __reserved :3,
44*11756SRobert.Johnston@Sun.COM ilgc_revonly :1);
45*11756SRobert.Johnston@Sun.COM uint8_t ilgc_param;
46*11756SRobert.Johnston@Sun.COM uint8_t ilgc_set;
47*11756SRobert.Johnston@Sun.COM uint8_t ilgc_block;
48*11756SRobert.Johnston@Sun.COM } ipmi_cmd_lan_get_config_t;
49*11756SRobert.Johnston@Sun.COM
50*11756SRobert.Johnston@Sun.COM typedef struct ipmi_cmd_lan_set_config {
51*11756SRobert.Johnston@Sun.COM DECL_BITFIELD2(
52*11756SRobert.Johnston@Sun.COM ilsc_number :4,
53*11756SRobert.Johnston@Sun.COM __reserved :4);
54*11756SRobert.Johnston@Sun.COM uint8_t ilsc_param;
55*11756SRobert.Johnston@Sun.COM uint8_t ilsc_data[18];
56*11756SRobert.Johnston@Sun.COM } ipmi_cmd_lan_set_config_t;
57*11756SRobert.Johnston@Sun.COM
58*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_SET_LEN(dlen) \
59*11756SRobert.Johnston@Sun.COM (offsetof(ipmi_cmd_lan_set_config_t, ilsc_data) + (dlen))
60*11756SRobert.Johnston@Sun.COM
61*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_PARAM_SET_IN_PROGRESS 0
62*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_PARAM_IP_ADDR 3
63*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_PARAM_IP_SOURCE 4
64*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_PARAM_MAC_ADDR 5
65*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_PARAM_SUBNET_MASK 6
66*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_PARAM_GATEWAY_ADDR 12
67*11756SRobert.Johnston@Sun.COM
68*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_SET_COMPLETE 0x0
69*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_SET_INPROGRESS 0x1
70*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_SET_COMMIT 0x2
71*11756SRobert.Johnston@Sun.COM
72*11756SRobert.Johnston@Sun.COM typedef struct ipmi_lan_entry {
73*11756SRobert.Johnston@Sun.COM int ile_param;
74*11756SRobert.Johnston@Sun.COM int ile_mask;
75*11756SRobert.Johnston@Sun.COM int ile_set;
76*11756SRobert.Johnston@Sun.COM int ile_block;
77*11756SRobert.Johnston@Sun.COM size_t ile_offset;
78*11756SRobert.Johnston@Sun.COM size_t ile_len;
79*11756SRobert.Johnston@Sun.COM } ipmi_lan_entry_t;
80*11756SRobert.Johnston@Sun.COM
81*11756SRobert.Johnston@Sun.COM static ipmi_lan_entry_t ipmi_lan_table[] = {
82*11756SRobert.Johnston@Sun.COM { IPMI_LAN_PARAM_IP_ADDR, IPMI_LAN_SET_IPADDR, 0, 0,
83*11756SRobert.Johnston@Sun.COM offsetof(ipmi_lan_config_t, ilc_ipaddr), sizeof (uint32_t) },
84*11756SRobert.Johnston@Sun.COM { IPMI_LAN_PARAM_IP_SOURCE, IPMI_LAN_SET_IPADDR_SOURCE, 0, 0,
85*11756SRobert.Johnston@Sun.COM offsetof(ipmi_lan_config_t, ilc_ipaddr_source), sizeof (uint8_t) },
86*11756SRobert.Johnston@Sun.COM { IPMI_LAN_PARAM_MAC_ADDR, IPMI_LAN_SET_MACADDR, 0, 0,
87*11756SRobert.Johnston@Sun.COM offsetof(ipmi_lan_config_t, ilc_macaddr), 6 * sizeof (uint8_t) },
88*11756SRobert.Johnston@Sun.COM { IPMI_LAN_PARAM_SUBNET_MASK, IPMI_LAN_SET_SUBNET, 0, 0,
89*11756SRobert.Johnston@Sun.COM offsetof(ipmi_lan_config_t, ilc_subnet), sizeof (uint32_t) },
90*11756SRobert.Johnston@Sun.COM { IPMI_LAN_PARAM_GATEWAY_ADDR, IPMI_LAN_SET_GATEWAY_ADDR, 0, 0,
91*11756SRobert.Johnston@Sun.COM offsetof(ipmi_lan_config_t, ilc_gateway_addr), sizeof (uint32_t) }
92*11756SRobert.Johnston@Sun.COM };
93*11756SRobert.Johnston@Sun.COM
94*11756SRobert.Johnston@Sun.COM #define IPMI_LAN_NENTRIES \
95*11756SRobert.Johnston@Sun.COM (sizeof (ipmi_lan_table) / sizeof (ipmi_lan_table[0]))
96*11756SRobert.Johnston@Sun.COM
97*11756SRobert.Johnston@Sun.COM static int
ipmi_lan_get_param(ipmi_handle_t * ihp,int channel,int param,int set,int block,void * data,size_t len)98*11756SRobert.Johnston@Sun.COM ipmi_lan_get_param(ipmi_handle_t *ihp, int channel, int param, int set,
99*11756SRobert.Johnston@Sun.COM int block, void *data, size_t len)
100*11756SRobert.Johnston@Sun.COM {
101*11756SRobert.Johnston@Sun.COM ipmi_cmd_t cmd, *rsp;
102*11756SRobert.Johnston@Sun.COM ipmi_cmd_lan_get_config_t lcmd = { 0 };
103*11756SRobert.Johnston@Sun.COM
104*11756SRobert.Johnston@Sun.COM lcmd.ilgc_number = channel;
105*11756SRobert.Johnston@Sun.COM lcmd.ilgc_param = param;
106*11756SRobert.Johnston@Sun.COM lcmd.ilgc_set = set;
107*11756SRobert.Johnston@Sun.COM lcmd.ilgc_block = block;
108*11756SRobert.Johnston@Sun.COM
109*11756SRobert.Johnston@Sun.COM cmd.ic_netfn = IPMI_NETFN_TRANSPORT;
110*11756SRobert.Johnston@Sun.COM cmd.ic_lun = 0;
111*11756SRobert.Johnston@Sun.COM cmd.ic_cmd = IPMI_CMD_GET_LAN_CONFIG;
112*11756SRobert.Johnston@Sun.COM cmd.ic_data = &lcmd;
113*11756SRobert.Johnston@Sun.COM cmd.ic_dlen = sizeof (lcmd);
114*11756SRobert.Johnston@Sun.COM
115*11756SRobert.Johnston@Sun.COM if ((rsp = ipmi_send(ihp, &cmd)) == NULL) {
116*11756SRobert.Johnston@Sun.COM switch (ihp->ih_completion) {
117*11756SRobert.Johnston@Sun.COM case 0x80:
118*11756SRobert.Johnston@Sun.COM (void) ipmi_set_error(ihp, EIPMI_BADPARAM, NULL);
119*11756SRobert.Johnston@Sun.COM break;
120*11756SRobert.Johnston@Sun.COM }
121*11756SRobert.Johnston@Sun.COM return (-1);
122*11756SRobert.Johnston@Sun.COM }
123*11756SRobert.Johnston@Sun.COM
124*11756SRobert.Johnston@Sun.COM if (rsp->ic_dlen < len + 1)
125*11756SRobert.Johnston@Sun.COM return (ipmi_set_error(ihp, EIPMI_BAD_RESPONSE_LENGTH, NULL));
126*11756SRobert.Johnston@Sun.COM
127*11756SRobert.Johnston@Sun.COM bcopy((uint8_t *)rsp->ic_data + 1, data, len);
128*11756SRobert.Johnston@Sun.COM
129*11756SRobert.Johnston@Sun.COM return (0);
130*11756SRobert.Johnston@Sun.COM }
131*11756SRobert.Johnston@Sun.COM
132*11756SRobert.Johnston@Sun.COM int
ipmi_lan_get_config(ipmi_handle_t * ihp,int channel,ipmi_lan_config_t * cfgp)133*11756SRobert.Johnston@Sun.COM ipmi_lan_get_config(ipmi_handle_t *ihp, int channel, ipmi_lan_config_t *cfgp)
134*11756SRobert.Johnston@Sun.COM {
135*11756SRobert.Johnston@Sun.COM uint8_t set;
136*11756SRobert.Johnston@Sun.COM int i;
137*11756SRobert.Johnston@Sun.COM ipmi_lan_entry_t *lep;
138*11756SRobert.Johnston@Sun.COM
139*11756SRobert.Johnston@Sun.COM if (ipmi_lan_get_param(ihp, channel, IPMI_LAN_PARAM_SET_IN_PROGRESS, 0,
140*11756SRobert.Johnston@Sun.COM 0, &set, sizeof (set)) != 0)
141*11756SRobert.Johnston@Sun.COM return (-1);
142*11756SRobert.Johnston@Sun.COM
143*11756SRobert.Johnston@Sun.COM if (set & IPMI_LAN_SET_INPROGRESS)
144*11756SRobert.Johnston@Sun.COM cfgp->ilc_set_in_progress = B_TRUE;
145*11756SRobert.Johnston@Sun.COM else
146*11756SRobert.Johnston@Sun.COM cfgp->ilc_set_in_progress = B_FALSE;
147*11756SRobert.Johnston@Sun.COM
148*11756SRobert.Johnston@Sun.COM for (i = 0; i < IPMI_LAN_NENTRIES; i++) {
149*11756SRobert.Johnston@Sun.COM lep = &ipmi_lan_table[i];
150*11756SRobert.Johnston@Sun.COM if (ipmi_lan_get_param(ihp, channel, lep->ile_param,
151*11756SRobert.Johnston@Sun.COM lep->ile_set, lep->ile_block,
152*11756SRobert.Johnston@Sun.COM (char *)cfgp + lep->ile_offset, lep->ile_len) != 0)
153*11756SRobert.Johnston@Sun.COM return (-1);
154*11756SRobert.Johnston@Sun.COM }
155*11756SRobert.Johnston@Sun.COM
156*11756SRobert.Johnston@Sun.COM return (0);
157*11756SRobert.Johnston@Sun.COM }
158*11756SRobert.Johnston@Sun.COM
159*11756SRobert.Johnston@Sun.COM static int
ipmi_lan_set_param(ipmi_handle_t * ihp,int channel,int param,void * data,size_t len)160*11756SRobert.Johnston@Sun.COM ipmi_lan_set_param(ipmi_handle_t *ihp, int channel, int param, void *data,
161*11756SRobert.Johnston@Sun.COM size_t len)
162*11756SRobert.Johnston@Sun.COM {
163*11756SRobert.Johnston@Sun.COM ipmi_cmd_t cmd;
164*11756SRobert.Johnston@Sun.COM ipmi_cmd_lan_set_config_t lcmd = { 0 };
165*11756SRobert.Johnston@Sun.COM
166*11756SRobert.Johnston@Sun.COM lcmd.ilsc_number = channel;
167*11756SRobert.Johnston@Sun.COM lcmd.ilsc_param = param;
168*11756SRobert.Johnston@Sun.COM bcopy(data, lcmd.ilsc_data, len);
169*11756SRobert.Johnston@Sun.COM
170*11756SRobert.Johnston@Sun.COM cmd.ic_netfn = IPMI_NETFN_TRANSPORT;
171*11756SRobert.Johnston@Sun.COM cmd.ic_lun = 0;
172*11756SRobert.Johnston@Sun.COM cmd.ic_cmd = IPMI_CMD_SET_LAN_CONFIG;
173*11756SRobert.Johnston@Sun.COM cmd.ic_data = &lcmd;
174*11756SRobert.Johnston@Sun.COM cmd.ic_dlen = IPMI_LAN_SET_LEN(len);
175*11756SRobert.Johnston@Sun.COM
176*11756SRobert.Johnston@Sun.COM if (ipmi_send(ihp, &cmd) == NULL) {
177*11756SRobert.Johnston@Sun.COM switch (ihp->ih_completion) {
178*11756SRobert.Johnston@Sun.COM case 0x80:
179*11756SRobert.Johnston@Sun.COM (void) ipmi_set_error(ihp, EIPMI_BADPARAM, NULL);
180*11756SRobert.Johnston@Sun.COM break;
181*11756SRobert.Johnston@Sun.COM
182*11756SRobert.Johnston@Sun.COM case 0x81:
183*11756SRobert.Johnston@Sun.COM (void) ipmi_set_error(ihp, EIPMI_BUSY, NULL);
184*11756SRobert.Johnston@Sun.COM break;
185*11756SRobert.Johnston@Sun.COM
186*11756SRobert.Johnston@Sun.COM case 0x82:
187*11756SRobert.Johnston@Sun.COM (void) ipmi_set_error(ihp, EIPMI_READONLY, NULL);
188*11756SRobert.Johnston@Sun.COM break;
189*11756SRobert.Johnston@Sun.COM
190*11756SRobert.Johnston@Sun.COM case 0x83:
191*11756SRobert.Johnston@Sun.COM (void) ipmi_set_error(ihp, EIPMI_WRITEONLY, NULL);
192*11756SRobert.Johnston@Sun.COM break;
193*11756SRobert.Johnston@Sun.COM }
194*11756SRobert.Johnston@Sun.COM return (-1);
195*11756SRobert.Johnston@Sun.COM }
196*11756SRobert.Johnston@Sun.COM
197*11756SRobert.Johnston@Sun.COM return (0);
198*11756SRobert.Johnston@Sun.COM }
199*11756SRobert.Johnston@Sun.COM
200*11756SRobert.Johnston@Sun.COM int
ipmi_lan_set_config(ipmi_handle_t * ihp,int channel,ipmi_lan_config_t * cfgp,int mask)201*11756SRobert.Johnston@Sun.COM ipmi_lan_set_config(ipmi_handle_t *ihp, int channel, ipmi_lan_config_t *cfgp,
202*11756SRobert.Johnston@Sun.COM int mask)
203*11756SRobert.Johnston@Sun.COM {
204*11756SRobert.Johnston@Sun.COM uint8_t set;
205*11756SRobert.Johnston@Sun.COM int i;
206*11756SRobert.Johnston@Sun.COM ipmi_lan_entry_t *lep;
207*11756SRobert.Johnston@Sun.COM
208*11756SRobert.Johnston@Sun.COM /*
209*11756SRobert.Johnston@Sun.COM * Cancel any pending transaction, then open a new transaction.
210*11756SRobert.Johnston@Sun.COM */
211*11756SRobert.Johnston@Sun.COM set = IPMI_LAN_SET_COMPLETE;
212*11756SRobert.Johnston@Sun.COM if (ipmi_lan_set_param(ihp, channel, IPMI_LAN_PARAM_SET_IN_PROGRESS,
213*11756SRobert.Johnston@Sun.COM &set, sizeof (set)) != 0)
214*11756SRobert.Johnston@Sun.COM return (-1);
215*11756SRobert.Johnston@Sun.COM set = IPMI_LAN_SET_INPROGRESS;
216*11756SRobert.Johnston@Sun.COM if (ipmi_lan_set_param(ihp, channel, IPMI_LAN_PARAM_SET_IN_PROGRESS,
217*11756SRobert.Johnston@Sun.COM &set, sizeof (set)) != 0)
218*11756SRobert.Johnston@Sun.COM return (-1);
219*11756SRobert.Johnston@Sun.COM
220*11756SRobert.Johnston@Sun.COM /*
221*11756SRobert.Johnston@Sun.COM * Iterate over all parameters and set them.
222*11756SRobert.Johnston@Sun.COM */
223*11756SRobert.Johnston@Sun.COM for (i = 0; i < IPMI_LAN_NENTRIES; i++) {
224*11756SRobert.Johnston@Sun.COM lep = &ipmi_lan_table[i];
225*11756SRobert.Johnston@Sun.COM if (!(lep->ile_mask & mask))
226*11756SRobert.Johnston@Sun.COM continue;
227*11756SRobert.Johnston@Sun.COM
228*11756SRobert.Johnston@Sun.COM if (ipmi_lan_set_param(ihp, channel, lep->ile_param,
229*11756SRobert.Johnston@Sun.COM (char *)cfgp + lep->ile_offset, lep->ile_len) != 0) {
230*11756SRobert.Johnston@Sun.COM /*
231*11756SRobert.Johnston@Sun.COM * On some systems, setting the mode to DHCP may cause
232*11756SRobert.Johnston@Sun.COM * the command to timeout, presumably because it is
233*11756SRobert.Johnston@Sun.COM * waiting for the setting to take effect. If we see
234*11756SRobert.Johnston@Sun.COM * completion code 0xc3 (command timeout) while setting
235*11756SRobert.Johnston@Sun.COM * the DHCP value, just ignore it.
236*11756SRobert.Johnston@Sun.COM */
237*11756SRobert.Johnston@Sun.COM if (mask != IPMI_LAN_SET_IPADDR_SOURCE ||
238*11756SRobert.Johnston@Sun.COM cfgp->ilc_ipaddr_source != IPMI_LAN_SRC_DHCP ||
239*11756SRobert.Johnston@Sun.COM ihp->ih_completion != 0xC3)
240*11756SRobert.Johnston@Sun.COM return (-1);
241*11756SRobert.Johnston@Sun.COM }
242*11756SRobert.Johnston@Sun.COM }
243*11756SRobert.Johnston@Sun.COM
244*11756SRobert.Johnston@Sun.COM /*
245*11756SRobert.Johnston@Sun.COM * Commit the transaction.
246*11756SRobert.Johnston@Sun.COM */
247*11756SRobert.Johnston@Sun.COM set = IPMI_LAN_SET_COMPLETE;
248*11756SRobert.Johnston@Sun.COM if (ipmi_lan_set_param(ihp, channel, IPMI_LAN_PARAM_SET_IN_PROGRESS,
249*11756SRobert.Johnston@Sun.COM &set, sizeof (set)) != 0)
250*11756SRobert.Johnston@Sun.COM return (-1);
251*11756SRobert.Johnston@Sun.COM
252*11756SRobert.Johnston@Sun.COM return (0);
253*11756SRobert.Johnston@Sun.COM }
254