Main Page | Class List | Directories | File List | Class Members | File Members

ipmi_conn.h

Go to the documentation of this file.
00001 /*
00002  * ipmi_conn.h
00003  *
00004  * MontaVista IPMI interface, definition for a low-level connection (like a
00005  * LAN interface, or system management interface, etc.).
00006  *
00007  * Author: MontaVista Software, Inc.
00008  *         Corey Minyard <minyard@mvista.com>
00009  *         source@mvista.com
00010  *
00011  * Copyright 2002,2003 MontaVista Software Inc.
00012  *
00013  *  This program is free software; you can redistribute it and/or
00014  *  modify it under the terms of the GNU Lesser General Public License
00015  *  as published by the Free Software Foundation; either version 2 of
00016  *  the License, or (at your option) any later version.
00017  *
00018  *
00019  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00020  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00021  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00022  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00027  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00028  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *  You should have received a copy of the GNU Lesser General Public
00031  *  License along with this program; if not, write to the Free
00032  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00033  */
00034 
00035 #ifndef _IPMI_CONN_H
00036 #define _IPMI_CONN_H
00037 
00038 #include <OpenIPMI/ipmi_types.h>
00039 #include <OpenIPMI/ipmi_addr.h>
00040 #include <OpenIPMI/ipmiif.h>
00041 #include <OpenIPMI/os_handler.h>
00042 
00043 #ifdef __cplusplus
00044 extern "C" {
00045 #endif
00046 
00047 /* Called when an IPMI response to a command comes in from the BMC. */
00048 typedef int (*ipmi_ll_rsp_handler_t)(ipmi_con_t   *ipmi,
00049                                      ipmi_msgi_t  *rspi);
00050 
00051 /* Called when an IPMI event comes in from the BMC.  Note that the
00052    event may be NULL, meaning that an event came in but did not have
00053    enough information to build a full event message.  So this is just
00054    an indication that there is a new event in the event log.  Note that
00055    if an event is delivered here, it's mcid might be invalid, so that
00056    may need to be established here. */
00057 typedef void (*ipmi_ll_evt_handler_t)(ipmi_con_t         *ipmi,
00058                                       const ipmi_addr_t  *addr,
00059                                       unsigned int       addr_len,
00060                                       ipmi_event_t       *event,
00061                                       void               *cb_data);
00062 
00063 /* Called when an incoming command is received by the IPMI code. */
00064 typedef void (*ipmi_ll_cmd_handler_t)(ipmi_con_t        *ipmi,
00065                                       const ipmi_addr_t *addr,
00066                                       unsigned int      addr_len,
00067                                       const ipmi_msg_t  *cmd,
00068                                       long              sequence,
00069                                       void              *cmd_data,
00070                                       void              *data2,
00071                                       void              *data3);
00072 
00073 /* Called when a low-level connection has failed or come up.  If err
00074    is zero, the connection has come up after being failed.  if err is
00075    non-zero, it's an error number to report why the failure occurred.
00076    Since some connections support multiple ports into the system, this
00077    is used to report partial failures as well as full failures.
00078    port_num will be the port number that has failed (if err is
00079    nonzero) or has just come up (if err is zero).  What port_num that
00080    means depends on the connection type.  any_port_up will be true if
00081    the system still has connectivity through other ports. */
00082 typedef void (*ipmi_ll_con_changed_cb)(ipmi_con_t   *ipmi,
00083                                        int          err,
00084                                        unsigned int port_num,
00085                                        int          any_port_up,
00086                                        void         *cb_data);
00087 
00088 /* Used when fetching the IPMB address of the connection. The active
00089    parm tells if the interface is active or not, this callback is also
00090    used to inform the upper layer when the connection becomes active
00091    or inactive.  Note that there can be one IPMB address per channel,
00092    so this allows an array of IPMBs to be passed, one per channel.
00093    Set the IPMB to 0 if unknown. */
00094 typedef void (*ipmi_ll_ipmb_addr_cb)(ipmi_con_t    *ipmi,
00095                                      int           err,
00096                                      const unsigned char ipmb_addr[],
00097                                      unsigned int  num_ipmb_addr,
00098                                      int           active,
00099                                      unsigned int  hacks,
00100                                      void          *cb_data);
00101 
00102 /* Used to handle knowing when the connection shutdown is complete. */
00103 typedef void (*ipmi_ll_con_closed_cb)(ipmi_con_t *ipmi, void *cb_data);
00104 
00105 /* Set this bit in the hacks if, even though the connection is to a
00106    device not at 0x20, the first part of a LAN command should always
00107    use 0x20. */
00108 #define IPMI_CONN_HACK_20_AS_MAIN_ADDR          0x00000001
00109 
00110 /* Some systems (incorrectly, according to the spec) use only the
00111    bottom 4 bits or ROLE(m) for authentication in the RAKP3 message.
00112    The spec says to use all 8 bits, but enabling this hack makes
00113    OpenIPMI only use the bottom 4 bits. */
00114 #define IPMI_CONN_HACK_RAKP3_WRONG_ROLEM        0x00000002
00115 
00116 /* The spec is vague (perhaps wrong), but the default for RMCP+ seems
00117    to be to use K(1) as the integrity key.  That is thus the default
00118    of OpenIPMI, but this hack lets you use SIK as it says in one part
00119    of the spec. */
00120 #define IPMI_CONN_HACK_RMCPP_INTEG_SIK          0x00000004
00121 
00122 /*
00123  * Used to pass special options for sending messages.
00124  */
00125 typedef struct ipmi_con_option_s
00126 {
00127     int option;
00128     union {
00129         long ival;
00130         void *pval;
00131     };
00132 } ipmi_con_option_t;
00133 
00134 /* Used to mark the end of the option list.  Must always be the last
00135    option. */
00136 #define IPMI_CON_OPTION_LIST_END                0
00137 
00138 /* Enable/disable authentication on the message (set by ival).
00139    Default is enabled. */
00140 #define IPMI_CON_MSG_OPTION_AUTH                1
00141 
00142 /* Enable/disable confidentiality (encryption) on the message (set by
00143    ival).  Default is enabled. */
00144 #define IPMI_CON_MSG_OPTION_CONF                2
00145 
00146 
00147 /* The data structure representing a connection.  The low-level handler
00148    fills this out then calls ipmi_init_con() with the connection. */
00149 struct ipmi_con_s
00150 {
00151     /* If this is zero, the domain handling code will not attempt to
00152        scan the system interface address of the connection.  If 1, it
00153        will.  Generally, if the system interface will respond on a
00154        IPMB address, you should set this to zero.  If it does not
00155        respond on an IPMB, you should set this to one if it is a
00156        management controller. */
00157     int scan_sysaddr;
00158 
00159     /* The low-level handler should provide one of these for doing os-type
00160        things (locks, random numbers, etc.) */
00161     os_handler_t *os_hnd;
00162 
00163     /* This data can be fetched by the user and used for anything they
00164        like. */
00165     void *user_data;
00166 
00167     /* Connection-specific data for the underlying connection. */
00168     void *con_data;
00169 
00170     /* If OEM code want to attach some data, it can to it here. */
00171     void *oem_data;
00172     void (*oem_data_cleanup)(ipmi_con_t *ipmi);
00173 
00174     /* This allows the connection to tell the upper layer that broadcasting
00175        will not work on this interface. */
00176     int broadcast_broken;
00177 
00178     /* Calls for the interface.  These should all return standard
00179        "errno" errors if they fail. */
00180 
00181     /* Start processing on a connection.  Note that the handler *must*
00182        be called with the global read lock not held, because the
00183        handler must write lock the global lock in order to add the MC
00184        to the global list.  This will report success/failure with the
00185        con_changed_handler, so set that up first. */
00186     int (*start_con)(ipmi_con_t *ipmi);
00187 
00188     /* Add a callback to call when the connection goes down or up. */
00189     int (*add_con_change_handler)(ipmi_con_t             *ipmi,
00190                                   ipmi_ll_con_changed_cb handler,
00191                                   void                   *cb_data);
00192     int (*remove_con_change_handler)(ipmi_con_t             *ipmi,
00193                                      ipmi_ll_con_changed_cb handler,
00194                                      void                   *cb_data);
00195 
00196     /* If OEM code discovers that an IPMB address has changed, it can
00197        use this to change it.  The hacks are the same as the ones in
00198        the IPMB address handler. */
00199     void (*set_ipmb_addr)(ipmi_con_t    *ipmi,
00200                           const unsigned char ipmb_addr[],
00201                           unsigned int  num_ipmb_addr,
00202                           int           active,
00203                           unsigned int  hacks);
00204 
00205     /* Add a handler that will be called when the IPMB address changes. */
00206     int (*add_ipmb_addr_handler)(ipmi_con_t           *ipmi,
00207                                  ipmi_ll_ipmb_addr_cb handler,
00208                                  void                 *cb_data);
00209     int (*remove_ipmb_addr_handler)(ipmi_con_t           *ipmi,
00210                                     ipmi_ll_ipmb_addr_cb handler,
00211                                     void                 *cb_data);
00212 
00213     /* This call gets the IPMB address of the connection.  It may be
00214        NULL if the connection does not support this.  This call may be
00215        set or overridden by the OEM code.  This is primarily for use
00216        by the connection code itself, the OEM code for the BMC
00217        connected to should set this.  If it is not set, the IPMB
00218        address is assumed to be 0x20.  This *should* send a message to
00219        the device, because connection code will assume that and use it
00220        to check for device function.  This should also check if the
00221        device is active.  If this is non-null, it will be called
00222        periodically. */
00223     int (*get_ipmb_addr)(ipmi_con_t           *ipmi,
00224                          ipmi_ll_ipmb_addr_cb handler,
00225                          void                 *cb_data);
00226 
00227     /* Change the state of the connection to be active or inactive.
00228        This may be NULL if the connection does not support this.  The
00229        interface code may set this, the OEM code should override this
00230        if necessary. */
00231     int (*set_active_state)(ipmi_con_t           *ipmi,
00232                             int                  is_active,
00233                             ipmi_ll_ipmb_addr_cb handler,
00234                             void                 *cb_data);
00235 
00236     /* Send an IPMI command (in "msg" on the "ipmi" connection to the
00237        given "addr".  When the response comes in or the message times
00238        out, rsp_handler will be called with the following four data
00239        items.  Note that the lower layer MUST guarantee that the
00240        reponse handler is called, even if it fails or the message is
00241        dropped. */
00242     int (*send_command)(ipmi_con_t            *ipmi,
00243                         const ipmi_addr_t     *addr,
00244                         unsigned int          addr_len,
00245                         const ipmi_msg_t      *msg,
00246                         ipmi_ll_rsp_handler_t rsp_handler,
00247                         ipmi_msgi_t           *rspi);
00248 
00249     /* Register to receive IPMI events from the interface. */
00250     int (*add_event_handler)(ipmi_con_t                 *ipmi,
00251                              ipmi_ll_evt_handler_t      handler,
00252                              void                       *cb_data);
00253 
00254     /* Remove an event handler. */
00255     int (*remove_event_handler)(ipmi_con_t                 *ipmi,
00256                                 ipmi_ll_evt_handler_t      handler,
00257                                 void                       *cb_data);
00258 
00259     /* Send a response message.  This is not supported on all
00260        interfaces, primarily only on system management interfaces.  If
00261        not supported, this should return ENOSYS. */
00262     int (*send_response)(ipmi_con_t        *ipmi,
00263                          const ipmi_addr_t *addr,
00264                          unsigned int      addr_len,
00265                          const ipmi_msg_t  *msg,
00266                          long              sequence);
00267 
00268     /* Register to receive incoming commands.  This is not supported
00269        on all interfaces, primarily only on system management
00270        interfaces.  If not supported, this should return ENOSYS. */
00271     int (*register_for_command)(ipmi_con_t            *ipmi,
00272                                 unsigned char         netfn,
00273                                 unsigned char         cmd,
00274                                 ipmi_ll_cmd_handler_t handler,
00275                                 void                  *cmd_data,
00276                                 void                  *data2,
00277                                 void                  *data3);
00278 
00279     /* Deregister a command registration.  This is not supported on
00280        all interfaces, primarily only on system management interfaces.
00281        If not supported, this should return ENOSYS. */
00282     int (*deregister_for_command)(ipmi_con_t    *ipmi,
00283                                   unsigned char netfn,
00284                                   unsigned char cmd);
00285 
00286     /* Close an IPMI connection. */
00287     int (*close_connection)(ipmi_con_t *ipmi);
00288 
00289     /* This is set by OEM code to handle certain conditions when a
00290        send message fails.  It is currently only used by the IPMI LAN
00291        code, if a send messages response is an error, this will be
00292        called first.  If this function returns true, then the IPMI LAN
00293        code will not do anything with the message. */
00294     int (*handle_send_rsp_err)(ipmi_con_t *con, ipmi_msg_t *msg);
00295 
00296     /* Name the connection code can use for logging and instance names
00297        for statistics.  Must be dynamically allocated with
00298        ipmi_mem_alloc().  The connection code will free this.  May be
00299        NULL. */
00300     char *name;
00301 
00302     /* The connection code may put a string here to identify
00303        itself. */
00304     char *con_type;
00305 
00306     /* The privilege level of the connection */
00307     unsigned int priv_level;
00308 
00309     /* Close an IPMI connection and report that it is closed. */
00310     int (*close_connection_done)(ipmi_con_t            *ipmi,
00311                                  ipmi_ll_con_closed_cb handler,
00312                                  void                  *cb_data);
00313 
00314     /* Hacks reported by OEM code.  This should be set by the lower
00315        layer or by the user interface code. */
00316     unsigned int  hacks;
00317 
00318     /* The IPMB address as reported by the lower layer. */
00319     unsigned char ipmb_addr[MAX_IPMI_USED_CHANNELS];
00320 
00321     /* Handle an async event for the connection reported by something
00322        else. */
00323     void (*handle_async_event)(ipmi_con_t        *con,
00324                                const ipmi_addr_t *addr,
00325                                unsigned int      addr_len,
00326                                const ipmi_msg_t  *msg);
00327 
00328     /* Used by the connection attribute code.  Don't do anything with
00329        this yourself!.  The thing that creates this connection should
00330        call ipmi_con_attr_init() when the connection is created and
00331        ipmi_con_attr_cleanup() when the connection is destroyed. */
00332     void *attr;
00333 
00334     /* Statistics interfaces.  These may be NULL if the user doesn't
00335        want statistics.  They pass in the user data field. */
00336     int (*register_stat)(void *user_data, char *name,
00337                          char *instance,  void **stat);
00338     void (*add_stat)(void *user_data, void *stat, int value);
00339     void (*finished_with_stat)(void *user_data, void *stat);
00340 
00341     /* Return the arguments or the connection. */
00342     ipmi_args_t *(*get_startup_args)(ipmi_con_t *con);
00343 
00344     /* Increment the usecount of the connection; for each use, the
00345        connection must be closed.  This may be NULL if the connection
00346        type does not support being reused. */
00347     void (*use_connection)(ipmi_con_t *con);
00348 
00349     /* Like send_command, but with options.  options may be NULL if
00350        none.  If options are passed in, they must be terminated with
00351        the proper option.  This field may be NULL if the connection
00352        does not support options. */
00353     int (*send_command_option)(ipmi_con_t              *ipmi,
00354                                const ipmi_addr_t       *addr,
00355                                unsigned int            addr_len,
00356                                const ipmi_msg_t        *msg,
00357                                const ipmi_con_option_t *options,
00358                                ipmi_ll_rsp_handler_t   rsp_handler,
00359                                ipmi_msgi_t             *rspi);
00360 
00361     /* Returns the number of ports on the connection (one more than
00362        the max_port that can be reported by ipmi_ll_con_changed_cb().
00363        If NULL, assume 1. */
00364     unsigned int (*get_num_ports)(ipmi_con_t *ipmi);
00365 };
00366 
00367 #define IPMI_CONN_NAME(c) (c->name ? c->name : "")
00368 
00369 /* Initialization code for the initialization the connection code. */
00370 int _ipmi_conn_init(os_handler_t *os_hnd);
00371 void _ipmi_conn_shutdown(void);
00372 
00373 
00374 /* Address types for external addresses. */
00375 #define IPMI_EXTERN_ADDR_IP     1
00376 
00377 /* Handle a trap from an external SNMP source.  It returns 1 if the
00378    event was handled an zero if it was not. */
00379 int ipmi_handle_snmp_trap_data(const void          *src_addr,
00380                                unsigned int        src_addr_len,
00381                                int                 src_addr_type,
00382                                long                specific,
00383                                const unsigned char *data,
00384                                unsigned int        data_len);
00385 
00386 /* These calls deal with OEM-type handlers for connections.  Certain
00387    connections can be detected with special means (beyond just the
00388    manufacturer and product id) and this allows handlers for these
00389    types of connections to be registered.  At the very initial
00390    connection of every connection, the handler will be called and it
00391    must detect whether this is the specific type of connection or not,
00392    do any setup for that connection type, and then call the done
00393    routine passed in.  Note that the done routine may be called later,
00394    (allowing this handler to send messages and the like) but it *must*
00395    be called.  Note that this has no cancellation handler.  It relies
00396    on the lower levels returning responses for all the commands with
00397    NULL connections. */
00398 typedef void (*ipmi_conn_oem_check_done)(ipmi_con_t *conn,
00399                                          void       *cb_data);
00400 typedef int (*ipmi_conn_oem_check)(ipmi_con_t               *conn,
00401                                    void                     *check_cb_data,
00402                                    ipmi_conn_oem_check_done done,
00403                                    void                     *done_cb_data);
00404 int ipmi_register_conn_oem_check(ipmi_conn_oem_check check,
00405                                  void                *cb_data);
00406 int ipmi_deregister_conn_oem_check(ipmi_conn_oem_check check,
00407                                    void                *cb_data);
00408 /* Should be called by the connection code for any new connection. */
00409 int ipmi_conn_check_oem_handlers(ipmi_con_t               *conn,
00410                                  ipmi_conn_oem_check_done done,
00411                                  void                     *cb_data);
00412 
00413 /* Generic message handling */
00414 void ipmi_handle_rsp_item(ipmi_con_t            *ipmi,
00415                           ipmi_msgi_t           *rspi,
00416                           ipmi_ll_rsp_handler_t rsp_handler);
00417 
00418 void ipmi_handle_rsp_item_copymsg(ipmi_con_t            *ipmi,
00419                                   ipmi_msgi_t           *rspi,
00420                                   const ipmi_msg_t      *msg,
00421                                   ipmi_ll_rsp_handler_t rsp_handler);
00422 
00423 void ipmi_handle_rsp_item_copyall(ipmi_con_t            *ipmi,
00424                                   ipmi_msgi_t           *rspi,
00425                                   const ipmi_addr_t     *addr,
00426                                   unsigned int          addr_len,
00427                                   const ipmi_msg_t      *msg,
00428                                   ipmi_ll_rsp_handler_t rsp_handler);
00429 
00430 /* You should use these for allocating and freeing mesage items.  Note
00431    that if you set item->msg.data to a non-NULL value that is not
00432    item->data, the system will free it with ipmi_free_msg_item_data().
00433    So you should allocate it with ipmi_alloc_msg_item_data9). */
00434 ipmi_msgi_t *ipmi_alloc_msg_item(void);
00435 void ipmi_free_msg_item(ipmi_msgi_t *item);
00436 void *ipmi_alloc_msg_item_data(unsigned int size);
00437 void ipmi_free_msg_item_data(void *data);
00438 /* Move the data from the old message item to the new one, NULL-ing
00439    out the old item's data.  This will free the new_item's original
00440    data if necessary.  This will *not* copy the data items, just the
00441    address and message. */
00442 void ipmi_move_msg_item(ipmi_msgi_t *new_item, ipmi_msgi_t *old_item);
00443 
00444 /*
00445  * Connection attributes.  These are named items that code may create
00446  * to attach a void data item to a connection by name.  It can then
00447  * look up the data item by name.  Note that you can call
00448  * ipmi_con_register_attribute multiple times.  The first time will
00449  * create the item, the rest of the times will return the existing
00450  * item.
00451  *
00452  * When the connection is destroyed, the destroy function will be
00453  * called on the attribute so the memory (or anything else) can be
00454  * cleaned up.
00455  *
00456  * This is especially for use by RMCP+ payloads so they may attach
00457  * data to the connection they are associated with.
00458  */
00459 typedef struct ipmi_con_attr_s ipmi_con_attr_t;
00460 
00461 /* Attr init function.  Return the data item in the data field.  Returns
00462    an error value.  Will only be called once for the attribute.  */
00463 typedef int (*ipmi_con_attr_init_cb)(ipmi_con_t *con, void *cb_data,
00464                                      void **data);
00465 
00466 /* Called when the attribute is destroyed.  Note that this may happen
00467    after connection destruction, so the connection may not exist any
00468    more. */
00469 typedef void (*ipmi_con_attr_kill_cb)(void *cb_data, void *data);
00470 
00471 int ipmi_con_register_attribute(ipmi_con_t            *con,
00472                                 char                  *name,
00473                                 ipmi_con_attr_init_cb init,
00474                                 ipmi_con_attr_kill_cb destroy,
00475                                 void                  *cb_data,
00476                                 ipmi_con_attr_t       **attr);
00477 int ipmi_con_find_attribute(ipmi_con_t      *con,
00478                             char             *name,
00479                             ipmi_con_attr_t **attr);
00480 void *ipmi_con_attr_get_data(ipmi_con_attr_t *attr);
00481 /* You must call the put operation of every attribute returned by
00482    register or find. */
00483 void ipmi_con_attr_put(ipmi_con_attr_t *attr);
00484 int ipmi_con_attr_init(ipmi_con_t *con);
00485 void ipmi_con_attr_cleanup(ipmi_con_t *con);
00486 
00487 #ifdef __cplusplus
00488 }
00489 #endif
00490 
00491 #endif /* _IPMI_CONN_H */

© sourcejam.com 2005-2008