1
/* scan_ipmi.c: detect NUT supported Power Supply Units
4
* 2011 - 2012 Arnaud Quette <arnaud.quette@free.fr>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
#include "upsclient.h"
25
#include <freeipmi/freeipmi.h>
30
#define NUT_IPMI_DRV_NAME "nut-ipmipsu"
33
/* 5 seconds for establishing an IPMI connection */
34
#define IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT 5000
35
#define IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT 250
37
/* dynamic link library stuff */
38
static char * libname = "libfreeipmi";
39
static lt_dlhandle dl_handle = NULL;
40
static const char *dl_error = NULL;
42
#ifdef HAVE_FREEIPMI_11X_12X
43
/* Functions symbols remapping */
44
#define IPMI_FRU_CLOSE_DEVICE_ID "ipmi_fru_close_device_id"
45
#define IPMI_FRU_CTX_DESTROY "ipmi_fru_ctx_destroy"
46
#define IPMI_FRU_CTX_CREATE "ipmi_fru_ctx_create"
47
#define IPMI_FRU_CTX_SET_FLAGS "ipmi_fru_ctx_set_flags"
48
#define IPMI_FRU_OPEN_DEVICE_ID "ipmi_fru_open_device_id"
49
#define IPMI_FRU_CTX_ERRORMSG "ipmi_fru_ctx_errormsg"
50
#define IPMI_FRU_READ_DATA_AREA "ipmi_fru_read_data_area"
51
#define IPMI_FRU_PARSE_NEXT "ipmi_fru_next"
52
typedef ipmi_fru_ctx_t ipmi_fru_parse_ctx_t;
53
typedef ipmi_sdr_ctx_t ipmi_sdr_cache_ctx_t;
54
/* Functions remapping */
55
static void (*nut_ipmi_sdr_ctx_destroy) (ipmi_sdr_ctx_t ctx);
56
#else /* HAVE_FREEIPMI_11X_12X */
57
#define IPMI_FRU_AREA_SIZE_MAX IPMI_FRU_PARSE_AREA_SIZE_MAX
58
#define IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS
59
#define IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION
60
/* Functions symbols remapping */
61
#define IPMI_FRU_CLOSE_DEVICE_ID "ipmi_fru_parse_close_device_id"
62
#define IPMI_FRU_CTX_DESTROY "ipmi_fru_parse_ctx_destroy"
63
#define IPMI_FRU_CTX_CREATE "ipmi_fru_parse_ctx_create"
64
#define IPMI_FRU_CTX_SET_FLAGS "ipmi_fru_parse_ctx_set_flags"
65
#define IPMI_FRU_OPEN_DEVICE_ID "ipmi_fru_parse_open_device_id"
66
#define IPMI_FRU_CTX_ERRORMSG "ipmi_fru_parse_ctx_errormsg"
67
#define IPMI_FRU_READ_DATA_AREA "ipmi_fru_parse_read_data_area"
68
#define IPMI_FRU_PARSE_NEXT "ipmi_fru_parse_next"
69
/* Functions remapping */
70
static void (*nut_ipmi_sdr_cache_ctx_destroy) (ipmi_sdr_cache_ctx_t ctx);
71
static void (*nut_ipmi_sdr_parse_ctx_destroy) (ipmi_sdr_parse_ctx_t ctx);
72
#endif /* HAVE_FREEIPMI_11X_12X */
75
static int (*nut_ipmi_fru_close_device_id) (ipmi_fru_parse_ctx_t ctx);
76
static void (*nut_ipmi_fru_ctx_destroy) (ipmi_fru_parse_ctx_t ctx);
77
static ipmi_fru_parse_ctx_t (*nut_ipmi_fru_ctx_create) (ipmi_ctx_t ipmi_ctx);
78
static int (*nut_ipmi_fru_ctx_set_flags) (ipmi_fru_parse_ctx_t ctx, unsigned int flags);
79
static int (*nut_ipmi_fru_open_device_id) (ipmi_fru_parse_ctx_t ctx, uint8_t fru_device_id);
80
static char * (*nut_ipmi_fru_ctx_errormsg) (ipmi_fru_parse_ctx_t ctx);
81
static int (*nut_ipmi_fru_read_data_area) (ipmi_fru_parse_ctx_t ctx,
82
unsigned int *area_type,
83
unsigned int *area_length,
85
unsigned int areabuflen);
86
static int (*nut_ipmi_fru_next) (ipmi_fru_parse_ctx_t ctx);
87
static ipmi_ctx_t (*nut_ipmi_ctx_create) (void);
88
static int (*nut_ipmi_ctx_find_inband) (ipmi_ctx_t ctx,
89
ipmi_driver_type_t *driver_type,
90
int disable_auto_probe,
91
uint16_t driver_address,
92
uint8_t register_spacing,
93
const char *driver_device,
94
unsigned int workaround_flags,
96
static int (*nut_ipmi_ctx_open_outofband) (ipmi_ctx_t ctx,
100
uint8_t authentication_type,
101
uint8_t privilege_level,
102
unsigned int session_timeout,
103
unsigned int retransmission_timeout,
104
unsigned int workaround_flags,
106
static int (*nut_ipmi_ctx_errnum) (ipmi_ctx_t ctx);
107
static char * (*nut_ipmi_ctx_errormsg) (ipmi_ctx_t ctx);
108
static int (*nut_ipmi_ctx_close) (ipmi_ctx_t ctx);
109
static void (*nut_ipmi_ctx_destroy) (ipmi_ctx_t ctx);
111
/* Internal functions */
112
static nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * sec);
114
/* Return 0 on error */
115
int nutscan_load_ipmi_library()
117
if( dl_handle != NULL ) {
118
/* if previous init failed */
119
if( dl_handle == (void *)1 ) {
122
/* init has already been done */
126
if( lt_dlinit() != 0 ) {
127
fprintf(stderr, "Error initializing lt_init\n");
131
dl_handle = lt_dlopenext(libname);
133
dl_error = lt_dlerror();
137
/* Clear any existing error */
140
*(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID);
141
if ((dl_error = lt_dlerror()) != NULL) {
145
*(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY);
146
if ((dl_error = lt_dlerror()) != NULL) {
150
#ifdef HAVE_FREEIPMI_11X_12X
152
*(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_ctx_destroy");
153
if ((dl_error = lt_dlerror()) != NULL) {
157
#else /* HAVE_FREEIPMI_11X_12X */
159
*(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_cache_ctx_destroy");
160
if ((dl_error = lt_dlerror()) != NULL) {
164
*(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_parse_ctx_destroy");
165
if ((dl_error = lt_dlerror()) != NULL) {
168
#endif /* HAVE_FREEIPMI_11X_12X */
170
*(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE);
171
if ((dl_error = lt_dlerror()) != NULL) {
175
*(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS);
176
if ((dl_error = lt_dlerror()) != NULL) {
180
*(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID);
181
if ((dl_error = lt_dlerror()) != NULL) {
185
*(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG);
186
if ((dl_error = lt_dlerror()) != NULL) {
190
*(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA);
191
if ((dl_error = lt_dlerror()) != NULL) {
195
*(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT);
196
if ((dl_error = lt_dlerror()) != NULL) {
200
*(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, "ipmi_ctx_create");
201
if ((dl_error = lt_dlerror()) != NULL) {
205
*(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, "ipmi_ctx_find_inband");
206
if ((dl_error = lt_dlerror()) != NULL) {
210
*(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband");
211
if ((dl_error = lt_dlerror()) != NULL) {
215
*(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum");
216
if ((dl_error = lt_dlerror()) != NULL) {
220
*(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg");
221
if ((dl_error = lt_dlerror()) != NULL) {
225
*(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, "ipmi_ctx_close");
226
if ((dl_error = lt_dlerror()) != NULL) {
230
*(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_ctx_destroy");
231
if ((dl_error = lt_dlerror()) != NULL) {
237
fprintf(stderr, "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", libname, dl_error);
238
dl_handle = (void *)1;
242
/* end of dynamic link library stuff */
244
/* Cleanup IPMI contexts */
245
#ifdef HAVE_FREEIPMI_11X_12X
246
static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx,
247
ipmi_sdr_ctx_t sdr_ctx)
248
#else /* HAVE_FREEIPMI_11X_12X */
249
static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx,
250
ipmi_sdr_cache_ctx_t sdr_cache_ctx,
251
ipmi_sdr_parse_ctx_t sdr_parse_ctx)
252
#endif /* HAVE_FREEIPMI_11X_12X */
255
(*nut_ipmi_fru_close_device_id) (fru_parse_ctx);
256
(*nut_ipmi_fru_ctx_destroy) (fru_parse_ctx);
259
#ifdef HAVE_FREEIPMI_11X_12X
262
(*nut_ipmi_sdr_ctx_destroy) (sdr_ctx);
265
#else /* HAVE_FREEIPMI_11X_12X */
268
(*nut_ipmi_sdr_cache_ctx_destroy) (sdr_cache_ctx);
272
(*nut_ipmi_sdr_parse_ctx_destroy) (sdr_parse_ctx);
275
#endif /* HAVE_FREEIPMI_11X_12X */
278
/* Return 1 if supported, 0 otherwise */
279
int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id)
282
unsigned int area_type = 0;
283
unsigned int area_length = 0;
284
uint8_t areabuf[IPMI_FRU_AREA_SIZE_MAX+1];
285
ipmi_fru_parse_ctx_t fru_parse_ctx = NULL;
286
#ifdef HAVE_FREEIPMI_11X_12X
287
ipmi_sdr_ctx_t sdr_ctx = NULL;
288
#else /* HAVE_FREEIPMI_11X_12X */
289
ipmi_sdr_cache_ctx_t sdr_cache_ctx = NULL;
290
ipmi_sdr_parse_ctx_t sdr_parse_ctx = NULL;
291
#endif /* HAVE_FREEIPMI_11X_12X */
293
/* Parse FRU information */
294
if (!(fru_parse_ctx = (*nut_ipmi_fru_ctx_create) (ipmi_ctx)))
296
fprintf(stderr, "Error with %s(): %s\n", IPMI_FRU_CTX_CREATE, (*nut_ipmi_ctx_errormsg)(ipmi_ctx));
300
/* lots of motherboards calculate checksums incorrectly */
301
if ((*nut_ipmi_fru_ctx_set_flags) (fru_parse_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0)
303
#ifdef HAVE_FREEIPMI_11X_12X
304
nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
306
nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
307
#endif /* HAVE_FREEIPMI_11X_12X */
311
if ((*nut_ipmi_fru_open_device_id) (fru_parse_ctx, ipmi_id) < 0)
313
#ifdef HAVE_FREEIPMI_11X_12X
314
nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
316
nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
317
#endif /* HAVE_FREEIPMI_11X_12X */
326
memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1);
328
/* parse FRU buffer */
329
if ((*nut_ipmi_fru_read_data_area) (fru_parse_ctx,
333
IPMI_FRU_AREA_SIZE_MAX) < 0)
335
#ifdef HAVE_FREEIPMI_11X_12X
336
nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
338
nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
339
#endif /* HAVE_FREEIPMI_11X_12X */
345
if (area_type == IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION)
347
/* Found a POWER_SUPPLY record */
348
#ifdef HAVE_FREEIPMI_11X_12X
349
nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
351
nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
352
#endif /* HAVE_FREEIPMI_11X_12X */
356
} while ((ret = (*nut_ipmi_fru_next) (fru_parse_ctx)) == 1);
358
/* No need for further errors checking */
359
#ifdef HAVE_FREEIPMI_11X_12X
360
nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
362
nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
363
#endif /* HAVE_FREEIPMI_11X_12X */
367
/* Check for IPMI support on a specific (local or remote) system
368
* Return NULL on error, or a valid nutscan_device_t otherwise */
369
nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * ipmi_sec)
371
ipmi_ctx_t ipmi_ctx = NULL;
372
nutscan_device_t * nut_dev = NULL;
373
nutscan_device_t * current_nut_dev = NULL;
378
if( !nutscan_avail_ipmi ) {
382
/* Initialize the FreeIPMI library. */
383
if (!(ipmi_ctx = (*nut_ipmi_ctx_create) ()))
385
/* we have to force cleanup, since exit handler is not yet installed */
386
fprintf(stderr, "ipmi_ctx_create\n");
390
/* Are we scanning locally, or over the network? */
393
/* FIXME: we need root right to access local IPMI!
394
if (!ipmi_is_root ()) {
395
fprintf(stderr, "IPMI scan: %s\n", ipmi_ctx_strerror (IPMI_ERR_PERMISSION));
398
if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx,
400
0, /* don't disable auto-probe */
404
0, /* workaround flags, none by default */
408
fprintf(stderr, "ipmi_ctx_find_inband: %s\n",
409
(*nut_ipmi_ctx_errormsg) (ipmi_ctx));
414
/* No local IPMI device detected */
421
if (ipmi_sec->ipmi_version == IPMI_2_0) {
423
/* FIXME: need processing?!
424
* int parse_kg (void *out, unsigned int outlen, const char *in)
425
* if ((rv = parse_kg (common_cmd_args_config->k_g, IPMI_MAX_K_G_LENGTH + 1, data->string)) < 0)
427
* fprintf (stderr, "Config File Error: k_g input formatted incorrectly\n");
428
* exit (EXIT_FAILURE);
430
if ((ret = (*nut_ipmi_ctx_open_outofband_2_0) (ipmi_ctx,
434
ipmi_sec->K_g_BMC_key,
435
??? (ipmi_sec->K_g_BMC_key) ? config->k_g_len : 0,
436
ipmi_sec->privilege_level,
437
ipmi_sec->cipher_suite_id,
438
IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT,
439
IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT,
440
ipmi_dev->workaround_flags,
443
IPMI_MONITORING_DEBUG (("ipmi_ctx_open_outofband_2_0: %s", ipmi_ctx_errormsg (c->ipmi_ctx)));
444
if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_USERNAME_INVALID)
445
c->errnum = IPMI_MONITORING_ERR_USERNAME_INVALID;
446
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID)
447
c->errnum = IPMI_MONITORING_ERR_PASSWORD_INVALID;
448
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT)
449
c->errnum = IPMI_MONITORING_ERR_PRIVILEGE_LEVEL_INSUFFICIENT;
450
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED)
451
c->errnum = IPMI_MONITORING_ERR_PRIVILEGEL_LEVEL_CANNOT_BE_OBTAINED;
452
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_K_G_INVALID)
453
c->errnum = IPMI_MONITORING_ERR_K_G_INVALID;
454
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CIPHER_SUITE_ID_UNAVAILABLE)
455
c->errnum = IPMI_MONITORING_ERR_CIPHER_SUITE_ID_UNAVAILABLE;
456
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT)
457
c->errnum = IPMI_MONITORING_ERR_PASSWORD_VERIFICATION_TIMEOUT;
458
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_2_0_UNAVAILABLE)
459
c->errnum = IPMI_MONITORING_ERR_IPMI_2_0_UNAVAILABLE;
460
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT)
461
c->errnum = IPMI_MONITORING_ERR_CONNECTION_TIMEOUT;
462
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SESSION_TIMEOUT)
463
c->errnum = IPMI_MONITORING_ERR_SESSION_TIMEOUT;
464
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE
465
|| ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_ERROR)
466
c->errnum = IPMI_MONITORING_ERR_IPMI_ERROR;
467
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BMC_BUSY)
468
c->errnum = IPMI_MONITORING_ERR_BMC_BUSY;
469
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_OUT_OF_MEMORY)
470
c->errnum = IPMI_MONITORING_ERR_OUT_OF_MEMORY;
471
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID)
472
c->errnum = IPMI_MONITORING_ERR_HOSTNAME_INVALID;
473
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PARAMETERS)
474
c->errnum = IPMI_MONITORING_ERR_PARAMETERS;
475
else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SYSTEM_ERROR)
476
c->errnum = IPMI_MONITORING_ERR_SYSTEM_ERROR;
478
c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
482
else { /* Not IPMI 2.0 */
486
/* Fall back to IPMI 1.5 */
487
if ((ret = (*nut_ipmi_ctx_open_outofband) (ipmi_ctx,
491
ipmi_sec->authentication_type,
492
ipmi_sec->privilege_level,
493
IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT,
494
IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT,
495
ipmi_sec->workaround_flags,
499
/* No IPMI device detected on this host!
500
if ((*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID
501
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID
502
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT
503
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED
504
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_AUTHENTICATION_TYPE_UNAVAILABLE
505
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT
506
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID
507
|| (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) { */
509
/* FIXME: don't log timeout errors */
510
fprintf(stderr, "nut_ipmi_ctx_open_outofband: %s\n",
511
(*nut_ipmi_ctx_errormsg) (ipmi_ctx));
517
/* Loop through all possible components */
518
for (ipmi_id = 0 ; ipmi_id <= IPMI_FRU_DEVICE_ID_MAX ; ipmi_id++) {
520
if (is_ipmi_device_supported(ipmi_ctx, ipmi_id)) {
522
if ( (nut_dev = nutscan_new_device()) == NULL ) {
523
fprintf(stderr,"Memory allocation error\n");
524
nutscan_free_device(current_nut_dev);
528
/* Fill the device structure (sufficient with driver and port) */
529
nut_dev->type = TYPE_IPMI;
530
nut_dev->driver = strdup(NUT_IPMI_DRV_NAME);
531
if (IPaddr == NULL) {
532
sprintf(port_id, "id%x", ipmi_id);
535
/* FIXME: also check against "localhost" and its IPv{4,6} */
536
sprintf(port_id, "id%x@%s", ipmi_id, IPaddr);
538
nut_dev->port = strdup(port_id);
539
/* FIXME: also dump device.serial?
540
* using drivers/libfreeipmi_get_board_info() */
542
current_nut_dev = nutscan_add_device_to_device(
546
memset (port_id, 0, sizeof(port_id));
552
(*nut_ipmi_ctx_close) (ipmi_ctx);
553
(*nut_ipmi_ctx_destroy) (ipmi_ctx);
556
return current_nut_dev;
559
/* General IPMI scan entry point: scan 1 to n devices, local or remote,
561
* Return NULL on error, or a valid nutscan_device_t otherwise */
562
nutscan_device_t * nutscan_scan_ipmi(const char * start_ip, const char * stop_ip, nutscan_ipmi_t * sec)
564
nutscan_ip_iter_t ip;
565
char * ip_str = NULL;
566
nutscan_ipmi_t * tmp_sec;
567
nutscan_device_t * nut_dev = NULL;
568
nutscan_device_t * current_nut_dev = NULL;
570
if( !nutscan_avail_ipmi ) {
575
/* Are we scanning locally, or through the network? */
576
if (start_ip == NULL)
579
current_nut_dev = nutscan_scan_ipmi_device(NULL, NULL);
582
ip_str = nutscan_ip_iter_init(&ip, start_ip, stop_ip);
584
while(ip_str != NULL) {
585
tmp_sec = malloc(sizeof(nutscan_ipmi_t));
586
memcpy(tmp_sec, sec, sizeof(nutscan_ipmi_t));
588
if ((current_nut_dev = nutscan_scan_ipmi_device(ip_str, tmp_sec)) != NULL) {
589
/* Store the positive result */
590
current_nut_dev = nutscan_add_device_to_device(current_nut_dev, nut_dev);
592
/* Prepare the next iteration */
593
ip_str = nutscan_ip_iter_inc(&ip);
597
return nutscan_rewind_device(current_nut_dev);
599
#else /* WITH_IPMI */
601
nutscan_device_t * nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec)
605
#endif /* WITH_IPMI */