1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3c18ec02fSPetter Reinholdtsen *
4c18ec02fSPetter Reinholdtsen * Redistribution and use in source and binary forms, with or without
5c18ec02fSPetter Reinholdtsen * modification, are permitted provided that the following conditions
6c18ec02fSPetter Reinholdtsen * are met:
7c18ec02fSPetter Reinholdtsen *
8c18ec02fSPetter Reinholdtsen * Redistribution of source code must retain the above copyright
9c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer.
10c18ec02fSPetter Reinholdtsen *
11c18ec02fSPetter Reinholdtsen * Redistribution in binary form must reproduce the above copyright
12c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer in the
13c18ec02fSPetter Reinholdtsen * documentation and/or other materials provided with the distribution.
14c18ec02fSPetter Reinholdtsen *
15c18ec02fSPetter Reinholdtsen * Neither the name of Sun Microsystems, Inc. or the names of
16c18ec02fSPetter Reinholdtsen * contributors may be used to endorse or promote products derived
17c18ec02fSPetter Reinholdtsen * from this software without specific prior written permission.
18c18ec02fSPetter Reinholdtsen *
19c18ec02fSPetter Reinholdtsen * This software is provided "AS IS," without a warranty of any kind.
20c18ec02fSPetter Reinholdtsen * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21c18ec02fSPetter Reinholdtsen * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22c18ec02fSPetter Reinholdtsen * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23c18ec02fSPetter Reinholdtsen * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24c18ec02fSPetter Reinholdtsen * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25c18ec02fSPetter Reinholdtsen * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26c18ec02fSPetter Reinholdtsen * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27c18ec02fSPetter Reinholdtsen * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28c18ec02fSPetter Reinholdtsen * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29c18ec02fSPetter Reinholdtsen * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30c18ec02fSPetter Reinholdtsen * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31c18ec02fSPetter Reinholdtsen */
32ce02ffafSZdenek Styblik #define _XOPEN_SOURCE 700
33ce02ffafSZdenek Styblik #define _GNU_SOURCE 1
34c18ec02fSPetter Reinholdtsen
35c18ec02fSPetter Reinholdtsen #include <stdio.h>
36c18ec02fSPetter Reinholdtsen #include <stdlib.h>
37c18ec02fSPetter Reinholdtsen #include <string.h>
38c18ec02fSPetter Reinholdtsen #if defined(HAVE_CONFIG_H)
39c18ec02fSPetter Reinholdtsen # include <config.h>
40c18ec02fSPetter Reinholdtsen #endif
41c18ec02fSPetter Reinholdtsen
42c18ec02fSPetter Reinholdtsen #if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
43c18ec02fSPetter Reinholdtsen #include <sys/types.h>
44c18ec02fSPetter Reinholdtsen #include <sys/socket.h>
45c18ec02fSPetter Reinholdtsen #include <netinet/in.h>
46c18ec02fSPetter Reinholdtsen #include <arpa/inet.h>
47c18ec02fSPetter Reinholdtsen #include <ifaddrs.h>
48c18ec02fSPetter Reinholdtsen #include <unistd.h>
49c18ec02fSPetter Reinholdtsen #include <netdb.h>
50c18ec02fSPetter Reinholdtsen #endif
51c18ec02fSPetter Reinholdtsen
52c18ec02fSPetter Reinholdtsen
53c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
54c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
55c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_sdr.h>
56c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
57c18ec02fSPetter Reinholdtsen
5823e9340bSZdenek Styblik #define IPMI_DEFAULT_PAYLOAD_SIZE 25
5923e9340bSZdenek Styblik
60c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_OPEN
61c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_open_intf;
62c18ec02fSPetter Reinholdtsen #endif
63c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_IMB
64c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_imb_intf;
65c18ec02fSPetter Reinholdtsen #endif
66c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_LIPMI
67c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_lipmi_intf;
68c18ec02fSPetter Reinholdtsen #endif
69c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_BMC
70c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_bmc_intf;
71c18ec02fSPetter Reinholdtsen #endif
72c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_LAN
73c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_lan_intf;
74c18ec02fSPetter Reinholdtsen #endif
75c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_LANPLUS
76c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_lanplus_intf;
77c18ec02fSPetter Reinholdtsen #endif
78c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_FREE
79c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_free_intf;
80c18ec02fSPetter Reinholdtsen #endif
81c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_SERIAL
82c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_serial_term_intf;
83c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_serial_bm_intf;
84c18ec02fSPetter Reinholdtsen #endif
85c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_DUMMY
86c18ec02fSPetter Reinholdtsen extern struct ipmi_intf ipmi_dummy_intf;
87c18ec02fSPetter Reinholdtsen #endif
88e2c5b322SZdenek Styblik #ifdef IPMI_INTF_USB
89e2c5b322SZdenek Styblik extern struct ipmi_intf ipmi_usb_intf;
90e2c5b322SZdenek Styblik #endif
91069e132eSJeremy Kerr #ifdef IPMI_INTF_DBUS
92069e132eSJeremy Kerr extern struct ipmi_intf ipmi_dbus_intf;
93069e132eSJeremy Kerr #endif
94c18ec02fSPetter Reinholdtsen
95c18ec02fSPetter Reinholdtsen struct ipmi_intf * ipmi_intf_table[] = {
96*dfdfd89eSVernon Mauery #ifdef IPMI_INTF_DBUS
97*dfdfd89eSVernon Mauery &ipmi_dbus_intf,
98*dfdfd89eSVernon Mauery #endif
99c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_OPEN
100c18ec02fSPetter Reinholdtsen &ipmi_open_intf,
101c18ec02fSPetter Reinholdtsen #endif
102c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_IMB
103c18ec02fSPetter Reinholdtsen &ipmi_imb_intf,
104c18ec02fSPetter Reinholdtsen #endif
105c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_LIPMI
106c18ec02fSPetter Reinholdtsen &ipmi_lipmi_intf,
107c18ec02fSPetter Reinholdtsen #endif
108c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_BMC
109c18ec02fSPetter Reinholdtsen &ipmi_bmc_intf,
110c18ec02fSPetter Reinholdtsen #endif
111c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_LAN
112c18ec02fSPetter Reinholdtsen &ipmi_lan_intf,
113c18ec02fSPetter Reinholdtsen #endif
114c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_LANPLUS
115c18ec02fSPetter Reinholdtsen &ipmi_lanplus_intf,
116c18ec02fSPetter Reinholdtsen #endif
117c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_FREE
118c18ec02fSPetter Reinholdtsen &ipmi_free_intf,
119c18ec02fSPetter Reinholdtsen #endif
120c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_SERIAL
121c18ec02fSPetter Reinholdtsen &ipmi_serial_term_intf,
122c18ec02fSPetter Reinholdtsen &ipmi_serial_bm_intf,
123c18ec02fSPetter Reinholdtsen #endif
124c18ec02fSPetter Reinholdtsen #ifdef IPMI_INTF_DUMMY
125c18ec02fSPetter Reinholdtsen &ipmi_dummy_intf,
126c18ec02fSPetter Reinholdtsen #endif
127e2c5b322SZdenek Styblik #ifdef IPMI_INTF_USB
128e2c5b322SZdenek Styblik &ipmi_usb_intf,
129e2c5b322SZdenek Styblik #endif
130c18ec02fSPetter Reinholdtsen NULL
131c18ec02fSPetter Reinholdtsen };
132c18ec02fSPetter Reinholdtsen
133c18ec02fSPetter Reinholdtsen /* ipmi_intf_print - Print list of interfaces
134c18ec02fSPetter Reinholdtsen *
135c18ec02fSPetter Reinholdtsen * no meaningful return code
136c18ec02fSPetter Reinholdtsen */
ipmi_intf_print(struct ipmi_intf_support * intflist)137c18ec02fSPetter Reinholdtsen void ipmi_intf_print(struct ipmi_intf_support * intflist)
138c18ec02fSPetter Reinholdtsen {
139c18ec02fSPetter Reinholdtsen struct ipmi_intf ** intf;
140c18ec02fSPetter Reinholdtsen struct ipmi_intf_support * sup;
141c18ec02fSPetter Reinholdtsen int def = 1;
142c18ec02fSPetter Reinholdtsen int found;
143c18ec02fSPetter Reinholdtsen
144c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "Interfaces:");
145c18ec02fSPetter Reinholdtsen
146c18ec02fSPetter Reinholdtsen for (intf = ipmi_intf_table; intf && *intf; intf++) {
147c18ec02fSPetter Reinholdtsen
148c18ec02fSPetter Reinholdtsen if (intflist != NULL) {
149c18ec02fSPetter Reinholdtsen found = 0;
150c18ec02fSPetter Reinholdtsen for (sup=intflist; sup->name != NULL; sup++) {
151c18ec02fSPetter Reinholdtsen if (strncmp(sup->name, (*intf)->name, strlen(sup->name)) == 0 &&
152c18ec02fSPetter Reinholdtsen strncmp(sup->name, (*intf)->name, strlen((*intf)->name)) == 0 &&
153c18ec02fSPetter Reinholdtsen sup->supported == 1)
154c18ec02fSPetter Reinholdtsen found = 1;
155c18ec02fSPetter Reinholdtsen }
156c18ec02fSPetter Reinholdtsen if (found == 0)
157c18ec02fSPetter Reinholdtsen continue;
158c18ec02fSPetter Reinholdtsen }
159c18ec02fSPetter Reinholdtsen
160c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "\t%-12s %s %s",
161c18ec02fSPetter Reinholdtsen (*intf)->name, (*intf)->desc,
162c18ec02fSPetter Reinholdtsen def ? "[default]" : "");
163c18ec02fSPetter Reinholdtsen def = 0;
164c18ec02fSPetter Reinholdtsen }
165c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE, "");
166c18ec02fSPetter Reinholdtsen }
167c18ec02fSPetter Reinholdtsen
168c18ec02fSPetter Reinholdtsen /* ipmi_intf_load - Load an interface from the interface table above
169c18ec02fSPetter Reinholdtsen * If no interface name is given return first entry
170c18ec02fSPetter Reinholdtsen *
171c18ec02fSPetter Reinholdtsen * @name: interface name to try and load
172c18ec02fSPetter Reinholdtsen *
173c18ec02fSPetter Reinholdtsen * returns pointer to inteface structure if found
174c18ec02fSPetter Reinholdtsen * returns NULL on error
175c18ec02fSPetter Reinholdtsen */
ipmi_intf_load(char * name)176c18ec02fSPetter Reinholdtsen struct ipmi_intf * ipmi_intf_load(char * name)
177c18ec02fSPetter Reinholdtsen {
178c18ec02fSPetter Reinholdtsen struct ipmi_intf ** intf;
179c18ec02fSPetter Reinholdtsen struct ipmi_intf * i;
180c18ec02fSPetter Reinholdtsen
181c18ec02fSPetter Reinholdtsen if (name == NULL) {
182c18ec02fSPetter Reinholdtsen i = ipmi_intf_table[0];
183c18ec02fSPetter Reinholdtsen if (i->setup != NULL && (i->setup(i) < 0)) {
184c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to setup "
185c18ec02fSPetter Reinholdtsen "interface %s", name);
186c18ec02fSPetter Reinholdtsen return NULL;
187c18ec02fSPetter Reinholdtsen }
188c18ec02fSPetter Reinholdtsen return i;
189c18ec02fSPetter Reinholdtsen }
190c18ec02fSPetter Reinholdtsen
191c18ec02fSPetter Reinholdtsen for (intf = ipmi_intf_table;
192c18ec02fSPetter Reinholdtsen ((intf != NULL) && (*intf != NULL));
193c18ec02fSPetter Reinholdtsen intf++) {
194c18ec02fSPetter Reinholdtsen i = *intf;
195c18ec02fSPetter Reinholdtsen if (strncmp(name, i->name, strlen(name)) == 0) {
196c18ec02fSPetter Reinholdtsen if (i->setup != NULL && (i->setup(i) < 0)) {
197c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to setup "
198c18ec02fSPetter Reinholdtsen "interface %s", name);
199c18ec02fSPetter Reinholdtsen return NULL;
200c18ec02fSPetter Reinholdtsen }
201c18ec02fSPetter Reinholdtsen return i;
202c18ec02fSPetter Reinholdtsen }
203c18ec02fSPetter Reinholdtsen }
204c18ec02fSPetter Reinholdtsen
205c18ec02fSPetter Reinholdtsen return NULL;
206c18ec02fSPetter Reinholdtsen }
207c18ec02fSPetter Reinholdtsen
208c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_hostname(struct ipmi_intf * intf,char * hostname)209c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname)
210c18ec02fSPetter Reinholdtsen {
211eb541367SZdenek Styblik if (intf->ssn_params.hostname != NULL) {
212eb541367SZdenek Styblik free(intf->ssn_params.hostname);
213eb541367SZdenek Styblik intf->ssn_params.hostname = NULL;
214eb541367SZdenek Styblik }
215eb541367SZdenek Styblik if (hostname == NULL) {
216c18ec02fSPetter Reinholdtsen return;
217c18ec02fSPetter Reinholdtsen }
218eb541367SZdenek Styblik intf->ssn_params.hostname = strdup(hostname);
219c18ec02fSPetter Reinholdtsen }
220c18ec02fSPetter Reinholdtsen
221c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_username(struct ipmi_intf * intf,char * username)222c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username)
223c18ec02fSPetter Reinholdtsen {
224eb541367SZdenek Styblik memset(intf->ssn_params.username, 0, 17);
225c18ec02fSPetter Reinholdtsen
226c18ec02fSPetter Reinholdtsen if (username == NULL)
227c18ec02fSPetter Reinholdtsen return;
228c18ec02fSPetter Reinholdtsen
229eb541367SZdenek Styblik memcpy(intf->ssn_params.username, username, __min(strlen(username), 16));
230c18ec02fSPetter Reinholdtsen }
231c18ec02fSPetter Reinholdtsen
232c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_password(struct ipmi_intf * intf,char * password)233c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password)
234c18ec02fSPetter Reinholdtsen {
235eb541367SZdenek Styblik memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE);
236c18ec02fSPetter Reinholdtsen
237c18ec02fSPetter Reinholdtsen if (password == NULL) {
238eb541367SZdenek Styblik intf->ssn_params.password = 0;
239c18ec02fSPetter Reinholdtsen return;
240c18ec02fSPetter Reinholdtsen }
241c18ec02fSPetter Reinholdtsen
242eb541367SZdenek Styblik intf->ssn_params.password = 1;
243eb541367SZdenek Styblik memcpy(intf->ssn_params.authcode_set, password,
244c18ec02fSPetter Reinholdtsen __min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE));
245c18ec02fSPetter Reinholdtsen }
246c18ec02fSPetter Reinholdtsen
247c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_privlvl(struct ipmi_intf * intf,uint8_t level)248c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level)
249c18ec02fSPetter Reinholdtsen {
250eb541367SZdenek Styblik intf->ssn_params.privlvl = level;
251c18ec02fSPetter Reinholdtsen }
252c18ec02fSPetter Reinholdtsen
253c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf,uint8_t lookupbit)254c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
255c18ec02fSPetter Reinholdtsen {
256eb541367SZdenek Styblik intf->ssn_params.lookupbit = lookupbit;
257c18ec02fSPetter Reinholdtsen }
258c18ec02fSPetter Reinholdtsen
259c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf,uint8_t cipher_suite_id)260c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
261c18ec02fSPetter Reinholdtsen {
262eb541367SZdenek Styblik intf->ssn_params.cipher_suite_id = cipher_suite_id;
263c18ec02fSPetter Reinholdtsen }
264c18ec02fSPetter Reinholdtsen
265c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf,char sol_escape_char)266c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
267c18ec02fSPetter Reinholdtsen {
268eb541367SZdenek Styblik intf->ssn_params.sol_escape_char = sol_escape_char;
269c18ec02fSPetter Reinholdtsen }
270c18ec02fSPetter Reinholdtsen
271c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_kgkey(struct ipmi_intf * intf,char * kgkey)272c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey)
273c18ec02fSPetter Reinholdtsen {
274eb541367SZdenek Styblik memset(intf->ssn_params.kg, 0, IPMI_KG_BUFFER_SIZE);
275c18ec02fSPetter Reinholdtsen
276c18ec02fSPetter Reinholdtsen if (kgkey == NULL)
277c18ec02fSPetter Reinholdtsen return;
278c18ec02fSPetter Reinholdtsen
279eb541367SZdenek Styblik memcpy(intf->ssn_params.kg, kgkey,
280c18ec02fSPetter Reinholdtsen __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE));
281c18ec02fSPetter Reinholdtsen }
282c18ec02fSPetter Reinholdtsen
283c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_port(struct ipmi_intf * intf,int port)284c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_port(struct ipmi_intf * intf, int port)
285c18ec02fSPetter Reinholdtsen {
286eb541367SZdenek Styblik intf->ssn_params.port = port;
287c18ec02fSPetter Reinholdtsen }
288c18ec02fSPetter Reinholdtsen
289c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_authtype(struct ipmi_intf * intf,uint8_t authtype)290c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype)
291c18ec02fSPetter Reinholdtsen {
292c18ec02fSPetter Reinholdtsen /* clear password field if authtype NONE specified */
293c18ec02fSPetter Reinholdtsen if (authtype == IPMI_SESSION_AUTHTYPE_NONE) {
294eb541367SZdenek Styblik memset(intf->ssn_params.authcode_set, 0, IPMI_AUTHCODE_BUFFER_SIZE);
295eb541367SZdenek Styblik intf->ssn_params.password = 0;
296c18ec02fSPetter Reinholdtsen }
297c18ec02fSPetter Reinholdtsen
298eb541367SZdenek Styblik intf->ssn_params.authtype_set = authtype;
299c18ec02fSPetter Reinholdtsen }
300c18ec02fSPetter Reinholdtsen
301c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_timeout(struct ipmi_intf * intf,uint32_t timeout)302c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout)
303c18ec02fSPetter Reinholdtsen {
304eb541367SZdenek Styblik intf->ssn_params.timeout = timeout;
305c18ec02fSPetter Reinholdtsen }
306c18ec02fSPetter Reinholdtsen
307c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_set_retry(struct ipmi_intf * intf,int retry)308c18ec02fSPetter Reinholdtsen ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry)
309c18ec02fSPetter Reinholdtsen {
310eb541367SZdenek Styblik intf->ssn_params.retry = retry;
311c18ec02fSPetter Reinholdtsen }
312c18ec02fSPetter Reinholdtsen
313c18ec02fSPetter Reinholdtsen void
ipmi_intf_session_cleanup(struct ipmi_intf * intf)314deb9a4edSZdenek Styblik ipmi_intf_session_cleanup(struct ipmi_intf *intf)
315deb9a4edSZdenek Styblik {
316deb9a4edSZdenek Styblik if (intf->session == NULL) {
317deb9a4edSZdenek Styblik return;
318deb9a4edSZdenek Styblik }
319eb541367SZdenek Styblik
320deb9a4edSZdenek Styblik free(intf->session);
321deb9a4edSZdenek Styblik intf->session = NULL;
322deb9a4edSZdenek Styblik }
323deb9a4edSZdenek Styblik
324deb9a4edSZdenek Styblik void
ipmi_cleanup(struct ipmi_intf * intf)325c18ec02fSPetter Reinholdtsen ipmi_cleanup(struct ipmi_intf * intf)
326c18ec02fSPetter Reinholdtsen {
327c18ec02fSPetter Reinholdtsen ipmi_sdr_list_empty(intf);
328eb541367SZdenek Styblik ipmi_intf_session_set_hostname(intf, NULL);
329c18ec02fSPetter Reinholdtsen }
330c18ec02fSPetter Reinholdtsen
331c18ec02fSPetter Reinholdtsen #if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
332c18ec02fSPetter Reinholdtsen int
ipmi_intf_socket_connect(struct ipmi_intf * intf)333c18ec02fSPetter Reinholdtsen ipmi_intf_socket_connect(struct ipmi_intf * intf)
334c18ec02fSPetter Reinholdtsen {
335eb541367SZdenek Styblik struct ipmi_session_params *params;
336c18ec02fSPetter Reinholdtsen
337c18ec02fSPetter Reinholdtsen struct sockaddr_storage addr;
338c18ec02fSPetter Reinholdtsen struct addrinfo hints;
339c18ec02fSPetter Reinholdtsen struct addrinfo *rp0 = NULL, *rp;
340c18ec02fSPetter Reinholdtsen char service[NI_MAXSERV];
341c18ec02fSPetter Reinholdtsen
342eb541367SZdenek Styblik if (!intf) {
343c18ec02fSPetter Reinholdtsen return -1;
344c18ec02fSPetter Reinholdtsen }
345c18ec02fSPetter Reinholdtsen
346eb541367SZdenek Styblik params = &intf->ssn_params;
347c18ec02fSPetter Reinholdtsen
348eb541367SZdenek Styblik if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) {
349c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "No hostname specified!");
350c18ec02fSPetter Reinholdtsen return -1;
351c18ec02fSPetter Reinholdtsen }
352c18ec02fSPetter Reinholdtsen
353c18ec02fSPetter Reinholdtsen /* open port to BMC */
354c18ec02fSPetter Reinholdtsen memset(&addr, 0, sizeof(addr));
355c18ec02fSPetter Reinholdtsen
356eb541367SZdenek Styblik sprintf(service, "%d", params->port);
357c18ec02fSPetter Reinholdtsen /* Obtain address(es) matching host/port */
358c18ec02fSPetter Reinholdtsen memset(&hints, 0, sizeof(hints));
359c18ec02fSPetter Reinholdtsen hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
360c18ec02fSPetter Reinholdtsen hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
361c18ec02fSPetter Reinholdtsen hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */
362c18ec02fSPetter Reinholdtsen hints.ai_protocol = IPPROTO_UDP; /* */
363c18ec02fSPetter Reinholdtsen
364eb541367SZdenek Styblik if (getaddrinfo(params->hostname, service, &hints, &rp0) != 0) {
365c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Address lookup for %s failed",
366eb541367SZdenek Styblik params->hostname);
367c18ec02fSPetter Reinholdtsen return -1;
368c18ec02fSPetter Reinholdtsen }
369c18ec02fSPetter Reinholdtsen
370c18ec02fSPetter Reinholdtsen /* getaddrinfo() returns a list of address structures.
371c18ec02fSPetter Reinholdtsen * Try each address until we successfully connect(2).
372c18ec02fSPetter Reinholdtsen * If socket(2) (or connect(2)) fails, we (close the socket
373c18ec02fSPetter Reinholdtsen * and) try the next address.
374c18ec02fSPetter Reinholdtsen */
375c18ec02fSPetter Reinholdtsen
376c18ec02fSPetter Reinholdtsen for (rp = rp0; rp != NULL; rp = rp->ai_next) {
377c18ec02fSPetter Reinholdtsen /* We are only interested in IPv4 and IPv6 */
378c18ec02fSPetter Reinholdtsen if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) {
379c18ec02fSPetter Reinholdtsen continue;
380c18ec02fSPetter Reinholdtsen }
381c18ec02fSPetter Reinholdtsen
382c18ec02fSPetter Reinholdtsen intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
383c18ec02fSPetter Reinholdtsen if (intf->fd == -1) {
384c18ec02fSPetter Reinholdtsen continue;
385c18ec02fSPetter Reinholdtsen }
386c18ec02fSPetter Reinholdtsen
387c18ec02fSPetter Reinholdtsen if (rp->ai_family == AF_INET) {
388c18ec02fSPetter Reinholdtsen if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
389eb541367SZdenek Styblik hints.ai_family = rp->ai_family;
390c18ec02fSPetter Reinholdtsen break; /* Success */
391c18ec02fSPetter Reinholdtsen }
392c18ec02fSPetter Reinholdtsen } else if (rp->ai_family == AF_INET6) {
393c18ec02fSPetter Reinholdtsen struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr;
394c18ec02fSPetter Reinholdtsen char hbuf[NI_MAXHOST];
395c18ec02fSPetter Reinholdtsen socklen_t len;
396c18ec02fSPetter Reinholdtsen
397c18ec02fSPetter Reinholdtsen /* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */
398c18ec02fSPetter Reinholdtsen if (addr6->sin6_scope_id != 0) {
399c18ec02fSPetter Reinholdtsen len = sizeof(struct sockaddr_in6);
400c18ec02fSPetter Reinholdtsen if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
401c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
402c18ec02fSPetter Reinholdtsen hbuf,
403c18ec02fSPetter Reinholdtsen addr6->sin6_scope_id);
404c18ec02fSPetter Reinholdtsen }
405c18ec02fSPetter Reinholdtsen if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
406eb541367SZdenek Styblik hints.ai_family = rp->ai_family;
407c18ec02fSPetter Reinholdtsen break; /* Success */
408c18ec02fSPetter Reinholdtsen }
409c18ec02fSPetter Reinholdtsen } else {
410c18ec02fSPetter Reinholdtsen /* No scope specified, try to get this from the list of interfaces */
411c18ec02fSPetter Reinholdtsen struct ifaddrs *ifaddrs = NULL;
412c18ec02fSPetter Reinholdtsen struct ifaddrs *ifa = NULL;
413c18ec02fSPetter Reinholdtsen
414c18ec02fSPetter Reinholdtsen if (getifaddrs(&ifaddrs) < 0) {
415c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Interface address lookup for %s failed",
416eb541367SZdenek Styblik params->hostname);
417c18ec02fSPetter Reinholdtsen break;
418c18ec02fSPetter Reinholdtsen }
419c18ec02fSPetter Reinholdtsen
420c18ec02fSPetter Reinholdtsen for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
421c18ec02fSPetter Reinholdtsen if (ifa->ifa_addr == NULL) {
422c18ec02fSPetter Reinholdtsen continue;
423c18ec02fSPetter Reinholdtsen }
424c18ec02fSPetter Reinholdtsen
425c18ec02fSPetter Reinholdtsen if (ifa->ifa_addr->sa_family == AF_INET6) {
426c18ec02fSPetter Reinholdtsen struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr;
427c18ec02fSPetter Reinholdtsen
428c18ec02fSPetter Reinholdtsen /* Skip unwanted addresses */
429c18ec02fSPetter Reinholdtsen if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) {
430c18ec02fSPetter Reinholdtsen continue;
431c18ec02fSPetter Reinholdtsen }
432c18ec02fSPetter Reinholdtsen if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) {
433c18ec02fSPetter Reinholdtsen continue;
434c18ec02fSPetter Reinholdtsen }
435c18ec02fSPetter Reinholdtsen len = sizeof(struct sockaddr_in6);
436c18ec02fSPetter Reinholdtsen if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
437c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
438c18ec02fSPetter Reinholdtsen ifa->ifa_name != NULL ? ifa->ifa_name : "???",
439c18ec02fSPetter Reinholdtsen hbuf,
440c18ec02fSPetter Reinholdtsen tmp6->sin6_scope_id);
441c18ec02fSPetter Reinholdtsen }
442c18ec02fSPetter Reinholdtsen
443c18ec02fSPetter Reinholdtsen if (tmp6->sin6_scope_id != 0) {
444c18ec02fSPetter Reinholdtsen addr6->sin6_scope_id = tmp6->sin6_scope_id;
445c18ec02fSPetter Reinholdtsen } else {
446c18ec02fSPetter Reinholdtsen /*
447c18ec02fSPetter Reinholdtsen * No scope information in interface address information
448c18ec02fSPetter Reinholdtsen * On some OS'es, getifaddrs() is returning out the 'kernel' representation
449c18ec02fSPetter Reinholdtsen * of scoped addresses which stores the scope in the 3rd and 4th
450c18ec02fSPetter Reinholdtsen * byte. See also this page:
451c18ec02fSPetter Reinholdtsen * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html
452c18ec02fSPetter Reinholdtsen */
453c18ec02fSPetter Reinholdtsen if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)
4544c5058cdSGaurav Jain && (tmp6->sin6_addr.s6_addr[1] != 0)) {
4554c5058cdSGaurav Jain addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr[1]);
456c18ec02fSPetter Reinholdtsen }
457c18ec02fSPetter Reinholdtsen }
458c18ec02fSPetter Reinholdtsen
459c18ec02fSPetter Reinholdtsen /* OK, now try to connect with the scope id from this interface address */
460c18ec02fSPetter Reinholdtsen if (addr6->sin6_scope_id != 0) {
461c18ec02fSPetter Reinholdtsen if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
462eb541367SZdenek Styblik hints.ai_family = rp->ai_family;
463c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id);
464c18ec02fSPetter Reinholdtsen break; /* Success */
465c18ec02fSPetter Reinholdtsen }
466c18ec02fSPetter Reinholdtsen }
467c18ec02fSPetter Reinholdtsen }
468c18ec02fSPetter Reinholdtsen }
469c18ec02fSPetter Reinholdtsen freeifaddrs(ifaddrs);
470c18ec02fSPetter Reinholdtsen }
471c18ec02fSPetter Reinholdtsen }
472eb541367SZdenek Styblik if (hints.ai_family != AF_UNSPEC) {
473c18ec02fSPetter Reinholdtsen break;
474c18ec02fSPetter Reinholdtsen }
475c18ec02fSPetter Reinholdtsen close(intf->fd);
476c18ec02fSPetter Reinholdtsen intf->fd = -1;
477c18ec02fSPetter Reinholdtsen }
478c18ec02fSPetter Reinholdtsen
479c18ec02fSPetter Reinholdtsen /* No longer needed */
480c18ec02fSPetter Reinholdtsen freeaddrinfo(rp0);
481c18ec02fSPetter Reinholdtsen
482c18ec02fSPetter Reinholdtsen return ((intf->fd != -1) ? 0 : -1);
483c18ec02fSPetter Reinholdtsen }
484c18ec02fSPetter Reinholdtsen #endif
485c18ec02fSPetter Reinholdtsen
48623e9340bSZdenek Styblik uint16_t
ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf)48723e9340bSZdenek Styblik ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf)
48823e9340bSZdenek Styblik {
48923e9340bSZdenek Styblik int16_t size;
49023e9340bSZdenek Styblik
49123e9340bSZdenek Styblik size = intf->max_request_data_size;
49223e9340bSZdenek Styblik
49323e9340bSZdenek Styblik /* check if request size is not specified */
49423e9340bSZdenek Styblik if (!size) {
49523e9340bSZdenek Styblik /*
49623e9340bSZdenek Styblik * The IPMB standard overall message length for �non -bridging�
49723e9340bSZdenek Styblik * messages is specified as 32 bytes, maximum, including slave
49823e9340bSZdenek Styblik * address. This sets the upper limit for typical IPMI messages.
49923e9340bSZdenek Styblik * With the exception of messages used for bridging messages to
50023e9340bSZdenek Styblik * other busses or interfaces (e.g. Master Write-Read and Send Message)
50123e9340bSZdenek Styblik * IPMI messages should be designed to fit within this 32-byte maximum.
50223e9340bSZdenek Styblik * In order to support bridging, the Master Write -Read and Send Message
50323e9340bSZdenek Styblik * commands are allowed to exceed the 32-byte maximum transaction on IPMB
50423e9340bSZdenek Styblik */
50523e9340bSZdenek Styblik
50623e9340bSZdenek Styblik size = IPMI_DEFAULT_PAYLOAD_SIZE;
50723e9340bSZdenek Styblik
50823e9340bSZdenek Styblik /* check if message is forwarded */
50923e9340bSZdenek Styblik if (intf->target_addr && intf->target_addr != intf->my_addr) {
51023e9340bSZdenek Styblik /* add Send Message request size */
51123e9340bSZdenek Styblik size += 8;
51223e9340bSZdenek Styblik }
51323e9340bSZdenek Styblik }
51423e9340bSZdenek Styblik
51523e9340bSZdenek Styblik /* check if message is forwarded */
51623e9340bSZdenek Styblik if (intf->target_addr && intf->target_addr != intf->my_addr) {
51723e9340bSZdenek Styblik /* subtract send message request size */
51823e9340bSZdenek Styblik size -= 8;
51923e9340bSZdenek Styblik
52023e9340bSZdenek Styblik /*
52123e9340bSZdenek Styblik * Check that forwarded request size is not greater
52223e9340bSZdenek Styblik * than the default payload size.
52323e9340bSZdenek Styblik */
52423e9340bSZdenek Styblik if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
52523e9340bSZdenek Styblik size = IPMI_DEFAULT_PAYLOAD_SIZE;
52623e9340bSZdenek Styblik }
52723e9340bSZdenek Styblik
52823e9340bSZdenek Styblik /* check for double bridging */
52923e9340bSZdenek Styblik if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
53023e9340bSZdenek Styblik /* subtract inner send message request size */
53123e9340bSZdenek Styblik size -= 8;
53223e9340bSZdenek Styblik }
53323e9340bSZdenek Styblik }
53423e9340bSZdenek Styblik
53523e9340bSZdenek Styblik /* check for underflow */
53623e9340bSZdenek Styblik if (size < 0) {
53723e9340bSZdenek Styblik return 0;
53823e9340bSZdenek Styblik }
53923e9340bSZdenek Styblik
54023e9340bSZdenek Styblik return size;
54123e9340bSZdenek Styblik }
54223e9340bSZdenek Styblik
54323e9340bSZdenek Styblik uint16_t
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf)54423e9340bSZdenek Styblik ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf)
54523e9340bSZdenek Styblik {
54623e9340bSZdenek Styblik int16_t size;
54723e9340bSZdenek Styblik
54823e9340bSZdenek Styblik size = intf->max_response_data_size;
54923e9340bSZdenek Styblik
55023e9340bSZdenek Styblik /* check if response size is not specified */
55123e9340bSZdenek Styblik if (!size) {
55223e9340bSZdenek Styblik /*
55323e9340bSZdenek Styblik * The IPMB standard overall message length for �non -bridging�
55423e9340bSZdenek Styblik * messages is specified as 32 bytes, maximum, including slave
55523e9340bSZdenek Styblik * address. This sets the upper limit for typical IPMI messages.
55623e9340bSZdenek Styblik * With the exception of messages used for bridging messages to
55723e9340bSZdenek Styblik * other busses or interfaces (e.g. Master Write-Read and Send Message)
55823e9340bSZdenek Styblik * IPMI messages should be designed to fit within this 32-byte maximum.
55923e9340bSZdenek Styblik * In order to support bridging, the Master Write -Read and Send Message
56023e9340bSZdenek Styblik * commands are allowed to exceed the 32-byte maximum transaction on IPMB
56123e9340bSZdenek Styblik */
56223e9340bSZdenek Styblik
56323e9340bSZdenek Styblik size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */
56423e9340bSZdenek Styblik
56523e9340bSZdenek Styblik /* check if message is forwarded */
56623e9340bSZdenek Styblik if (intf->target_addr && intf->target_addr != intf->my_addr) {
56723e9340bSZdenek Styblik /* add Send Message header size */
56823e9340bSZdenek Styblik size += 7;
56923e9340bSZdenek Styblik }
57023e9340bSZdenek Styblik }
57123e9340bSZdenek Styblik
57223e9340bSZdenek Styblik /* check if message is forwarded */
57323e9340bSZdenek Styblik if (intf->target_addr && intf->target_addr != intf->my_addr) {
57423e9340bSZdenek Styblik /*
57523e9340bSZdenek Styblik * Some IPMI controllers like PICMG AMC Carriers embed responses
57623e9340bSZdenek Styblik * to the forwarded messages into the Send Message response.
57723e9340bSZdenek Styblik * In order to be sure that the response is not truncated,
57823e9340bSZdenek Styblik * subtract the internal message header size.
57923e9340bSZdenek Styblik */
58023e9340bSZdenek Styblik size -= 8;
58123e9340bSZdenek Styblik
58223e9340bSZdenek Styblik /*
58323e9340bSZdenek Styblik * Check that forwarded response is not greater
58423e9340bSZdenek Styblik * than the default payload size.
58523e9340bSZdenek Styblik */
58623e9340bSZdenek Styblik if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
58723e9340bSZdenek Styblik size = IPMI_DEFAULT_PAYLOAD_SIZE;
58823e9340bSZdenek Styblik }
58923e9340bSZdenek Styblik
59023e9340bSZdenek Styblik /* check for double bridging */
59123e9340bSZdenek Styblik if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
59223e9340bSZdenek Styblik /* subtract inner send message header size */
59323e9340bSZdenek Styblik size -= 8;
59423e9340bSZdenek Styblik }
59523e9340bSZdenek Styblik }
59623e9340bSZdenek Styblik
59723e9340bSZdenek Styblik /* check for underflow */
59823e9340bSZdenek Styblik if (size < 0) {
59923e9340bSZdenek Styblik return 0;
60023e9340bSZdenek Styblik }
60123e9340bSZdenek Styblik
60223e9340bSZdenek Styblik return size;
60323e9340bSZdenek Styblik }
60423e9340bSZdenek Styblik
60523e9340bSZdenek Styblik void
ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf,uint16_t size)60623e9340bSZdenek Styblik ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size)
60723e9340bSZdenek Styblik {
60823e9340bSZdenek Styblik if (size < IPMI_DEFAULT_PAYLOAD_SIZE) {
60923e9340bSZdenek Styblik lprintf(LOG_ERR, "Request size is too small (%d), leave default size",
61023e9340bSZdenek Styblik size);
61123e9340bSZdenek Styblik return;
61223e9340bSZdenek Styblik }
61323e9340bSZdenek Styblik
61423e9340bSZdenek Styblik if (intf->set_max_request_data_size) {
61523e9340bSZdenek Styblik intf->set_max_request_data_size(intf, size);
61623e9340bSZdenek Styblik } else {
61723e9340bSZdenek Styblik intf->max_request_data_size = size;
61823e9340bSZdenek Styblik }
61923e9340bSZdenek Styblik }
62023e9340bSZdenek Styblik
62123e9340bSZdenek Styblik void
ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf,uint16_t size)62223e9340bSZdenek Styblik ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size)
62323e9340bSZdenek Styblik {
62423e9340bSZdenek Styblik if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) {
62523e9340bSZdenek Styblik lprintf(LOG_ERR, "Response size is too small (%d), leave default size",
62623e9340bSZdenek Styblik size);
62723e9340bSZdenek Styblik return;
62823e9340bSZdenek Styblik }
62923e9340bSZdenek Styblik
63023e9340bSZdenek Styblik if (intf->set_max_response_data_size) {
63123e9340bSZdenek Styblik intf->set_max_response_data_size(intf, size);
63223e9340bSZdenek Styblik } else {
63323e9340bSZdenek Styblik intf->max_response_data_size = size;
63423e9340bSZdenek Styblik }
63523e9340bSZdenek Styblik }
636