genl.c revision 1155370f520cb64657e25153255cf7dc1424317f
1/* 2 * lib/genl/genl.c Generic Netlink 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 */ 11 12/** 13 * @ingroup nlfam 14 * @defgroup genl Generic Netlink 15 * 16 * @par Message Format 17 * @code 18 * <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) ---> 19 * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 20 * | Header | Pad | Payload | Pad | 21 * | struct nlmsghdr | | | | 22 * +----------------------------+- - -+- - - - - - - - - - -+- - -+ 23 * @endcode 24 * @code 25 * <-------- GENL_HDRLEN -------> <--- hdrlen --> 26 * <------- genlmsg_len(ghdr) ------> 27 * +------------------------+- - -+---------------+- - -+------------+ 28 * | Generic Netlink Header | Pad | Family Header | Pad | Attributes | 29 * | struct genlmsghdr | | | | | 30 * +------------------------+- - -+---------------+- - -+------------+ 31 * genlmsg_data(ghdr)--------------^ ^ 32 * genlmsg_attrdata(ghdr, hdrlen)------------------------- 33 * @endcode 34 * 35 * @par Example 36 * @code 37 * #include <netlink/netlink.h> 38 * #include <netlink/genl/genl.h> 39 * #include <netlink/genl/ctrl.h> 40 * 41 * struct nl_sock *sock; 42 * struct nl_msg *msg; 43 * int family; 44 * 45 * // Allocate a new netlink socket 46 * sock = nl_socket_alloc(); 47 * 48 * // Connect to generic netlink socket on kernel side 49 * genl_connect(sock); 50 * 51 * // Ask kernel to resolve family name to family id 52 * family = genl_ctrl_resolve(sock, "generic_netlink_family_name"); 53 * 54 * // Construct a generic netlink by allocating a new message, fill in 55 * // the header and append a simple integer attribute. 56 * msg = nlmsg_alloc(); 57 * genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, 58 * CMD_FOO_GET, FOO_VERSION); 59 * nla_put_u32(msg, ATTR_FOO, 123); 60 * 61 * // Send message over netlink socket 62 * nl_send_auto_complete(sock, msg); 63 * 64 * // Free message 65 * nlmsg_free(msg); 66 * 67 * // Prepare socket to receive the answer by specifying the callback 68 * // function to be called for valid messages. 69 * nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL); 70 * 71 * // Wait for the answer and receive it 72 * nl_recvmsgs_default(sock); 73 * 74 * static int parse_cb(struct nl_msg *msg, void *arg) 75 * { 76 * struct nlmsghdr *nlh = nlmsg_hdr(msg); 77 * struct nlattr *attrs[ATTR_MAX+1]; 78 * 79 * // Validate message and parse attributes 80 * genlmsg_parse(nlh, 0, attrs, ATTR_MAX, policy); 81 * 82 * if (attrs[ATTR_FOO]) { 83 * uint32_t value = nla_get_u32(attrs[ATTR_FOO]); 84 * ... 85 * } 86 * 87 * return 0; 88 * } 89 * @endcode 90 * @{ 91 */ 92 93#include <netlink-generic.h> 94#include <netlink/netlink.h> 95#include <netlink/genl/genl.h> 96#include <netlink/utils.h> 97 98/** 99 * @name Socket Creating 100 * @{ 101 */ 102 103int genl_connect(struct nl_sock *sk) 104{ 105 return nl_connect(sk, NETLINK_GENERIC); 106} 107 108/** @} */ 109 110/** 111 * @name Sending 112 * @{ 113 */ 114 115/** 116 * Send trivial generic netlink message 117 * @arg sk Netlink socket. 118 * @arg family Generic netlink family 119 * @arg cmd Command 120 * @arg version Version 121 * @arg flags Additional netlink message flags. 122 * 123 * Fills out a routing netlink request message and sends it out 124 * using nl_send_simple(). 125 * 126 * @return 0 on success or a negative error code. 127 */ 128int genl_send_simple(struct nl_sock *sk, int family, int cmd, 129 int version, int flags) 130{ 131 struct genlmsghdr hdr = { 132 .cmd = cmd, 133 .version = version, 134 }; 135 136 return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr)); 137} 138 139/** @} */ 140 141 142/** 143 * @name Message Parsing 144 * @{ 145 */ 146 147int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) 148{ 149 struct genlmsghdr *ghdr; 150 151 if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) 152 return 0; 153 154 ghdr = nlmsg_data(nlh); 155 if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) 156 return 0; 157 158 return 1; 159} 160 161int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, 162 struct nla_policy *policy) 163{ 164 struct genlmsghdr *ghdr; 165 166 if (!genlmsg_valid_hdr(nlh, hdrlen)) 167 return -NLE_MSG_TOOSHORT; 168 169 ghdr = nlmsg_data(nlh); 170 return nla_validate(genlmsg_attrdata(ghdr, hdrlen), 171 genlmsg_attrlen(ghdr, hdrlen), maxtype, policy); 172} 173 174int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], 175 int maxtype, struct nla_policy *policy) 176{ 177 struct genlmsghdr *ghdr; 178 179 if (!genlmsg_valid_hdr(nlh, hdrlen)) 180 return -NLE_MSG_TOOSHORT; 181 182 ghdr = nlmsg_data(nlh); 183 return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen), 184 genlmsg_attrlen(ghdr, hdrlen), policy); 185} 186 187/** 188 * Get head of message payload 189 * @arg gnlh genetlink messsage header 190 */ 191void *genlmsg_data(const struct genlmsghdr *gnlh) 192{ 193 return ((unsigned char *) gnlh + GENL_HDRLEN); 194} 195 196/** 197 * Get lenght of message payload 198 * @arg gnlh genetlink message header 199 */ 200int genlmsg_len(const struct genlmsghdr *gnlh) 201{ 202 struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh - 203 NLMSG_HDRLEN); 204 return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); 205} 206 207/** 208 * Get head of attribute data 209 * @arg gnlh generic netlink message header 210 * @arg hdrlen length of family specific header 211 */ 212struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) 213{ 214 return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen); 215} 216 217/** 218 * Get length of attribute data 219 * @arg gnlh generic netlink message header 220 * @arg hdrlen length of family specific header 221 */ 222int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) 223{ 224 return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); 225} 226 227/** @} */ 228 229/** 230 * @name Message Building 231 * @{ 232 */ 233 234/** 235 * Add generic netlink header to netlink message 236 * @arg msg netlink message 237 * @arg pid netlink process id or NL_AUTO_PID 238 * @arg seq sequence number of message or NL_AUTO_SEQ 239 * @arg family generic netlink family 240 * @arg hdrlen length of user specific header 241 * @arg flags message flags 242 * @arg cmd generic netlink command 243 * @arg version protocol version 244 * 245 * Returns pointer to user specific header. 246 */ 247void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family, 248 int hdrlen, int flags, uint8_t cmd, uint8_t version) 249{ 250 struct nlmsghdr *nlh; 251 struct genlmsghdr hdr = { 252 .cmd = cmd, 253 .version = version, 254 }; 255 256 nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags); 257 if (nlh == NULL) 258 return NULL; 259 260 memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); 261 NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n", 262 msg, cmd, version); 263 264 return nlmsg_data(nlh) + GENL_HDRLEN; 265} 266 267/** @} */ 268 269/** @} */ 270