xref: /onnv-gate/usr/src/lib/libipmi/common/ipmi_lan.c (revision 11756:3ae81edcfbf7)
18339SEric.Schrock@Sun.COM /*
28339SEric.Schrock@Sun.COM  * CDDL HEADER START
38339SEric.Schrock@Sun.COM  *
48339SEric.Schrock@Sun.COM  * The contents of this file are subject to the terms of the
58339SEric.Schrock@Sun.COM  * Common Development and Distribution License (the "License").
68339SEric.Schrock@Sun.COM  * You may not use this file except in compliance with the License.
78339SEric.Schrock@Sun.COM  *
88339SEric.Schrock@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98339SEric.Schrock@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108339SEric.Schrock@Sun.COM  * See the License for the specific language governing permissions
118339SEric.Schrock@Sun.COM  * and limitations under the License.
128339SEric.Schrock@Sun.COM  *
138339SEric.Schrock@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148339SEric.Schrock@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158339SEric.Schrock@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168339SEric.Schrock@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178339SEric.Schrock@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188339SEric.Schrock@Sun.COM  *
198339SEric.Schrock@Sun.COM  * CDDL HEADER END
208339SEric.Schrock@Sun.COM  */
218339SEric.Schrock@Sun.COM /*
22*11756SRobert.Johnston@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
238339SEric.Schrock@Sun.COM  * Use is subject to license terms.
248339SEric.Schrock@Sun.COM  */
258339SEric.Schrock@Sun.COM 
26*11756SRobert.Johnston@Sun.COM #include <stdlib.h>
27*11756SRobert.Johnston@Sun.COM #include <stdio.h>
28*11756SRobert.Johnston@Sun.COM #include <assert.h>
29*11756SRobert.Johnston@Sun.COM #include <inttypes.h>
30*11756SRobert.Johnston@Sun.COM #include <string.h>
31*11756SRobert.Johnston@Sun.COM #include <sys/types.h>
32*11756SRobert.Johnston@Sun.COM #include <sys/socket.h>
33*11756SRobert.Johnston@Sun.COM #include <netinet/in.h>
34*11756SRobert.Johnston@Sun.COM #include <arpa/inet.h>
35*11756SRobert.Johnston@Sun.COM #include <errno.h>
36*11756SRobert.Johnston@Sun.COM #include <unistd.h>
37*11756SRobert.Johnston@Sun.COM #include <netdb.h>
38*11756SRobert.Johnston@Sun.COM #include <fcntl.h>
398339SEric.Schrock@Sun.COM 
40*11756SRobert.Johnston@Sun.COM #include "libipmi.h"
41*11756SRobert.Johnston@Sun.COM #include "ipmi_lan.h"
428339SEric.Schrock@Sun.COM #include "ipmi_impl.h"
438339SEric.Schrock@Sun.COM 
44*11756SRobert.Johnston@Sun.COM #define	DEF_IPMI_LAN_TIMEOUT		3 /* seconds */
45*11756SRobert.Johnston@Sun.COM #define	DEF_IPMI_LAN_NUM_RETRIES	5
46*11756SRobert.Johnston@Sun.COM #define	IPMI_LAN_CHANNEL_E		0x0e
47*11756SRobert.Johnston@Sun.COM 
48*11756SRobert.Johnston@Sun.COM typedef struct ipmi_rs {
49*11756SRobert.Johnston@Sun.COM 	uint8_t		ir_data[IPMI_BUF_SIZE];
50*11756SRobert.Johnston@Sun.COM 	int		ir_dlen;
51*11756SRobert.Johnston@Sun.COM 	ipmi_msg_hdr_t	ir_ihdr;
52*11756SRobert.Johnston@Sun.COM 	uint8_t		ir_ccode;
53*11756SRobert.Johnston@Sun.COM } ipmi_rs_t;
54*11756SRobert.Johnston@Sun.COM 
55*11756SRobert.Johnston@Sun.COM static ipmi_rs_t *ipmi_lan_poll_recv(ipmi_handle_t *);
56*11756SRobert.Johnston@Sun.COM 
57*11756SRobert.Johnston@Sun.COM typedef struct ipmi_rq_entry {
58*11756SRobert.Johnston@Sun.COM 	ipmi_list_t	ire_list;
59*11756SRobert.Johnston@Sun.COM 	ipmi_cmd_t	ire_req;
60*11756SRobert.Johnston@Sun.COM 	uint8_t		ire_target_cmd;
61*11756SRobert.Johnston@Sun.COM 	uint8_t		ire_rq_seq;
62*11756SRobert.Johnston@Sun.COM 	uint8_t		*ire_msg_data;
63*11756SRobert.Johnston@Sun.COM 	int		ire_msg_len;
64*11756SRobert.Johnston@Sun.COM } ipmi_rq_entry_t;
65*11756SRobert.Johnston@Sun.COM 
66*11756SRobert.Johnston@Sun.COM ipmi_rq_entry_t *ipmi_req_entries = NULL;
67*11756SRobert.Johnston@Sun.COM 
68*11756SRobert.Johnston@Sun.COM /*
69*11756SRobert.Johnston@Sun.COM  * LAN transport-specific data
70*11756SRobert.Johnston@Sun.COM  */
71*11756SRobert.Johnston@Sun.COM typedef struct ipmi_lan {
72*11756SRobert.Johnston@Sun.COM 	ipmi_handle_t	*il_ihp;
73*11756SRobert.Johnston@Sun.COM 	char		il_host[MAXHOSTNAMELEN + 1];
74*11756SRobert.Johnston@Sun.COM 	uint16_t	il_port;
75*11756SRobert.Johnston@Sun.COM 	char		il_user[17];
76*11756SRobert.Johnston@Sun.COM 	char		il_authcode[IPMI_AUTHCODE_BUF_SIZE + 1];
77*11756SRobert.Johnston@Sun.COM 	uint8_t		il_challenge[16];
78*11756SRobert.Johnston@Sun.COM 	uint32_t	il_session_id;
79*11756SRobert.Johnston@Sun.COM 	int 		il_sd;
80*11756SRobert.Johnston@Sun.COM 	boolean_t	il_send_authcode;
81*11756SRobert.Johnston@Sun.COM 	boolean_t	il_session_active;
82*11756SRobert.Johnston@Sun.COM 	uint8_t		il_authtype;
83*11756SRobert.Johnston@Sun.COM 	uint8_t		il_privlvl;
84*11756SRobert.Johnston@Sun.COM 	uint8_t		il_num_retries;
85*11756SRobert.Johnston@Sun.COM 	uint32_t	il_in_seq;
86*11756SRobert.Johnston@Sun.COM 	uint32_t	il_timeout;
87*11756SRobert.Johnston@Sun.COM 	struct sockaddr_in il_addr;
88*11756SRobert.Johnston@Sun.COM 	socklen_t	il_addrlen;
89*11756SRobert.Johnston@Sun.COM } ipmi_lan_t;
908339SEric.Schrock@Sun.COM 
91*11756SRobert.Johnston@Sun.COM /*
92*11756SRobert.Johnston@Sun.COM  * Calculate and returns IPMI checksum
93*11756SRobert.Johnston@Sun.COM  *
94*11756SRobert.Johnston@Sun.COM  * Checksum algorithm is described in Section 13.8
95*11756SRobert.Johnston@Sun.COM  *
96*11756SRobert.Johnston@Sun.COM  * d:		buffer to check
97*11756SRobert.Johnston@Sun.COM  * s:		position in buffer to start checksum from
98*11756SRobert.Johnston@Sun.COM  */
99*11756SRobert.Johnston@Sun.COM static uint8_t
ipmi_csum(uint8_t * d,int s)100*11756SRobert.Johnston@Sun.COM ipmi_csum(uint8_t *d, int s)
101*11756SRobert.Johnston@Sun.COM {
102*11756SRobert.Johnston@Sun.COM 	uint8_t c = 0;
103*11756SRobert.Johnston@Sun.COM 	for (; s > 0; s--, d++)
104*11756SRobert.Johnston@Sun.COM 		c += *d;
105*11756SRobert.Johnston@Sun.COM 	return (-c);
106*11756SRobert.Johnston@Sun.COM }
107*11756SRobert.Johnston@Sun.COM 
108*11756SRobert.Johnston@Sun.COM static ipmi_rq_entry_t *
ipmi_req_add_entry(ipmi_handle_t * ihp,ipmi_cmd_t * req)109*11756SRobert.Johnston@Sun.COM ipmi_req_add_entry(ipmi_handle_t *ihp, ipmi_cmd_t *req)
110*11756SRobert.Johnston@Sun.COM {
111*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *e;
112*11756SRobert.Johnston@Sun.COM 
113*11756SRobert.Johnston@Sun.COM 	if ((e = ipmi_zalloc(ihp, sizeof (ipmi_rq_entry_t))) == NULL)
114*11756SRobert.Johnston@Sun.COM 		return (NULL);
115*11756SRobert.Johnston@Sun.COM 
116*11756SRobert.Johnston@Sun.COM 	(void) memcpy(&e->ire_req, req, sizeof (ipmi_cmd_t));
117*11756SRobert.Johnston@Sun.COM 	ipmi_list_append(&ipmi_req_entries->ire_list, e);
118*11756SRobert.Johnston@Sun.COM 
119*11756SRobert.Johnston@Sun.COM 	return (e);
120*11756SRobert.Johnston@Sun.COM }
1218339SEric.Schrock@Sun.COM 
122*11756SRobert.Johnston@Sun.COM /*ARGSUSED*/
123*11756SRobert.Johnston@Sun.COM static ipmi_rq_entry_t *
ipmi_req_lookup_entry(ipmi_handle_t * ihp,uint8_t seq,uint8_t cmd)124*11756SRobert.Johnston@Sun.COM ipmi_req_lookup_entry(ipmi_handle_t *ihp, uint8_t seq, uint8_t cmd)
125*11756SRobert.Johnston@Sun.COM {
126*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *e;
127*11756SRobert.Johnston@Sun.COM 
128*11756SRobert.Johnston@Sun.COM 	for (e = ipmi_list_next(&ipmi_req_entries->ire_list); e != NULL;
129*11756SRobert.Johnston@Sun.COM 	    e = ipmi_list_next(e))
130*11756SRobert.Johnston@Sun.COM 		if (e->ire_rq_seq == seq && e->ire_req.ic_cmd == cmd)
131*11756SRobert.Johnston@Sun.COM 			return (e);
132*11756SRobert.Johnston@Sun.COM 
133*11756SRobert.Johnston@Sun.COM 	return (NULL);
134*11756SRobert.Johnston@Sun.COM }
135*11756SRobert.Johnston@Sun.COM 
136*11756SRobert.Johnston@Sun.COM static void
ipmi_req_remove_entry(ipmi_handle_t * ihp,uint8_t seq,uint8_t cmd)137*11756SRobert.Johnston@Sun.COM ipmi_req_remove_entry(ipmi_handle_t *ihp, uint8_t seq, uint8_t cmd)
138*11756SRobert.Johnston@Sun.COM {
139*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *e;
140*11756SRobert.Johnston@Sun.COM 
141*11756SRobert.Johnston@Sun.COM 	e = ipmi_req_lookup_entry(ihp, seq, cmd);
142*11756SRobert.Johnston@Sun.COM 
143*11756SRobert.Johnston@Sun.COM 	if (e) {
144*11756SRobert.Johnston@Sun.COM 		ipmi_list_delete(&ipmi_req_entries->ire_list, e);
145*11756SRobert.Johnston@Sun.COM 		ipmi_free(ihp, e->ire_msg_data);
146*11756SRobert.Johnston@Sun.COM 		ipmi_free(ihp, e);
147*11756SRobert.Johnston@Sun.COM 	}
148*11756SRobert.Johnston@Sun.COM }
149*11756SRobert.Johnston@Sun.COM 
150*11756SRobert.Johnston@Sun.COM static void
ipmi_req_clear_entries(ipmi_handle_t * ihp)151*11756SRobert.Johnston@Sun.COM ipmi_req_clear_entries(ipmi_handle_t *ihp)
152*11756SRobert.Johnston@Sun.COM {
153*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *e;
1548339SEric.Schrock@Sun.COM 
155*11756SRobert.Johnston@Sun.COM 	while ((e = ipmi_list_next(&ipmi_req_entries->ire_list)) != NULL) {
156*11756SRobert.Johnston@Sun.COM 		ipmi_list_delete(&ipmi_req_entries->ire_list, e);
157*11756SRobert.Johnston@Sun.COM 		ipmi_free(ihp, e);
158*11756SRobert.Johnston@Sun.COM 	}
159*11756SRobert.Johnston@Sun.COM }
160*11756SRobert.Johnston@Sun.COM 
161*11756SRobert.Johnston@Sun.COM static int
get_random(void * buf,uint_t len)162*11756SRobert.Johnston@Sun.COM get_random(void *buf, uint_t len)
163*11756SRobert.Johnston@Sun.COM {
164*11756SRobert.Johnston@Sun.COM 	int fd;
165*11756SRobert.Johnston@Sun.COM 
166*11756SRobert.Johnston@Sun.COM 	assert(buf != NULL && len > 0);
167*11756SRobert.Johnston@Sun.COM 	if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
168*11756SRobert.Johnston@Sun.COM 		return (-1);
169*11756SRobert.Johnston@Sun.COM 
170*11756SRobert.Johnston@Sun.COM 	if (read(fd, buf, len) < 0) {
171*11756SRobert.Johnston@Sun.COM 		(void) close(fd);
172*11756SRobert.Johnston@Sun.COM 		return (-1);
173*11756SRobert.Johnston@Sun.COM 	}
174*11756SRobert.Johnston@Sun.COM 	(void) close(fd);
175*11756SRobert.Johnston@Sun.COM 	return (0);
176*11756SRobert.Johnston@Sun.COM }
1778339SEric.Schrock@Sun.COM 
178*11756SRobert.Johnston@Sun.COM static int
ipmi_lan_send_packet(ipmi_handle_t * ihp,uint8_t * data,int dlen)179*11756SRobert.Johnston@Sun.COM ipmi_lan_send_packet(ipmi_handle_t *ihp, uint8_t *data, int dlen)
180*11756SRobert.Johnston@Sun.COM {
181*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
182*11756SRobert.Johnston@Sun.COM 
183*11756SRobert.Johnston@Sun.COM 	return (send(ilp->il_sd, data, dlen, 0));
184*11756SRobert.Johnston@Sun.COM }
185*11756SRobert.Johnston@Sun.COM 
186*11756SRobert.Johnston@Sun.COM static ipmi_rs_t *
ipmi_lan_recv_packet(ipmi_handle_t * ihp)187*11756SRobert.Johnston@Sun.COM ipmi_lan_recv_packet(ipmi_handle_t *ihp)
188*11756SRobert.Johnston@Sun.COM {
189*11756SRobert.Johnston@Sun.COM 	static ipmi_rs_t rsp;
190*11756SRobert.Johnston@Sun.COM 	fd_set read_set, err_set;
191*11756SRobert.Johnston@Sun.COM 	struct timeval tmout;
192*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
193*11756SRobert.Johnston@Sun.COM 	int ret;
194*11756SRobert.Johnston@Sun.COM 
195*11756SRobert.Johnston@Sun.COM 	FD_ZERO(&read_set);
196*11756SRobert.Johnston@Sun.COM 	FD_SET(ilp->il_sd, &read_set);
197*11756SRobert.Johnston@Sun.COM 
198*11756SRobert.Johnston@Sun.COM 	FD_ZERO(&err_set);
199*11756SRobert.Johnston@Sun.COM 	FD_SET(ilp->il_sd, &err_set);
200*11756SRobert.Johnston@Sun.COM 
201*11756SRobert.Johnston@Sun.COM 	tmout.tv_sec = 	ilp->il_timeout;
202*11756SRobert.Johnston@Sun.COM 	tmout.tv_usec = 0;
203*11756SRobert.Johnston@Sun.COM 
204*11756SRobert.Johnston@Sun.COM 	ret = select(ilp->il_sd + 1, &read_set, NULL, &err_set, &tmout);
205*11756SRobert.Johnston@Sun.COM 	if (ret < 0 || FD_ISSET(ilp->il_sd, &err_set) ||
206*11756SRobert.Johnston@Sun.COM 	    !FD_ISSET(ilp->il_sd, &read_set))
207*11756SRobert.Johnston@Sun.COM 		return (NULL);
2088339SEric.Schrock@Sun.COM 
209*11756SRobert.Johnston@Sun.COM 	/*
210*11756SRobert.Johnston@Sun.COM 	 * The first read may return ECONNREFUSED because the rmcp ping
211*11756SRobert.Johnston@Sun.COM 	 * packet--sent to UDP port 623--will be processed by both the
212*11756SRobert.Johnston@Sun.COM 	 * BMC and the OS.
213*11756SRobert.Johnston@Sun.COM 	 *
214*11756SRobert.Johnston@Sun.COM 	 * The problem with this is that the ECONNREFUSED takes
215*11756SRobert.Johnston@Sun.COM 	 * priority over any other received datagram; that means that
216*11756SRobert.Johnston@Sun.COM 	 * the Connection Refused shows up _before_ the response packet,
217*11756SRobert.Johnston@Sun.COM 	 * regardless of the order they were sent out.  (unless the
218*11756SRobert.Johnston@Sun.COM 	 * response is read before the connection refused is returned)
219*11756SRobert.Johnston@Sun.COM 	 */
220*11756SRobert.Johnston@Sun.COM 	ret = recv(ilp->il_sd, &rsp.ir_data, IPMI_BUF_SIZE, 0);
221*11756SRobert.Johnston@Sun.COM 
222*11756SRobert.Johnston@Sun.COM 	if (ret < 0) {
223*11756SRobert.Johnston@Sun.COM 		FD_ZERO(&read_set);
224*11756SRobert.Johnston@Sun.COM 		FD_SET(ilp->il_sd, &read_set);
225*11756SRobert.Johnston@Sun.COM 
226*11756SRobert.Johnston@Sun.COM 		FD_ZERO(&err_set);
227*11756SRobert.Johnston@Sun.COM 		FD_SET(ilp->il_sd, &err_set);
228*11756SRobert.Johnston@Sun.COM 
229*11756SRobert.Johnston@Sun.COM 		tmout.tv_sec = ilp->il_timeout;
230*11756SRobert.Johnston@Sun.COM 		tmout.tv_usec = 0;
231*11756SRobert.Johnston@Sun.COM 
232*11756SRobert.Johnston@Sun.COM 		ret = select(ilp->il_sd + 1, &read_set, NULL, &err_set, &tmout);
233*11756SRobert.Johnston@Sun.COM 		if (ret < 0) {
234*11756SRobert.Johnston@Sun.COM 			if (FD_ISSET(ilp->il_sd, &err_set) ||
235*11756SRobert.Johnston@Sun.COM 			    !FD_ISSET(ilp->il_sd, &read_set))
236*11756SRobert.Johnston@Sun.COM 				return (NULL);
2378339SEric.Schrock@Sun.COM 
238*11756SRobert.Johnston@Sun.COM 			ret = recv(ilp->il_sd, &rsp.ir_data, IPMI_BUF_SIZE, 0);
239*11756SRobert.Johnston@Sun.COM 			if (ret < 0)
240*11756SRobert.Johnston@Sun.COM 				return (NULL);
241*11756SRobert.Johnston@Sun.COM 		}
242*11756SRobert.Johnston@Sun.COM 	}
243*11756SRobert.Johnston@Sun.COM 
244*11756SRobert.Johnston@Sun.COM 	if (ret == 0)
245*11756SRobert.Johnston@Sun.COM 		return (NULL);
246*11756SRobert.Johnston@Sun.COM 
247*11756SRobert.Johnston@Sun.COM 	rsp.ir_data[ret] = '\0';
248*11756SRobert.Johnston@Sun.COM 	rsp.ir_dlen = ret;
249*11756SRobert.Johnston@Sun.COM 
250*11756SRobert.Johnston@Sun.COM 	return (&rsp);
251*11756SRobert.Johnston@Sun.COM }
252*11756SRobert.Johnston@Sun.COM 
253*11756SRobert.Johnston@Sun.COM 
254*11756SRobert.Johnston@Sun.COM /*
255*11756SRobert.Johnston@Sun.COM  * ASF/RMCP Pong Message
256*11756SRobert.Johnston@Sun.COM  *
257*11756SRobert.Johnston@Sun.COM  * See section 13.2.4
258*11756SRobert.Johnston@Sun.COM  */
259*11756SRobert.Johnston@Sun.COM struct rmcp_pong {
260*11756SRobert.Johnston@Sun.COM 	rmcp_hdr_t rp_rmcp;
261*11756SRobert.Johnston@Sun.COM 	asf_hdr_t rp_asf;
262*11756SRobert.Johnston@Sun.COM 	uint32_t rp_iana;
263*11756SRobert.Johnston@Sun.COM 	uint32_t rp_oem;
264*11756SRobert.Johnston@Sun.COM 	uint8_t rp_sup_entities;
265*11756SRobert.Johnston@Sun.COM 	uint8_t rp_sup_interact;
266*11756SRobert.Johnston@Sun.COM 	uint8_t rp_reserved[6];
2678339SEric.Schrock@Sun.COM };
2688339SEric.Schrock@Sun.COM 
269*11756SRobert.Johnston@Sun.COM /*
270*11756SRobert.Johnston@Sun.COM  * parse response RMCP "pong" packet
271*11756SRobert.Johnston@Sun.COM  *
272*11756SRobert.Johnston@Sun.COM  * return -1 if ping response not received
273*11756SRobert.Johnston@Sun.COM  * returns 0 if IPMI is NOT supported
274*11756SRobert.Johnston@Sun.COM  * returns 1 if IPMI is supported
275*11756SRobert.Johnston@Sun.COM  */
276*11756SRobert.Johnston@Sun.COM /*ARGSUSED*/
2778339SEric.Schrock@Sun.COM static int
ipmi_handle_pong(ipmi_handle_t * ihp,ipmi_rs_t * rsp)278*11756SRobert.Johnston@Sun.COM ipmi_handle_pong(ipmi_handle_t *ihp, ipmi_rs_t *rsp)
2798339SEric.Schrock@Sun.COM {
280*11756SRobert.Johnston@Sun.COM 	struct rmcp_pong *pong;
281*11756SRobert.Johnston@Sun.COM 
282*11756SRobert.Johnston@Sun.COM 	if (rsp == NULL)
283*11756SRobert.Johnston@Sun.COM 		return (-1);
2848339SEric.Schrock@Sun.COM 
285*11756SRobert.Johnston@Sun.COM 	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
286*11756SRobert.Johnston@Sun.COM 	pong = (struct rmcp_pong *)rsp->ir_data;
287*11756SRobert.Johnston@Sun.COM 
288*11756SRobert.Johnston@Sun.COM 	return ((pong->rp_sup_entities & 0x80) ? 1 : 0);
289*11756SRobert.Johnston@Sun.COM }
2908339SEric.Schrock@Sun.COM 
291*11756SRobert.Johnston@Sun.COM /*
292*11756SRobert.Johnston@Sun.COM  * Build and send RMCP presence ping message
293*11756SRobert.Johnston@Sun.COM  */
294*11756SRobert.Johnston@Sun.COM static int
ipmi_lan_ping(ipmi_handle_t * ihp)295*11756SRobert.Johnston@Sun.COM ipmi_lan_ping(ipmi_handle_t *ihp)
296*11756SRobert.Johnston@Sun.COM {
297*11756SRobert.Johnston@Sun.COM 	rmcp_hdr_t rmcp_ping;
298*11756SRobert.Johnston@Sun.COM 	asf_hdr_t asf_ping;
299*11756SRobert.Johnston@Sun.COM 	uint8_t *data;
300*11756SRobert.Johnston@Sun.COM 	int rv, dlen = sizeof (rmcp_ping) + sizeof (asf_ping);
301*11756SRobert.Johnston@Sun.COM 
302*11756SRobert.Johnston@Sun.COM 	(void) memset(&rmcp_ping, 0, sizeof (rmcp_ping));
303*11756SRobert.Johnston@Sun.COM 	rmcp_ping.rh_version = RMCP_VERSION_1;
304*11756SRobert.Johnston@Sun.COM 	rmcp_ping.rh_msg_class = RMCP_CLASS_ASF;
305*11756SRobert.Johnston@Sun.COM 	rmcp_ping.rh_seq = 0xff;
3068339SEric.Schrock@Sun.COM 
307*11756SRobert.Johnston@Sun.COM 	(void) memset(&asf_ping, 0, sizeof (asf_ping));
308*11756SRobert.Johnston@Sun.COM 	asf_ping.ah_iana = htonl(ASF_RMCP_IANA);
309*11756SRobert.Johnston@Sun.COM 	asf_ping.ah_msg_type = ASF_TYPE_PING;
310*11756SRobert.Johnston@Sun.COM 
311*11756SRobert.Johnston@Sun.COM 	if ((data = ipmi_zalloc(ihp, dlen)) == NULL)
3128339SEric.Schrock@Sun.COM 		return (-1);
313*11756SRobert.Johnston@Sun.COM 
314*11756SRobert.Johnston@Sun.COM 	(void) memcpy(data, &rmcp_ping, sizeof (rmcp_ping));
315*11756SRobert.Johnston@Sun.COM 	(void) memcpy(data + sizeof (rmcp_ping), &asf_ping, sizeof (asf_ping));
316*11756SRobert.Johnston@Sun.COM 
317*11756SRobert.Johnston@Sun.COM 	rv = ipmi_lan_send_packet(ihp, data, dlen);
3188339SEric.Schrock@Sun.COM 
319*11756SRobert.Johnston@Sun.COM 	ipmi_free(ihp, data);
3208339SEric.Schrock@Sun.COM 
321*11756SRobert.Johnston@Sun.COM 	if (rv < 0)
322*11756SRobert.Johnston@Sun.COM 		return (ipmi_set_error(ihp, EIPMI_LAN_PING_FAILED, NULL));
323*11756SRobert.Johnston@Sun.COM 
324*11756SRobert.Johnston@Sun.COM 	if (ipmi_lan_poll_recv(ihp) == NULL)
325*11756SRobert.Johnston@Sun.COM 		return (ipmi_set_error(ihp, EIPMI_LAN_PING_FAILED, NULL));
3268339SEric.Schrock@Sun.COM 
3278339SEric.Schrock@Sun.COM 	return (0);
3288339SEric.Schrock@Sun.COM }
3298339SEric.Schrock@Sun.COM 
330*11756SRobert.Johnston@Sun.COM static ipmi_rs_t *
ipmi_lan_poll_recv(ipmi_handle_t * ihp)331*11756SRobert.Johnston@Sun.COM ipmi_lan_poll_recv(ipmi_handle_t *ihp)
3328339SEric.Schrock@Sun.COM {
333*11756SRobert.Johnston@Sun.COM 	rmcp_hdr_t rmcp_rsp;
334*11756SRobert.Johnston@Sun.COM 	ipmi_rs_t *rsp;
335*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *entry;
336*11756SRobert.Johnston@Sun.COM 	int off = 0, rv;
337*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
338*11756SRobert.Johnston@Sun.COM 	uint8_t rsp_authtype;
339*11756SRobert.Johnston@Sun.COM 
340*11756SRobert.Johnston@Sun.COM 	rsp = ipmi_lan_recv_packet(ihp);
341*11756SRobert.Johnston@Sun.COM 
342*11756SRobert.Johnston@Sun.COM 	while (rsp != NULL) {
343*11756SRobert.Johnston@Sun.COM 
344*11756SRobert.Johnston@Sun.COM 		/* parse response headers */
345*11756SRobert.Johnston@Sun.COM 		(void) memcpy(&rmcp_rsp, rsp->ir_data, 4);
346*11756SRobert.Johnston@Sun.COM 
347*11756SRobert.Johnston@Sun.COM 		switch (rmcp_rsp.rh_msg_class) {
348*11756SRobert.Johnston@Sun.COM 		case RMCP_CLASS_ASF:
349*11756SRobert.Johnston@Sun.COM 			/* ping response packet */
350*11756SRobert.Johnston@Sun.COM 			rv = ipmi_handle_pong(ihp, rsp);
351*11756SRobert.Johnston@Sun.COM 			return ((rv <= 0) ? NULL : rsp);
352*11756SRobert.Johnston@Sun.COM 		case RMCP_CLASS_IPMI:
353*11756SRobert.Johnston@Sun.COM 			/* handled by rest of function */
354*11756SRobert.Johnston@Sun.COM 			break;
355*11756SRobert.Johnston@Sun.COM 		default:
356*11756SRobert.Johnston@Sun.COM 			/* Invalid RMCP class */
357*11756SRobert.Johnston@Sun.COM 			rsp = ipmi_lan_recv_packet(ihp);
358*11756SRobert.Johnston@Sun.COM 			continue;
359*11756SRobert.Johnston@Sun.COM 		}
360*11756SRobert.Johnston@Sun.COM 
361*11756SRobert.Johnston@Sun.COM 		off = sizeof (rmcp_hdr_t);
362*11756SRobert.Johnston@Sun.COM 		rsp_authtype = rsp->ir_data[off];
363*11756SRobert.Johnston@Sun.COM 		if (ilp->il_send_authcode && (rsp_authtype || ilp->il_authtype))
364*11756SRobert.Johnston@Sun.COM 			off += 26;
365*11756SRobert.Johnston@Sun.COM 		else
366*11756SRobert.Johnston@Sun.COM 			off += 10;
367*11756SRobert.Johnston@Sun.COM 
368*11756SRobert.Johnston@Sun.COM 		(void) memcpy(&rsp->ir_ihdr, (void *)(rsp->ir_data + off),
369*11756SRobert.Johnston@Sun.COM 		    sizeof (rsp->ir_ihdr));
370*11756SRobert.Johnston@Sun.COM 		rsp->ir_ihdr.imh_seq = rsp->ir_ihdr.imh_seq >> 2;
371*11756SRobert.Johnston@Sun.COM 		off += sizeof (rsp->ir_ihdr);
372*11756SRobert.Johnston@Sun.COM 		rsp->ir_ccode = rsp->ir_data[off++];
3738339SEric.Schrock@Sun.COM 
374*11756SRobert.Johnston@Sun.COM 		entry = ipmi_req_lookup_entry(ihp, rsp->ir_ihdr.imh_seq,
375*11756SRobert.Johnston@Sun.COM 		    rsp->ir_ihdr.imh_cmd);
376*11756SRobert.Johnston@Sun.COM 		if (entry) {
377*11756SRobert.Johnston@Sun.COM 			ipmi_req_remove_entry(ihp, rsp->ir_ihdr.imh_seq,
378*11756SRobert.Johnston@Sun.COM 			    rsp->ir_ihdr.imh_cmd);
379*11756SRobert.Johnston@Sun.COM 		} else {
380*11756SRobert.Johnston@Sun.COM 			rsp = ipmi_lan_recv_packet(ihp);
381*11756SRobert.Johnston@Sun.COM 			continue;
382*11756SRobert.Johnston@Sun.COM 		}
383*11756SRobert.Johnston@Sun.COM 		break;
384*11756SRobert.Johnston@Sun.COM 	}
385*11756SRobert.Johnston@Sun.COM 
386*11756SRobert.Johnston@Sun.COM 	/* shift response data to start of array */
387*11756SRobert.Johnston@Sun.COM 	if (rsp && rsp->ir_dlen > off) {
388*11756SRobert.Johnston@Sun.COM 		rsp->ir_dlen -= off + 1;
389*11756SRobert.Johnston@Sun.COM 		(void) memmove(rsp->ir_data, rsp->ir_data + off, rsp->ir_dlen);
390*11756SRobert.Johnston@Sun.COM 		(void) memset(rsp->ir_data + rsp->ir_dlen, 0,
391*11756SRobert.Johnston@Sun.COM 		    IPMI_BUF_SIZE - rsp->ir_dlen);
392*11756SRobert.Johnston@Sun.COM 	}
393*11756SRobert.Johnston@Sun.COM 	return (rsp);
394*11756SRobert.Johnston@Sun.COM }
395*11756SRobert.Johnston@Sun.COM 
396*11756SRobert.Johnston@Sun.COM /*
397*11756SRobert.Johnston@Sun.COM  * IPMI LAN Request Message Format
398*11756SRobert.Johnston@Sun.COM  *
399*11756SRobert.Johnston@Sun.COM  * See section 13.8
400*11756SRobert.Johnston@Sun.COM  *
401*11756SRobert.Johnston@Sun.COM  * +---------------------+
402*11756SRobert.Johnston@Sun.COM  * |  rmcp_hdr_t         | 4 bytes
403*11756SRobert.Johnston@Sun.COM  * +---------------------+
404*11756SRobert.Johnston@Sun.COM  * |  v15_session_hdr_t  | 9 bytes
405*11756SRobert.Johnston@Sun.COM  * +---------------------+
406*11756SRobert.Johnston@Sun.COM  * | [authcode]          | 16 bytes (if AUTHTYPE != none)
407*11756SRobert.Johnston@Sun.COM  * +---------------------+
408*11756SRobert.Johnston@Sun.COM  * |  msg length         | 1 byte
409*11756SRobert.Johnston@Sun.COM  * +---------------------+
410*11756SRobert.Johnston@Sun.COM  * |  ipmi_msg_hdr_t     | 6 bytes
411*11756SRobert.Johnston@Sun.COM  * +---------------------+
412*11756SRobert.Johnston@Sun.COM  * | [msg data]          | variable
413*11756SRobert.Johnston@Sun.COM  * +---------------------+
414*11756SRobert.Johnston@Sun.COM  * |  msg data checksum  | 1 byte
415*11756SRobert.Johnston@Sun.COM  * +---------------------+
416*11756SRobert.Johnston@Sun.COM  */
417*11756SRobert.Johnston@Sun.COM static ipmi_rq_entry_t *
ipmi_lan_build_cmd(ipmi_handle_t * ihp,ipmi_cmd_t * req)418*11756SRobert.Johnston@Sun.COM ipmi_lan_build_cmd(ipmi_handle_t *ihp, ipmi_cmd_t *req)
419*11756SRobert.Johnston@Sun.COM {
420*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
421*11756SRobert.Johnston@Sun.COM 	rmcp_hdr_t rmcp_hdr;
422*11756SRobert.Johnston@Sun.COM 	v15_session_hdr_t session_hdr;
423*11756SRobert.Johnston@Sun.COM 	ipmi_msg_hdr_t msg_hdr;
424*11756SRobert.Johnston@Sun.COM 	uint8_t *msg;
425*11756SRobert.Johnston@Sun.COM 	int cs, tmp, off = 0, len;
426*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *entry;
427*11756SRobert.Johnston@Sun.COM 	static int curr_seq = 0;
428*11756SRobert.Johnston@Sun.COM 
429*11756SRobert.Johnston@Sun.COM 	if (curr_seq >= 64)
430*11756SRobert.Johnston@Sun.COM 		curr_seq = 0;
431*11756SRobert.Johnston@Sun.COM 
432*11756SRobert.Johnston@Sun.COM 	if ((entry = ipmi_req_add_entry(ihp, req)) == NULL)
433*11756SRobert.Johnston@Sun.COM 		return (NULL);
4348339SEric.Schrock@Sun.COM 
435*11756SRobert.Johnston@Sun.COM 	len = req->ic_dlen + 29;
436*11756SRobert.Johnston@Sun.COM 	if (ilp->il_send_authcode && ilp->il_authtype)
437*11756SRobert.Johnston@Sun.COM 		len += 16;
438*11756SRobert.Johnston@Sun.COM 
439*11756SRobert.Johnston@Sun.COM 	if ((msg = ipmi_zalloc(ihp, len)) == NULL)
440*11756SRobert.Johnston@Sun.COM 		/* ipmi_errno set */
441*11756SRobert.Johnston@Sun.COM 		return (NULL);
442*11756SRobert.Johnston@Sun.COM 
443*11756SRobert.Johnston@Sun.COM 	/* RMCP header */
444*11756SRobert.Johnston@Sun.COM 	(void) memset(&rmcp_hdr, 0, sizeof (rmcp_hdr));
445*11756SRobert.Johnston@Sun.COM 	rmcp_hdr.rh_version = RMCP_VERSION_1;
446*11756SRobert.Johnston@Sun.COM 	rmcp_hdr.rh_msg_class = RMCP_CLASS_IPMI;
447*11756SRobert.Johnston@Sun.COM 	rmcp_hdr.rh_seq = 0xff;
448*11756SRobert.Johnston@Sun.COM 	(void) memcpy(msg, &rmcp_hdr, sizeof (rmcp_hdr));
449*11756SRobert.Johnston@Sun.COM 	off = sizeof (rmcp_hdr);
450*11756SRobert.Johnston@Sun.COM 
451*11756SRobert.Johnston@Sun.COM 	/* IPMI session header */
452*11756SRobert.Johnston@Sun.COM 	(void) memset(&session_hdr, 0, sizeof (session_hdr));
453*11756SRobert.Johnston@Sun.COM 	if (! ilp->il_send_authcode)
454*11756SRobert.Johnston@Sun.COM 		session_hdr.sh_authtype = 0x00;
4558339SEric.Schrock@Sun.COM 	else
456*11756SRobert.Johnston@Sun.COM 		/* hardcode passwd authentication */
457*11756SRobert.Johnston@Sun.COM 		session_hdr.sh_authtype = 0x04;
458*11756SRobert.Johnston@Sun.COM 
459*11756SRobert.Johnston@Sun.COM 	(void) memcpy(&session_hdr.sh_seq, &ilp->il_in_seq, sizeof (uint32_t));
460*11756SRobert.Johnston@Sun.COM 	(void) memcpy(&session_hdr.sh_id, &ilp->il_session_id,
461*11756SRobert.Johnston@Sun.COM 	    sizeof (uint32_t));
462*11756SRobert.Johnston@Sun.COM 
463*11756SRobert.Johnston@Sun.COM 	(void) memcpy(msg + off, &session_hdr, sizeof (session_hdr));
464*11756SRobert.Johnston@Sun.COM 	off += sizeof (session_hdr);
465*11756SRobert.Johnston@Sun.COM 
466*11756SRobert.Johnston@Sun.COM 	/* IPMI session authcode */
467*11756SRobert.Johnston@Sun.COM 	if (ilp->il_send_authcode && ilp->il_authtype) {
468*11756SRobert.Johnston@Sun.COM 		(void) memcpy(msg + off, ilp->il_authcode, 16);
469*11756SRobert.Johnston@Sun.COM 		off += 16;
470*11756SRobert.Johnston@Sun.COM 	}
471*11756SRobert.Johnston@Sun.COM 
472*11756SRobert.Johnston@Sun.COM 	/* message length */
473*11756SRobert.Johnston@Sun.COM 	msg[off++] = req->ic_dlen + 7;
474*11756SRobert.Johnston@Sun.COM 	cs = off;
4758339SEric.Schrock@Sun.COM 
476*11756SRobert.Johnston@Sun.COM 	/* IPMI message header */
477*11756SRobert.Johnston@Sun.COM 	(void) memset(&msg_hdr, 0, sizeof (msg_hdr));
478*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_addr1 = IPMI_BMC_SLAVE_ADDR;
479*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_lun = req->ic_lun;
480*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_netfn = req->ic_netfn;
481*11756SRobert.Johnston@Sun.COM 	tmp = off - cs;
482*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_csum = ipmi_csum(msg + cs, tmp);
483*11756SRobert.Johnston@Sun.COM 	cs = off;
484*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_addr2 = IPMI_BMC_SLAVE_ADDR;
485*11756SRobert.Johnston@Sun.COM 	entry->ire_rq_seq = curr_seq++;
486*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_seq = entry->ire_rq_seq << 2;
487*11756SRobert.Johnston@Sun.COM 	msg_hdr.imh_cmd = req->ic_cmd;
488*11756SRobert.Johnston@Sun.COM 	(void) memcpy(msg + off, &msg_hdr, sizeof (msg_hdr));
489*11756SRobert.Johnston@Sun.COM 	off += sizeof (msg_hdr);
490*11756SRobert.Johnston@Sun.COM 
491*11756SRobert.Johnston@Sun.COM 	/* message data */
492*11756SRobert.Johnston@Sun.COM 	if (req->ic_dlen != 0) {
493*11756SRobert.Johnston@Sun.COM 		(void) memcpy(msg + off, req->ic_data, req->ic_dlen);
494*11756SRobert.Johnston@Sun.COM 		off += req->ic_dlen;
495*11756SRobert.Johnston@Sun.COM 	}
496*11756SRobert.Johnston@Sun.COM 
497*11756SRobert.Johnston@Sun.COM 	/* message data checksum */
498*11756SRobert.Johnston@Sun.COM 	tmp = off - cs;
499*11756SRobert.Johnston@Sun.COM 	msg[off++] = ipmi_csum(msg + cs, tmp);
500*11756SRobert.Johnston@Sun.COM 
501*11756SRobert.Johnston@Sun.COM 	if (ilp->il_in_seq) {
502*11756SRobert.Johnston@Sun.COM 		ilp->il_in_seq++;
503*11756SRobert.Johnston@Sun.COM 		if (ilp->il_in_seq == 0)
504*11756SRobert.Johnston@Sun.COM 			ilp->il_in_seq++;
505*11756SRobert.Johnston@Sun.COM 	}
506*11756SRobert.Johnston@Sun.COM 
507*11756SRobert.Johnston@Sun.COM 	entry->ire_msg_len = off;
508*11756SRobert.Johnston@Sun.COM 	entry->ire_msg_data = msg;
509*11756SRobert.Johnston@Sun.COM 
510*11756SRobert.Johnston@Sun.COM 	return (entry);
511*11756SRobert.Johnston@Sun.COM }
512*11756SRobert.Johnston@Sun.COM 
513*11756SRobert.Johnston@Sun.COM static int
ipmi_lan_send(void * data,ipmi_cmd_t * cmd,ipmi_cmd_t * response,int * completion)514*11756SRobert.Johnston@Sun.COM ipmi_lan_send(void *data, ipmi_cmd_t *cmd, ipmi_cmd_t *response,
515*11756SRobert.Johnston@Sun.COM     int *completion)
516*11756SRobert.Johnston@Sun.COM {
517*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)data;
518*11756SRobert.Johnston@Sun.COM 	ipmi_rq_entry_t *entry = NULL;
519*11756SRobert.Johnston@Sun.COM 	ipmi_rs_t *rsp = NULL;
520*11756SRobert.Johnston@Sun.COM 	uint_t try = 0;
521*11756SRobert.Johnston@Sun.COM 
522*11756SRobert.Johnston@Sun.COM 	for (;;) {
523*11756SRobert.Johnston@Sun.COM 		if ((entry = ipmi_lan_build_cmd(ilp->il_ihp, cmd)) == NULL)
524*11756SRobert.Johnston@Sun.COM 			return (-1);
525*11756SRobert.Johnston@Sun.COM 
526*11756SRobert.Johnston@Sun.COM 		if (ipmi_lan_send_packet(ilp->il_ihp, entry->ire_msg_data,
527*11756SRobert.Johnston@Sun.COM 		    entry->ire_msg_len) < 0) {
528*11756SRobert.Johnston@Sun.COM 			if (++try >= ilp->il_num_retries)
529*11756SRobert.Johnston@Sun.COM 				return (-1);
530*11756SRobert.Johnston@Sun.COM 			(void) usleep(5000);
531*11756SRobert.Johnston@Sun.COM 			continue;
532*11756SRobert.Johnston@Sun.COM 		}
533*11756SRobert.Johnston@Sun.COM 
534*11756SRobert.Johnston@Sun.COM 		(void) usleep(100);
535*11756SRobert.Johnston@Sun.COM 
536*11756SRobert.Johnston@Sun.COM 		if ((rsp = ipmi_lan_poll_recv(ilp->il_ihp)) != NULL)
537*11756SRobert.Johnston@Sun.COM 			break;
538*11756SRobert.Johnston@Sun.COM 
539*11756SRobert.Johnston@Sun.COM 		(void) usleep(5000);
540*11756SRobert.Johnston@Sun.COM 		ipmi_req_remove_entry(ilp->il_ihp, entry->ire_rq_seq,
541*11756SRobert.Johnston@Sun.COM 		    entry->ire_req.ic_cmd);
542*11756SRobert.Johnston@Sun.COM 
543*11756SRobert.Johnston@Sun.COM 		if (++try >= ilp->il_num_retries)
5448339SEric.Schrock@Sun.COM 			return (-1);
5458339SEric.Schrock@Sun.COM 	}
546*11756SRobert.Johnston@Sun.COM 	response->ic_netfn = rsp->ir_ihdr.imh_netfn;
547*11756SRobert.Johnston@Sun.COM 	response->ic_lun = rsp->ir_ihdr.imh_lun;
548*11756SRobert.Johnston@Sun.COM 	response->ic_cmd = rsp->ir_ihdr.imh_cmd;
549*11756SRobert.Johnston@Sun.COM 	if (rsp->ir_ccode != 0) {
550*11756SRobert.Johnston@Sun.COM 		*completion = rsp->ir_ccode;
551*11756SRobert.Johnston@Sun.COM 		response->ic_dlen = 0;
552*11756SRobert.Johnston@Sun.COM 		response->ic_data = NULL;
553*11756SRobert.Johnston@Sun.COM 	} else {
554*11756SRobert.Johnston@Sun.COM 		*completion = 0;
555*11756SRobert.Johnston@Sun.COM 		response->ic_dlen = rsp->ir_dlen;
556*11756SRobert.Johnston@Sun.COM 		response->ic_data = rsp->ir_data;
557*11756SRobert.Johnston@Sun.COM 	}
558*11756SRobert.Johnston@Sun.COM 	return (0);
559*11756SRobert.Johnston@Sun.COM }
560*11756SRobert.Johnston@Sun.COM 
561*11756SRobert.Johnston@Sun.COM /*
562*11756SRobert.Johnston@Sun.COM  * IPMI Get Session Challenge Command
563*11756SRobert.Johnston@Sun.COM  *
564*11756SRobert.Johnston@Sun.COM  * Copies the returned session ID and 16-byte challenge string to the supplied
565*11756SRobert.Johnston@Sun.COM  * buffers
566*11756SRobert.Johnston@Sun.COM  *
567*11756SRobert.Johnston@Sun.COM  * See section 22.16
568*11756SRobert.Johnston@Sun.COM  */
569*11756SRobert.Johnston@Sun.COM static int
ipmi_get_session_challenge_cmd(ipmi_handle_t * ihp,uint32_t * session_id,uint8_t * challenge)570*11756SRobert.Johnston@Sun.COM ipmi_get_session_challenge_cmd(ipmi_handle_t *ihp, uint32_t *session_id,
571*11756SRobert.Johnston@Sun.COM     uint8_t *challenge)
572*11756SRobert.Johnston@Sun.COM {
573*11756SRobert.Johnston@Sun.COM 	ipmi_cmd_t cmd, resp;
574*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
575*11756SRobert.Johnston@Sun.COM 	char msg_data[17];
576*11756SRobert.Johnston@Sun.COM 	int ccode;
577*11756SRobert.Johnston@Sun.COM 
578*11756SRobert.Johnston@Sun.COM 	(void) memset(msg_data, 0, 17);
579*11756SRobert.Johnston@Sun.COM 
580*11756SRobert.Johnston@Sun.COM 	switch (ilp->il_authtype) {
581*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_NONE:
582*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x00;
583*11756SRobert.Johnston@Sun.COM 		break;
584*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_MD2:
585*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x01;
586*11756SRobert.Johnston@Sun.COM 		break;
587*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_MD5:
588*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x02;
589*11756SRobert.Johnston@Sun.COM 		break;
590*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_PASSWORD:
591*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x04;
592*11756SRobert.Johnston@Sun.COM 		break;
593*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_OEM:
594*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x05;
595*11756SRobert.Johnston@Sun.COM 		break;
596*11756SRobert.Johnston@Sun.COM 	}
597*11756SRobert.Johnston@Sun.COM 	(void) memcpy(msg_data + 1, ilp->il_user, 16);
598*11756SRobert.Johnston@Sun.COM 
599*11756SRobert.Johnston@Sun.COM 	cmd.ic_netfn = IPMI_NETFN_APP;
600*11756SRobert.Johnston@Sun.COM 	cmd.ic_lun = 0;
601*11756SRobert.Johnston@Sun.COM 	cmd.ic_cmd = IPMI_CMD_GET_SESSION_CHALLENGE;
602*11756SRobert.Johnston@Sun.COM 	cmd.ic_data = msg_data;
603*11756SRobert.Johnston@Sun.COM 	cmd.ic_dlen = 17;
604*11756SRobert.Johnston@Sun.COM 
605*11756SRobert.Johnston@Sun.COM 	if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0 || ccode)
606*11756SRobert.Johnston@Sun.COM 		return (ipmi_set_error(ihp, EIPMI_LAN_CHALLENGE, NULL));
607*11756SRobert.Johnston@Sun.COM 
608*11756SRobert.Johnston@Sun.COM 	(void) memcpy(session_id, resp.ic_data, 4);
609*11756SRobert.Johnston@Sun.COM 	(void) memcpy(challenge, (uint8_t *)resp.ic_data + 4, 16);
6108339SEric.Schrock@Sun.COM 
6118339SEric.Schrock@Sun.COM 	return (0);
6128339SEric.Schrock@Sun.COM }
6138339SEric.Schrock@Sun.COM 
614*11756SRobert.Johnston@Sun.COM /*
615*11756SRobert.Johnston@Sun.COM  * IPMI Activate Session Command
616*11756SRobert.Johnston@Sun.COM  *
617*11756SRobert.Johnston@Sun.COM  * See section 22.17
618*11756SRobert.Johnston@Sun.COM  */
6198339SEric.Schrock@Sun.COM static int
ipmi_activate_session_cmd(ipmi_handle_t * ihp)620*11756SRobert.Johnston@Sun.COM ipmi_activate_session_cmd(ipmi_handle_t *ihp)
6218339SEric.Schrock@Sun.COM {
622*11756SRobert.Johnston@Sun.COM 	ipmi_cmd_t cmd, resp;
623*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
624*11756SRobert.Johnston@Sun.COM 	uint8_t msg_data[22], *resp_data;
625*11756SRobert.Johnston@Sun.COM 	int ccode;
6268339SEric.Schrock@Sun.COM 
627*11756SRobert.Johnston@Sun.COM 	cmd.ic_netfn = IPMI_NETFN_APP;
6288339SEric.Schrock@Sun.COM 	cmd.ic_lun = 0;
629*11756SRobert.Johnston@Sun.COM 	cmd.ic_cmd = IPMI_CMD_ACTIVATE_SESSION;
6308339SEric.Schrock@Sun.COM 
631*11756SRobert.Johnston@Sun.COM 	switch (ilp->il_authtype) {
632*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_NONE:
633*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x00;
634*11756SRobert.Johnston@Sun.COM 		break;
635*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_MD2:
636*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x01;
637*11756SRobert.Johnston@Sun.COM 		break;
638*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_MD5:
639*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x02;
640*11756SRobert.Johnston@Sun.COM 		break;
641*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_PASSWORD:
642*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x04;
643*11756SRobert.Johnston@Sun.COM 		break;
644*11756SRobert.Johnston@Sun.COM 	case IPMI_SESSION_AUTHTYPE_OEM:
645*11756SRobert.Johnston@Sun.COM 		msg_data[0] = 0x05;
646*11756SRobert.Johnston@Sun.COM 		break;
647*11756SRobert.Johnston@Sun.COM 	}
648*11756SRobert.Johnston@Sun.COM 	msg_data[1] = ilp->il_privlvl;
6498339SEric.Schrock@Sun.COM 
650*11756SRobert.Johnston@Sun.COM 	(void) memcpy(msg_data + 2, ilp->il_challenge, 16);
651*11756SRobert.Johnston@Sun.COM 
652*11756SRobert.Johnston@Sun.COM 	/* setup initial outbound sequence number */
653*11756SRobert.Johnston@Sun.COM 	(void) get_random(msg_data + 18, 4);
654*11756SRobert.Johnston@Sun.COM 
655*11756SRobert.Johnston@Sun.COM 	cmd.ic_data = msg_data;
656*11756SRobert.Johnston@Sun.COM 	cmd.ic_dlen = 22;
657*11756SRobert.Johnston@Sun.COM 
658*11756SRobert.Johnston@Sun.COM 	ilp->il_send_authcode = B_TRUE;
6598339SEric.Schrock@Sun.COM 
660*11756SRobert.Johnston@Sun.COM 	if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0 || ccode) {
661*11756SRobert.Johnston@Sun.COM 		ilp->il_send_authcode = B_FALSE;
662*11756SRobert.Johnston@Sun.COM 		return (ipmi_set_error(ihp, EIPMI_LAN_SESSION, NULL));
6638339SEric.Schrock@Sun.COM 	}
6648339SEric.Schrock@Sun.COM 
665*11756SRobert.Johnston@Sun.COM 	resp_data = (uint8_t *)resp.ic_data;
666*11756SRobert.Johnston@Sun.COM 	(void) memcpy(&ilp->il_session_id, resp_data + 1, 4);
667*11756SRobert.Johnston@Sun.COM 	ilp->il_in_seq = resp_data[8] << 24 | resp_data[7] << 16 |
668*11756SRobert.Johnston@Sun.COM 	    resp_data[6] << 8 | resp_data[5];
669*11756SRobert.Johnston@Sun.COM 	if (ilp->il_in_seq == 0)
670*11756SRobert.Johnston@Sun.COM 		++ilp->il_in_seq;
671*11756SRobert.Johnston@Sun.COM 
6728339SEric.Schrock@Sun.COM 	return (0);
6738339SEric.Schrock@Sun.COM }
6748339SEric.Schrock@Sun.COM 
675*11756SRobert.Johnston@Sun.COM 
676*11756SRobert.Johnston@Sun.COM /*
677*11756SRobert.Johnston@Sun.COM  * See section 22.18
678*11756SRobert.Johnston@Sun.COM  *
679*11756SRobert.Johnston@Sun.COM  * returns privilege level or -1 on error
680*11756SRobert.Johnston@Sun.COM  */
681*11756SRobert.Johnston@Sun.COM static int
ipmi_set_session_privlvl_cmd(ipmi_handle_t * ihp,uint8_t privlvl)682*11756SRobert.Johnston@Sun.COM ipmi_set_session_privlvl_cmd(ipmi_handle_t *ihp, uint8_t privlvl)
6838339SEric.Schrock@Sun.COM {
684*11756SRobert.Johnston@Sun.COM 	ipmi_cmd_t cmd, resp;
685*11756SRobert.Johnston@Sun.COM 	int ret = 0, ccode;
686*11756SRobert.Johnston@Sun.COM 
687*11756SRobert.Johnston@Sun.COM 	if (privlvl > IPMI_SESSION_PRIV_OEM)
688*11756SRobert.Johnston@Sun.COM 		return (ipmi_set_error(ihp, EIPMI_BADPARAM, NULL));
689*11756SRobert.Johnston@Sun.COM 
690*11756SRobert.Johnston@Sun.COM 	cmd.ic_netfn	= IPMI_NETFN_APP;
691*11756SRobert.Johnston@Sun.COM 	cmd.ic_lun 	= 0;
692*11756SRobert.Johnston@Sun.COM 	cmd.ic_cmd	= IPMI_CMD_SET_SESSION_PRIVLVL;
693*11756SRobert.Johnston@Sun.COM 	cmd.ic_data	= &privlvl;
694*11756SRobert.Johnston@Sun.COM 	cmd.ic_dlen	= 1;
695*11756SRobert.Johnston@Sun.COM 
696*11756SRobert.Johnston@Sun.COM 	if (ipmi_lan_send(ihp->ih_tdata, &cmd, &resp, &ccode) != 0)
697*11756SRobert.Johnston@Sun.COM 		ret = ipmi_set_error(ihp, EIPMI_LAN_SETPRIV, NULL);
698*11756SRobert.Johnston@Sun.COM 
699*11756SRobert.Johnston@Sun.COM 	return (ret);
700*11756SRobert.Johnston@Sun.COM }
701*11756SRobert.Johnston@Sun.COM 
702*11756SRobert.Johnston@Sun.COM /*
703*11756SRobert.Johnston@Sun.COM  * See section 22.19
704*11756SRobert.Johnston@Sun.COM  */
705*11756SRobert.Johnston@Sun.COM static int
ipmi_close_session_cmd(ipmi_handle_t * ihp)706*11756SRobert.Johnston@Sun.COM ipmi_close_session_cmd(ipmi_handle_t *ihp)
707*11756SRobert.Johnston@Sun.COM {
708*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
709*11756SRobert.Johnston@Sun.COM 	ipmi_cmd_t cmd, resp;
710*11756SRobert.Johnston@Sun.COM 	uint8_t msg_data[4];
711*11756SRobert.Johnston@Sun.COM 	int ret = 0, ccode;
712*11756SRobert.Johnston@Sun.COM 
713*11756SRobert.Johnston@Sun.COM 	if (! ilp->il_session_active)
714*11756SRobert.Johnston@Sun.COM 		return (-1);
715*11756SRobert.Johnston@Sun.COM 
716*11756SRobert.Johnston@Sun.COM 	(void) memcpy(&msg_data, &ilp->il_session_id, 4);
7178339SEric.Schrock@Sun.COM 
718*11756SRobert.Johnston@Sun.COM 	cmd.ic_netfn	= IPMI_NETFN_APP;
719*11756SRobert.Johnston@Sun.COM 	cmd.ic_lun	= 0;
720*11756SRobert.Johnston@Sun.COM 	cmd.ic_cmd	= IPMI_CMD_CLOSE_SESSION;
721*11756SRobert.Johnston@Sun.COM 	cmd.ic_data	= msg_data;
722*11756SRobert.Johnston@Sun.COM 	cmd.ic_dlen	= 4;
723*11756SRobert.Johnston@Sun.COM 
724*11756SRobert.Johnston@Sun.COM 	if (ipmi_lan_send(ilp, &cmd, &resp, &ccode) != 0)
725*11756SRobert.Johnston@Sun.COM 		ret = -1;
726*11756SRobert.Johnston@Sun.COM 
727*11756SRobert.Johnston@Sun.COM 	return (ret);
728*11756SRobert.Johnston@Sun.COM }
729*11756SRobert.Johnston@Sun.COM 
730*11756SRobert.Johnston@Sun.COM /*
731*11756SRobert.Johnston@Sun.COM  * IPMI LAN Session Activation
732*11756SRobert.Johnston@Sun.COM  *
733*11756SRobert.Johnston@Sun.COM  * See section 13.14
734*11756SRobert.Johnston@Sun.COM  *
735*11756SRobert.Johnston@Sun.COM  * 1. send "RMCP Presence Ping" message, response message will
736*11756SRobert.Johnston@Sun.COM  *    indicate whether the platform supports IPMI
737*11756SRobert.Johnston@Sun.COM  * 2. send "Get Channel Authentication Capabilities" command
738*11756SRobert.Johnston@Sun.COM  *    with AUTHTYPE = none, response packet will contain information
739*11756SRobert.Johnston@Sun.COM  *    about supported challenge/response authentication types
740*11756SRobert.Johnston@Sun.COM  * 3. send "Get Session Challenge" command with AUTHTYPE = none
741*11756SRobert.Johnston@Sun.COM  *    and indicate the authentication type in the message, response
742*11756SRobert.Johnston@Sun.COM  *    packet will contain challenge string and temporary session ID.
743*11756SRobert.Johnston@Sun.COM  * 4. send "Activate Session" command, authenticated with AUTHTYPE
744*11756SRobert.Johnston@Sun.COM  *    sent in previous message.  Also sends the initial value for
745*11756SRobert.Johnston@Sun.COM  *    the outbound sequence number for BMC.
746*11756SRobert.Johnston@Sun.COM  * 5. BMC returns response confirming session activation and
747*11756SRobert.Johnston@Sun.COM  *    session ID for this session and initial inbound sequence.
748*11756SRobert.Johnston@Sun.COM  */
749*11756SRobert.Johnston@Sun.COM static int
ipmi_lan_activate_session(ipmi_handle_t * ihp)750*11756SRobert.Johnston@Sun.COM ipmi_lan_activate_session(ipmi_handle_t *ihp)
751*11756SRobert.Johnston@Sun.COM {
752*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)ihp->ih_tdata;
753*11756SRobert.Johnston@Sun.COM 	ipmi_channel_auth_caps_t *ac;
754*11756SRobert.Johnston@Sun.COM 
755*11756SRobert.Johnston@Sun.COM 	if (ipmi_lan_ping(ihp) != 0)
7568339SEric.Schrock@Sun.COM 		return (-1);
757*11756SRobert.Johnston@Sun.COM 
758*11756SRobert.Johnston@Sun.COM 	if ((ac = ipmi_get_channel_auth_caps(ihp, IPMI_LAN_CHANNEL_E,
759*11756SRobert.Johnston@Sun.COM 	    ilp->il_privlvl)) == NULL)
7608339SEric.Schrock@Sun.COM 		return (-1);
7618339SEric.Schrock@Sun.COM 
7628339SEric.Schrock@Sun.COM 	/*
763*11756SRobert.Johnston@Sun.COM 	 * For the sake of simplicity, we're just supporting basic password
764*11756SRobert.Johnston@Sun.COM 	 * authentication.  If this authentication type is not supported then
765*11756SRobert.Johnston@Sun.COM 	 * we'll bail here.
7668339SEric.Schrock@Sun.COM 	 */
767*11756SRobert.Johnston@Sun.COM 	if (!(ac->cap_authtype & IPMI_SESSION_AUTHTYPE_PASSWORD)) {
768*11756SRobert.Johnston@Sun.COM 		free(ac);
769*11756SRobert.Johnston@Sun.COM 		return (ipmi_set_error(ihp, EIPMI_LAN_PASSWD_NOTSUP, NULL));
770*11756SRobert.Johnston@Sun.COM 	}
771*11756SRobert.Johnston@Sun.COM 	free(ac);
7728339SEric.Schrock@Sun.COM 
773*11756SRobert.Johnston@Sun.COM 	if (ipmi_get_session_challenge_cmd(ihp, &ilp->il_session_id,
774*11756SRobert.Johnston@Sun.COM 	    ilp->il_challenge) != 0)
775*11756SRobert.Johnston@Sun.COM 		return (-1);
7768339SEric.Schrock@Sun.COM 
777*11756SRobert.Johnston@Sun.COM 	if (ipmi_activate_session_cmd(ihp) != 0)
778*11756SRobert.Johnston@Sun.COM 		return (-1);
779*11756SRobert.Johnston@Sun.COM 
780*11756SRobert.Johnston@Sun.COM 	ilp->il_session_active = B_TRUE;
781*11756SRobert.Johnston@Sun.COM 
782*11756SRobert.Johnston@Sun.COM 	if (ipmi_set_session_privlvl_cmd(ihp, ilp->il_privlvl) != 0)
7838339SEric.Schrock@Sun.COM 		return (-1);
7848339SEric.Schrock@Sun.COM 
7858339SEric.Schrock@Sun.COM 	return (0);
7868339SEric.Schrock@Sun.COM }
787*11756SRobert.Johnston@Sun.COM 
788*11756SRobert.Johnston@Sun.COM static void
ipmi_lan_close(void * data)789*11756SRobert.Johnston@Sun.COM ipmi_lan_close(void *data)
790*11756SRobert.Johnston@Sun.COM {
791*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp = (ipmi_lan_t *)data;
792*11756SRobert.Johnston@Sun.COM 
793*11756SRobert.Johnston@Sun.COM 	if (ilp->il_session_active)
794*11756SRobert.Johnston@Sun.COM 		(void) ipmi_close_session_cmd(ilp->il_ihp);
795*11756SRobert.Johnston@Sun.COM 
796*11756SRobert.Johnston@Sun.COM 	if (ilp->il_sd >= 0)
797*11756SRobert.Johnston@Sun.COM 		(void) close(ilp->il_sd);
798*11756SRobert.Johnston@Sun.COM 
799*11756SRobert.Johnston@Sun.COM 	ipmi_req_clear_entries(ilp->il_ihp);
800*11756SRobert.Johnston@Sun.COM 	ipmi_free(ilp->il_ihp, ipmi_req_entries);
801*11756SRobert.Johnston@Sun.COM 	ipmi_free(ilp->il_ihp, ilp);
802*11756SRobert.Johnston@Sun.COM }
803*11756SRobert.Johnston@Sun.COM 
804*11756SRobert.Johnston@Sun.COM static void *
ipmi_lan_open(ipmi_handle_t * ihp,nvlist_t * params)805*11756SRobert.Johnston@Sun.COM ipmi_lan_open(ipmi_handle_t *ihp, nvlist_t *params)
806*11756SRobert.Johnston@Sun.COM {
807*11756SRobert.Johnston@Sun.COM 	int rc;
808*11756SRobert.Johnston@Sun.COM 	struct hostent *host;
809*11756SRobert.Johnston@Sun.COM 	ipmi_lan_t *ilp;
810*11756SRobert.Johnston@Sun.COM 	char *hostname, *user, *authcode;
811*11756SRobert.Johnston@Sun.COM 
812*11756SRobert.Johnston@Sun.COM 	if ((ilp = ipmi_zalloc(ihp, sizeof (ipmi_lan_t))) == NULL) {
813*11756SRobert.Johnston@Sun.COM 		/* ipmi errno set */
814*11756SRobert.Johnston@Sun.COM 		return (NULL);
815*11756SRobert.Johnston@Sun.COM 	}
816*11756SRobert.Johnston@Sun.COM 	ilp->il_ihp = ihp;
817*11756SRobert.Johnston@Sun.COM 	ihp->ih_tdata = ilp;
818*11756SRobert.Johnston@Sun.COM 
819*11756SRobert.Johnston@Sun.COM 	/*
820*11756SRobert.Johnston@Sun.COM 	 * Parse the parameters passed in the params nvlist.  The following
821*11756SRobert.Johnston@Sun.COM 	 * parameters are required
822*11756SRobert.Johnston@Sun.COM 	 *  IPMI_LAN_HOST, IPMI_LAN_USER and IPMI_LAN_PASSWD
823*11756SRobert.Johnston@Sun.COM 	 *
824*11756SRobert.Johnston@Sun.COM 	 * If any of these were not specified then we abort
825*11756SRobert.Johnston@Sun.COM 	 */
826*11756SRobert.Johnston@Sun.COM 	if (nvlist_lookup_string(params, IPMI_LAN_HOST, &hostname) ||
827*11756SRobert.Johnston@Sun.COM 	    nvlist_lookup_string(params, IPMI_LAN_USER, &user) ||
828*11756SRobert.Johnston@Sun.COM 	    nvlist_lookup_string(params, IPMI_LAN_PASSWD, &authcode)) {
829*11756SRobert.Johnston@Sun.COM 		ipmi_free(ihp, ilp);
830*11756SRobert.Johnston@Sun.COM 		(void) ipmi_set_error(ihp, EIPMI_BADPARAM, NULL);
831*11756SRobert.Johnston@Sun.COM 		return (NULL);
832*11756SRobert.Johnston@Sun.COM 	}
833*11756SRobert.Johnston@Sun.COM 	(void) strncpy(ilp->il_host, hostname, MAXHOSTNAMELEN);
834*11756SRobert.Johnston@Sun.COM 	(void) strncpy(ilp->il_user, user, 16);
835*11756SRobert.Johnston@Sun.COM 	(void) strncpy(ilp->il_authcode, authcode, 16);
836*11756SRobert.Johnston@Sun.COM 
837*11756SRobert.Johnston@Sun.COM 	/*
838*11756SRobert.Johnston@Sun.COM 	 * IPMI_LAN_PORT is an optional parameter and defaults to port 623
839*11756SRobert.Johnston@Sun.COM 	 * IPMI_LAN_PRIVLVL is also optional and defaults to admin
840*11756SRobert.Johnston@Sun.COM 	 * IPMI_LAN_TIMEOUT is optional and will default to 3 seconds
841*11756SRobert.Johnston@Sun.COM 	 * IPMI_LAN_NUM_RETIES is optional and will default to 5
842*11756SRobert.Johnston@Sun.COM 	 */
843*11756SRobert.Johnston@Sun.COM 	if (nvlist_lookup_uint16(params, IPMI_LAN_PORT, &ilp->il_port))
844*11756SRobert.Johnston@Sun.COM 		ilp->il_port = RMCP_UDP_PORT;
845*11756SRobert.Johnston@Sun.COM 
846*11756SRobert.Johnston@Sun.COM 	if (nvlist_lookup_uint8(params, IPMI_LAN_PRIVLVL, &ilp->il_privlvl))
847*11756SRobert.Johnston@Sun.COM 		ilp->il_privlvl = IPMI_SESSION_PRIV_ADMIN;
848*11756SRobert.Johnston@Sun.COM 
849*11756SRobert.Johnston@Sun.COM 	if (nvlist_lookup_uint32(params, IPMI_LAN_TIMEOUT, &ilp->il_timeout))
850*11756SRobert.Johnston@Sun.COM 		ilp->il_timeout = DEF_IPMI_LAN_TIMEOUT;
851*11756SRobert.Johnston@Sun.COM 
852*11756SRobert.Johnston@Sun.COM 	if (nvlist_lookup_uint8(params, IPMI_LAN_NUM_RETRIES,
853*11756SRobert.Johnston@Sun.COM 	    &ilp->il_num_retries))
854*11756SRobert.Johnston@Sun.COM 		ilp->il_num_retries = DEF_IPMI_LAN_NUM_RETRIES;
855*11756SRobert.Johnston@Sun.COM 
856*11756SRobert.Johnston@Sun.COM 	ilp->il_authtype = IPMI_SESSION_AUTHTYPE_PASSWORD;
857*11756SRobert.Johnston@Sun.COM 
858*11756SRobert.Johnston@Sun.COM 	/*
859*11756SRobert.Johnston@Sun.COM 	 * Open up and connect a UDP socket between us and the service
860*11756SRobert.Johnston@Sun.COM 	 * processor
861*11756SRobert.Johnston@Sun.COM 	 */
862*11756SRobert.Johnston@Sun.COM 	ilp->il_addr.sin_family = AF_INET;
863*11756SRobert.Johnston@Sun.COM 	ilp->il_addr.sin_port = htons(ilp->il_port);
864*11756SRobert.Johnston@Sun.COM 
865*11756SRobert.Johnston@Sun.COM 	rc = inet_pton(AF_INET, (const char *)ilp->il_host,
866*11756SRobert.Johnston@Sun.COM 	    &ilp->il_addr.sin_addr);
867*11756SRobert.Johnston@Sun.COM 	if (rc <= 0) {
868*11756SRobert.Johnston@Sun.COM 		if ((host = gethostbyname((const char *)ilp->il_host))
869*11756SRobert.Johnston@Sun.COM 		    == NULL) {
870*11756SRobert.Johnston@Sun.COM 			ipmi_free(ihp, ilp);
871*11756SRobert.Johnston@Sun.COM 			(void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL);
872*11756SRobert.Johnston@Sun.COM 			return (NULL);
873*11756SRobert.Johnston@Sun.COM 		}
874*11756SRobert.Johnston@Sun.COM 		ilp->il_addr.sin_family = host->h_addrtype;
875*11756SRobert.Johnston@Sun.COM 		(void) memcpy(&ilp->il_addr.sin_addr, host->h_addr,
876*11756SRobert.Johnston@Sun.COM 		    host->h_length);
877*11756SRobert.Johnston@Sun.COM 	}
878*11756SRobert.Johnston@Sun.COM 
879*11756SRobert.Johnston@Sun.COM 	if ((ilp->il_sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
880*11756SRobert.Johnston@Sun.COM 		ipmi_free(ihp, ilp);
881*11756SRobert.Johnston@Sun.COM 		(void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL);
882*11756SRobert.Johnston@Sun.COM 		return (NULL);
883*11756SRobert.Johnston@Sun.COM 	}
884*11756SRobert.Johnston@Sun.COM 	if (connect(ilp->il_sd, (struct sockaddr *)&ilp->il_addr,
885*11756SRobert.Johnston@Sun.COM 	    sizeof (struct sockaddr_in)) < 0) {
886*11756SRobert.Johnston@Sun.COM 		ipmi_lan_close(ilp);
887*11756SRobert.Johnston@Sun.COM 		(void) ipmi_set_error(ihp, EIPMI_LAN_OPEN_FAILED, NULL);
888*11756SRobert.Johnston@Sun.COM 		return (NULL);
889*11756SRobert.Johnston@Sun.COM 	}
890*11756SRobert.Johnston@Sun.COM 
891*11756SRobert.Johnston@Sun.COM 	if ((ipmi_req_entries = ipmi_zalloc(ihp, sizeof (ipmi_rq_entry_t)))
892*11756SRobert.Johnston@Sun.COM 	    == NULL)
893*11756SRobert.Johnston@Sun.COM 		return (NULL);
894*11756SRobert.Johnston@Sun.COM 
895*11756SRobert.Johnston@Sun.COM 	/*
896*11756SRobert.Johnston@Sun.COM 	 * Finally we start up the IPMI LAN session
897*11756SRobert.Johnston@Sun.COM 	 */
898*11756SRobert.Johnston@Sun.COM 	if ((rc = ipmi_lan_activate_session(ihp)) < 0) {
899*11756SRobert.Johnston@Sun.COM 		ipmi_lan_close(ilp);
900*11756SRobert.Johnston@Sun.COM 		return (NULL);
901*11756SRobert.Johnston@Sun.COM 	}
902*11756SRobert.Johnston@Sun.COM 
903*11756SRobert.Johnston@Sun.COM 	return (ilp);
904*11756SRobert.Johnston@Sun.COM }
905*11756SRobert.Johnston@Sun.COM 
906*11756SRobert.Johnston@Sun.COM ipmi_transport_t ipmi_transport_lan = {
907*11756SRobert.Johnston@Sun.COM 	ipmi_lan_open,
908*11756SRobert.Johnston@Sun.COM 	ipmi_lan_close,
909*11756SRobert.Johnston@Sun.COM 	ipmi_lan_send
910*11756SRobert.Johnston@Sun.COM };
911