4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Query and configure LAN interfaces over IPMI. This is done through the
28 * complicated get/set LAN Configuration Parameters command. This queries or
29 * sets the parameters one per command in series. We hide this implementation
30 * detail and instead export a single structure to consumers.
38 #include "ipmi_impl.h"
40 typedef struct ipmi_cmd_lan_get_config
{
48 } ipmi_cmd_lan_get_config_t
;
50 typedef struct ipmi_cmd_lan_set_config
{
55 uint8_t ilsc_data
[18];
56 } ipmi_cmd_lan_set_config_t
;
58 #define IPMI_LAN_SET_LEN(dlen) \
59 (offsetof(ipmi_cmd_lan_set_config_t, ilsc_data) + (dlen))
61 #define IPMI_LAN_PARAM_SET_IN_PROGRESS 0
62 #define IPMI_LAN_PARAM_IP_ADDR 3
63 #define IPMI_LAN_PARAM_IP_SOURCE 4
64 #define IPMI_LAN_PARAM_MAC_ADDR 5
65 #define IPMI_LAN_PARAM_SUBNET_MASK 6
66 #define IPMI_LAN_PARAM_GATEWAY_ADDR 12
68 #define IPMI_LAN_SET_COMPLETE 0x0
69 #define IPMI_LAN_SET_INPROGRESS 0x1
70 #define IPMI_LAN_SET_COMMIT 0x2
72 typedef struct ipmi_lan_entry
{
81 static ipmi_lan_entry_t ipmi_lan_table
[] = {
82 { IPMI_LAN_PARAM_IP_ADDR
, IPMI_LAN_SET_IPADDR
, 0, 0,
83 offsetof(ipmi_lan_config_t
, ilc_ipaddr
), sizeof (uint32_t) },
84 { IPMI_LAN_PARAM_IP_SOURCE
, IPMI_LAN_SET_IPADDR_SOURCE
, 0, 0,
85 offsetof(ipmi_lan_config_t
, ilc_ipaddr_source
), sizeof (uint8_t) },
86 { IPMI_LAN_PARAM_MAC_ADDR
, IPMI_LAN_SET_MACADDR
, 0, 0,
87 offsetof(ipmi_lan_config_t
, ilc_macaddr
), 6 * sizeof (uint8_t) },
88 { IPMI_LAN_PARAM_SUBNET_MASK
, IPMI_LAN_SET_SUBNET
, 0, 0,
89 offsetof(ipmi_lan_config_t
, ilc_subnet
), sizeof (uint32_t) },
90 { IPMI_LAN_PARAM_GATEWAY_ADDR
, IPMI_LAN_SET_GATEWAY_ADDR
, 0, 0,
91 offsetof(ipmi_lan_config_t
, ilc_gateway_addr
), sizeof (uint32_t) }
94 #define IPMI_LAN_NENTRIES \
95 (sizeof (ipmi_lan_table) / sizeof (ipmi_lan_table[0]))
98 ipmi_lan_get_param(ipmi_handle_t
*ihp
, int channel
, int param
, int set
,
99 int block
, void *data
, size_t len
)
101 ipmi_cmd_t cmd
, *rsp
;
102 ipmi_cmd_lan_get_config_t lcmd
= { 0 };
104 lcmd
.ilgc_number
= channel
;
105 lcmd
.ilgc_param
= param
;
107 lcmd
.ilgc_block
= block
;
109 cmd
.ic_netfn
= IPMI_NETFN_TRANSPORT
;
111 cmd
.ic_cmd
= IPMI_CMD_GET_LAN_CONFIG
;
113 cmd
.ic_dlen
= sizeof (lcmd
);
115 if ((rsp
= ipmi_send(ihp
, &cmd
)) == NULL
) {
116 switch (ihp
->ih_completion
) {
118 (void) ipmi_set_error(ihp
, EIPMI_BADPARAM
, NULL
);
124 if (rsp
->ic_dlen
< len
+ 1)
125 return (ipmi_set_error(ihp
, EIPMI_BAD_RESPONSE_LENGTH
, NULL
));
127 bcopy((uint8_t *)rsp
->ic_data
+ 1, data
, len
);
133 ipmi_lan_get_config(ipmi_handle_t
*ihp
, int channel
, ipmi_lan_config_t
*cfgp
)
137 ipmi_lan_entry_t
*lep
;
139 if (ipmi_lan_get_param(ihp
, channel
, IPMI_LAN_PARAM_SET_IN_PROGRESS
, 0,
140 0, &set
, sizeof (set
)) != 0)
143 if (set
& IPMI_LAN_SET_INPROGRESS
)
144 cfgp
->ilc_set_in_progress
= B_TRUE
;
146 cfgp
->ilc_set_in_progress
= B_FALSE
;
148 for (i
= 0; i
< IPMI_LAN_NENTRIES
; i
++) {
149 lep
= &ipmi_lan_table
[i
];
150 if (ipmi_lan_get_param(ihp
, channel
, lep
->ile_param
,
151 lep
->ile_set
, lep
->ile_block
,
152 (char *)cfgp
+ lep
->ile_offset
, lep
->ile_len
) != 0)
160 ipmi_lan_set_param(ipmi_handle_t
*ihp
, int channel
, int param
, void *data
,
164 ipmi_cmd_lan_set_config_t lcmd
= { 0 };
166 lcmd
.ilsc_number
= channel
;
167 lcmd
.ilsc_param
= param
;
168 bcopy(data
, lcmd
.ilsc_data
, len
);
170 cmd
.ic_netfn
= IPMI_NETFN_TRANSPORT
;
172 cmd
.ic_cmd
= IPMI_CMD_SET_LAN_CONFIG
;
174 cmd
.ic_dlen
= IPMI_LAN_SET_LEN(len
);
176 if (ipmi_send(ihp
, &cmd
) == NULL
) {
177 switch (ihp
->ih_completion
) {
179 (void) ipmi_set_error(ihp
, EIPMI_BADPARAM
, NULL
);
183 (void) ipmi_set_error(ihp
, EIPMI_BUSY
, NULL
);
187 (void) ipmi_set_error(ihp
, EIPMI_READONLY
, NULL
);
191 (void) ipmi_set_error(ihp
, EIPMI_WRITEONLY
, NULL
);
201 ipmi_lan_set_config(ipmi_handle_t
*ihp
, int channel
, ipmi_lan_config_t
*cfgp
,
206 ipmi_lan_entry_t
*lep
;
209 * Cancel any pending transaction, then open a new transaction.
211 set
= IPMI_LAN_SET_COMPLETE
;
212 if (ipmi_lan_set_param(ihp
, channel
, IPMI_LAN_PARAM_SET_IN_PROGRESS
,
213 &set
, sizeof (set
)) != 0)
215 set
= IPMI_LAN_SET_INPROGRESS
;
216 if (ipmi_lan_set_param(ihp
, channel
, IPMI_LAN_PARAM_SET_IN_PROGRESS
,
217 &set
, sizeof (set
)) != 0)
221 * Iterate over all parameters and set them.
223 for (i
= 0; i
< IPMI_LAN_NENTRIES
; i
++) {
224 lep
= &ipmi_lan_table
[i
];
225 if (!(lep
->ile_mask
& mask
))
228 if (ipmi_lan_set_param(ihp
, channel
, lep
->ile_param
,
229 (char *)cfgp
+ lep
->ile_offset
, lep
->ile_len
) != 0) {
231 * On some systems, setting the mode to DHCP may cause
232 * the command to timeout, presumably because it is
233 * waiting for the setting to take effect. If we see
234 * completion code 0xc3 (command timeout) while setting
235 * the DHCP value, just ignore it.
237 if (mask
!= IPMI_LAN_SET_IPADDR_SOURCE
||
238 cfgp
->ilc_ipaddr_source
!= IPMI_LAN_SRC_DHCP
||
239 ihp
->ih_completion
!= 0xC3)
245 * Commit the transaction.
247 set
= IPMI_LAN_SET_COMPLETE
;
248 if (ipmi_lan_set_param(ihp
, channel
, IPMI_LAN_PARAM_SET_IN_PROGRESS
,
249 &set
, sizeof (set
)) != 0)