~ubuntu-branches/ubuntu/maverick/ipmitool/maverick

« back to all changes in this revision

Viewing changes to src/plugins/open/open.c

  • Committer: Bazaar Package Importer
  • Author(s): Petter Reinholdtsen
  • Date: 2005-04-07 01:18:44 UTC
  • Revision ID: james.westby@ubuntu.com-20050407011844-a1b206z5iefiu5vi
Tags: upstream-1.8.1
ImportĀ upstreamĀ versionĀ 1.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
 
3
 * 
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 * 
 
8
 * Redistribution of source code must retain the above copyright
 
9
 * notice, this list of conditions and the following disclaimer.
 
10
 * 
 
11
 * Redistribution in binary form must reproduce the above copyright
 
12
 * notice, this list of conditions and the following disclaimer in the
 
13
 * documentation and/or other materials provided with the distribution.
 
14
 * 
 
15
 * Neither the name of Sun Microsystems, Inc. or the names of
 
16
 * contributors may be used to endorse or promote products derived
 
17
 * from this software without specific prior written permission.
 
18
 * 
 
19
 * This software is provided "AS IS," without a warranty of any kind.
 
20
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 
21
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 
22
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 
23
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
 
24
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 
25
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
 
26
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
 
27
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
 
28
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
 
29
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 
30
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
31
 * 
 
32
 * You acknowledge that this software is not designed or intended for use
 
33
 * in the design, construction, operation or maintenance of any nuclear
 
34
 * facility.
 
35
 */
 
36
 
 
37
#include <stdio.h>
 
38
#include <fcntl.h>
 
39
#include <unistd.h>
 
40
#include <sys/ioctl.h>
 
41
#include <errno.h>
 
42
#include <stdlib.h>
 
43
#include <string.h>
 
44
#include <sys/types.h>
 
45
#include <sys/stat.h>
 
46
 
 
47
#include <ipmitool/ipmi.h>
 
48
#include <ipmitool/ipmi_intf.h>
 
49
#include <ipmitool/helper.h>
 
50
#include <ipmitool/log.h>
 
51
 
 
52
#include <config.h>
 
53
 
 
54
#ifdef HAVE_OPENIPMI_H
 
55
# include <linux/compiler.h>
 
56
# include <linux/ipmi.h>
 
57
#else
 
58
# include "open.h"
 
59
#endif
 
60
 
 
61
extern int verbose;
 
62
 
 
63
#define IPMI_OPENIPMI_DEV       "/dev/ipmi0"
 
64
#define IPMI_OPENIPMI_DEVFS     "/dev/ipmi/0"
 
65
 
 
66
static int
 
67
ipmi_openipmi_open(struct ipmi_intf * intf)
 
68
{
 
69
        int i = 0;
 
70
 
 
71
        intf->fd = open(IPMI_OPENIPMI_DEV, O_RDWR);
 
72
 
 
73
        if (intf->fd < 0) {
 
74
                intf->fd = open(IPMI_OPENIPMI_DEVFS, O_RDWR);
 
75
                lperror(LOG_ERR, "Could not open device at %s or %s",
 
76
                        IPMI_OPENIPMI_DEV, IPMI_OPENIPMI_DEVFS);
 
77
                return -1;
 
78
        }
 
79
 
 
80
        if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i) < 0) {
 
81
                lperror(LOG_ERR, "Could not enable event receiver");
 
82
                return -1;
 
83
        }
 
84
 
 
85
        if (intf->my_addr != 0) {
 
86
                unsigned int a = intf->my_addr;
 
87
                if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a) < 0) {
 
88
                        lperror(LOG_ERR, "Could not set IPMB address");
 
89
                        return -1;
 
90
                }
 
91
                lprintf(LOG_DEBUG, "Set IPMB address to 0x%x",
 
92
                        intf->my_addr);
 
93
        }
 
94
 
 
95
        intf->opened = 1;
 
96
 
 
97
        return intf->fd;
 
98
}
 
99
 
 
100
static void
 
101
ipmi_openipmi_close(struct ipmi_intf * intf)
 
102
{
 
103
        if (intf->fd >= 0) {
 
104
                close(intf->fd);
 
105
                intf->fd = -1;
 
106
        }
 
107
 
 
108
        intf->opened = 0;
 
109
}
 
110
 
 
111
static struct ipmi_rs *
 
112
ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
 
113
{
 
114
        struct ipmi_recv recv;
 
115
        struct ipmi_addr addr;
 
116
        struct ipmi_system_interface_addr bmc_addr = {
 
117
                addr_type:      IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
 
118
                channel:        IPMI_BMC_CHANNEL,
 
119
        };
 
120
        struct ipmi_ipmb_addr ipmb_addr = {
 
121
                addr_type:      IPMI_IPMB_ADDR_TYPE,
 
122
        };
 
123
        struct ipmi_req _req;
 
124
        static struct ipmi_rs rsp;
 
125
        static int curr_seq = 0;
 
126
        fd_set rset;
 
127
 
 
128
        if (intf == NULL || req == NULL)
 
129
                return NULL;
 
130
        if (intf->opened == 0 && intf->open != NULL)
 
131
                if (intf->open(intf) < 0)
 
132
                        return NULL;
 
133
 
 
134
        if (verbose > 2)
 
135
                printbuf(req->msg.data, req->msg.data_len,
 
136
                         "OpenIPMI Request Message");
 
137
 
 
138
        /*
 
139
         * setup and send message
 
140
         */
 
141
 
 
142
        memset(&_req, 0, sizeof(struct ipmi_req));
 
143
 
 
144
        if (intf->target_addr != 0 &&
 
145
            intf->target_addr != intf->my_addr) {
 
146
                /* use IPMB address if needed */
 
147
                ipmb_addr.slave_addr = intf->target_addr;
 
148
                _req.addr = (char *) &ipmb_addr;
 
149
                _req.addr_len = sizeof(ipmb_addr);
 
150
                lprintf(LOG_DEBUG, "Sending request to "
 
151
                        "IPMB target @ 0x%x", intf->target_addr);
 
152
        } else {
 
153
                /* otherwise use system interface */
 
154
                lprintf(LOG_DEBUG+2, "Sending request to "
 
155
                        "System Interface");
 
156
                _req.addr = (char *) &bmc_addr;
 
157
                _req.addr_len = sizeof(bmc_addr);
 
158
        }
 
159
 
 
160
        _req.msgid = curr_seq++;
 
161
        _req.msg.netfn = req->msg.netfn;
 
162
        _req.msg.cmd = req->msg.cmd;
 
163
        _req.msg.data = req->msg.data;
 
164
        _req.msg.data_len = req->msg.data_len;
 
165
 
 
166
        if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
 
167
                lperror(LOG_ERR, "Unable to send command");
 
168
                return NULL;
 
169
        }
 
170
 
 
171
        /*
 
172
         * wait for and retrieve response
 
173
         */
 
174
 
 
175
        FD_ZERO(&rset);
 
176
        FD_SET(intf->fd, &rset);
 
177
 
 
178
        if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
 
179
                lperror(LOG_ERR, "I/O Error");
 
180
                return NULL;
 
181
        }
 
182
        if (FD_ISSET(intf->fd, &rset) == 0) {
 
183
                lprintf(LOG_ERR, "No data available");
 
184
                return NULL;
 
185
        }
 
186
 
 
187
        recv.addr = (char *) &addr;
 
188
        recv.addr_len = sizeof(addr);
 
189
        recv.msg.data = rsp.data;
 
190
        recv.msg.data_len = sizeof(rsp.data);
 
191
 
 
192
        /* get data */
 
193
        if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
 
194
                lperror(LOG_ERR, "Error receiving message");
 
195
                if (errno != EMSGSIZE)
 
196
                        return NULL;
 
197
        }
 
198
 
 
199
        if (verbose > 4) {
 
200
                fprintf(stderr, "Got message:");
 
201
                fprintf(stderr, "  type      = %d\n", recv.recv_type);
 
202
                fprintf(stderr, "  channel   = 0x%x\n", addr.channel);
 
203
                fprintf(stderr, "  msgid     = %ld\n", recv.msgid);
 
204
                fprintf(stderr, "  netfn     = 0x%x\n", recv.msg.netfn);
 
205
                fprintf(stderr, "  cmd       = 0x%x\n", recv.msg.cmd);
 
206
                if (recv.msg.data && recv.msg.data_len) {
 
207
                        fprintf(stderr, "  data_len  = %d\n", recv.msg.data_len);
 
208
                        fprintf(stderr, "  data      = %s\n",
 
209
                                buf2str(recv.msg.data, recv.msg.data_len));
 
210
                }
 
211
        }
 
212
 
 
213
        /* save completion code */
 
214
        rsp.ccode = recv.msg.data[0];
 
215
        rsp.data_len = recv.msg.data_len - 1;
 
216
 
 
217
        /* save response data for caller */
 
218
        if (rsp.ccode == 0 && rsp.data_len > 0) {
 
219
                memmove(rsp.data, rsp.data + 1, rsp.data_len);
 
220
                rsp.data[recv.msg.data_len] = 0;
 
221
        }
 
222
 
 
223
        return &rsp;
 
224
}
 
225
 
 
226
struct ipmi_intf ipmi_open_intf = {
 
227
        name:           "open",
 
228
        desc:           "Linux OpenIPMI Interface",
 
229
        open:           ipmi_openipmi_open,
 
230
        close:          ipmi_openipmi_close,
 
231
        sendrecv:       ipmi_openipmi_send_cmd,
 
232
        my_addr:        IPMI_BMC_SLAVE_ADDR,
 
233
        target_addr:    IPMI_BMC_SLAVE_ADDR,
 
234
};
 
235