libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/genl/genl.c
00001 /*
00002  * lib/genl/genl.c              Generic Netlink
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @defgroup genl Generic Netlink
00014  *
00015  * @par Message Format
00016  * @code
00017  *  <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
00018  * +----------------------------+- - -+- - - - - - - - - - -+- - -+
00019  * |           Header           | Pad |       Payload       | Pad |
00020  * |      struct nlmsghdr       |     |                     |     |
00021  * +----------------------------+- - -+- - - - - - - - - - -+- - -+
00022  * @endcode
00023  * @code
00024  *  <-------- GENL_HDRLEN -------> <--- hdrlen -->
00025  *                                 <------- genlmsg_len(ghdr) ------>
00026  * +------------------------+- - -+---------------+- - -+------------+
00027  * | Generic Netlink Header | Pad | Family Header | Pad | Attributes |
00028  * |    struct genlmsghdr   |     |               |     |            |
00029  * +------------------------+- - -+---------------+- - -+------------+
00030  * genlmsg_data(ghdr)--------------^                     ^
00031  * genlmsg_attrdata(ghdr, hdrlen)-------------------------
00032  * @endcode
00033  *
00034  * @par Example
00035  * @code
00036  * #include <netlink/netlink.h>
00037  * #include <netlink/genl/genl.h>
00038  * #include <netlink/genl/ctrl.h>
00039  *
00040  * struct nl_sock *sock;
00041  * struct nl_msg *msg;
00042  * int family;
00043  *
00044  * // Allocate a new netlink socket
00045  * sock = nl_socket_alloc();
00046  *
00047  * // Connect to generic netlink socket on kernel side
00048  * genl_connect(sock);
00049  *
00050  * // Ask kernel to resolve family name to family id
00051  * family = genl_ctrl_resolve(sock, "generic_netlink_family_name");
00052  *
00053  * // Construct a generic netlink by allocating a new message, fill in
00054  * // the header and append a simple integer attribute.
00055  * msg = nlmsg_alloc();
00056  * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO,
00057  *             CMD_FOO_GET, FOO_VERSION);
00058  * nla_put_u32(msg, ATTR_FOO, 123);
00059  *
00060  * // Send message over netlink socket
00061  * nl_send_auto_complete(sock, msg);
00062  *
00063  * // Free message
00064  * nlmsg_free(msg);
00065  *
00066  * // Prepare socket to receive the answer by specifying the callback
00067  * // function to be called for valid messages.
00068  * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
00069  *
00070  * // Wait for the answer and receive it
00071  * nl_recvmsgs_default(sock);
00072  *
00073  * static int parse_cb(struct nl_msg *msg, void *arg)
00074  * {
00075  *     struct nlmsghdr *nlh = nlmsg_hdr(msg);
00076  *     struct nlattr *attrs[ATTR_MAX+1];
00077  *
00078  *     // Validate message and parse attributes
00079  *     genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy);
00080  *
00081  *     if (attrs[ATTR_FOO]) {
00082  *         uint32_t value = nla_get_u32(attrs[ATTR_FOO]);
00083  *         ...
00084  *     }
00085  *
00086  *     return 0;
00087  * }
00088  * @endcode
00089  * @{
00090  */
00091 
00092 #include <netlink-generic.h>
00093 #include <netlink/netlink.h>
00094 #include <netlink/genl/genl.h>
00095 #include <netlink/utils.h>
00096 
00097 /**
00098  * @name Socket Creating
00099  * @{
00100  */
00101 
00102 int genl_connect(struct nl_sock *sk)
00103 {
00104         return nl_connect(sk, NETLINK_GENERIC);
00105 }
00106 
00107 /** @} */
00108 
00109 /**
00110  * @name Sending
00111  * @{
00112  */
00113 
00114 /**
00115  * Send trivial generic netlink message
00116  * @arg sk              Netlink socket.
00117  * @arg family          Generic netlink family
00118  * @arg cmd             Command
00119  * @arg version         Version
00120  * @arg flags           Additional netlink message flags.
00121  *
00122  * Fills out a routing netlink request message and sends it out
00123  * using nl_send_simple().
00124  *
00125  * @return 0 on success or a negative error code.
00126  */
00127 int genl_send_simple(struct nl_sock *sk, int family, int cmd,
00128                      int version, int flags)
00129 {
00130         struct genlmsghdr hdr = {
00131                 .cmd = cmd,
00132                 .version = version,
00133         };
00134 
00135         return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr));
00136 }
00137 
00138 /** @} */
00139 
00140 
00141 /**
00142  * @name Message Parsing
00143  * @{
00144  */
00145 
00146 int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
00147 {
00148         struct genlmsghdr *ghdr;
00149 
00150         if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
00151                 return 0;
00152 
00153         ghdr = nlmsg_data(nlh);
00154         if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
00155                 return 0;
00156 
00157         return 1;
00158 }
00159 
00160 int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
00161                    struct nla_policy *policy)
00162 {
00163         struct genlmsghdr *ghdr;
00164 
00165         if (!genlmsg_valid_hdr(nlh, hdrlen))
00166                 return -NLE_MSG_TOOSHORT;
00167 
00168         ghdr = nlmsg_data(nlh);
00169         return nla_validate(genlmsg_attrdata(ghdr, hdrlen),
00170                             genlmsg_attrlen(ghdr, hdrlen), maxtype, policy);
00171 }
00172 
00173 int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
00174                   int maxtype, struct nla_policy *policy)
00175 {
00176         struct genlmsghdr *ghdr;
00177 
00178         if (!genlmsg_valid_hdr(nlh, hdrlen))
00179                 return -NLE_MSG_TOOSHORT;
00180 
00181         ghdr = nlmsg_data(nlh);
00182         return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen),
00183                          genlmsg_attrlen(ghdr, hdrlen), policy);
00184 }
00185 
00186 /**
00187  * Get head of message payload
00188  * @arg gnlh    genetlink messsage header
00189  */
00190 void *genlmsg_data(const struct genlmsghdr *gnlh)
00191 {
00192         return ((unsigned char *) gnlh + GENL_HDRLEN);
00193 }
00194 
00195 /**
00196  * Get lenght of message payload
00197  * @arg gnlh    genetlink message header
00198  */
00199 int genlmsg_len(const struct genlmsghdr *gnlh)
00200 {
00201         struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
00202                                                         NLMSG_HDRLEN);
00203         return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
00204 }
00205 
00206 /**
00207  * Get head of attribute data
00208  * @arg gnlh    generic netlink message header
00209  * @arg hdrlen  length of family specific header
00210  */
00211 struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
00212 {
00213         return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen);
00214 }
00215 
00216 /**
00217  * Get length of attribute data
00218  * @arg gnlh    generic netlink message header
00219  * @arg hdrlen  length of family specific header
00220  */
00221 int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
00222 {
00223         return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
00224 }
00225 
00226 /** @} */
00227 
00228 /**
00229  * @name Message Building
00230  * @{
00231  */
00232 
00233 /**
00234  * Add generic netlink header to netlink message
00235  * @arg msg             netlink message
00236  * @arg pid             netlink process id or NL_AUTO_PID
00237  * @arg seq             sequence number of message or NL_AUTO_SEQ
00238  * @arg family          generic netlink family
00239  * @arg hdrlen          length of user specific header
00240  * @arg flags           message flags
00241  * @arg cmd             generic netlink command
00242  * @arg version         protocol version
00243  *
00244  * Returns pointer to user specific header.
00245  */
00246 void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
00247                   int hdrlen, int flags, uint8_t cmd, uint8_t version)
00248 {
00249         struct nlmsghdr *nlh;
00250         struct genlmsghdr hdr = {
00251                 .cmd = cmd,
00252                 .version = version,
00253         };
00254 
00255         nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags);
00256         if (nlh == NULL)
00257                 return NULL;
00258 
00259         memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr));
00260         NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n",
00261                msg, cmd, version);
00262 
00263         return nlmsg_data(nlh) + GENL_HDRLEN;
00264 }
00265 
00266 /** @} */
00267 
00268 /** @} */