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-2012 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 /** 13 * @defgroup genl Generic Netlink Library (libnl-genl) 14 * 15 * @{ 16 */ 17 18 #include <netlink-private/genl.h> 19 #include <netlink/netlink.h> 20 #include <netlink/genl/genl.h> 21 #include <netlink/utils.h> 22 23 /** 24 * @name Generic Netlink Socket 25 * @{ 26 */ 27 28 /** 29 * Connect a Generic Netlink socket 30 * @arg sk Unconnected Netlink socket 31 * 32 * This function expects a struct nl_socket object previously allocated via 33 * nl_socket_alloc(). It calls nl_connect() to create the local socket file 34 * descriptor and binds the socket to the \c NETLINK_GENERIC Netlink protocol. 35 * 36 * Using this function is equivalent to: 37 * @code 38 * nl_connect(sk, NETLINK_GENERIC); 39 * @endcode 40 * 41 * @see nl_connect() 42 * 43 * @return 0 on success or a negative error code. 44 */ 45 int genl_connect(struct nl_sock *sk) 46 { 47 return nl_connect(sk, NETLINK_GENERIC); 48 } 49 50 /** @} */ 51 52 /** 53 * @name Sending Data 54 * @{ 55 */ 56 57 /** 58 * Send a Generic Netlink message consisting only of a header 59 * @arg sk Generic Netlink socket 60 * @arg family Numeric family identifier 61 * @arg cmd Numeric command identifier 62 * @arg version Interface version 63 * @arg flags Additional Netlink message flags (optional) 64 * 65 * This function is a shortcut for sending a Generic Netlink message without 66 * any message payload. The message will only consist of the Netlink and 67 * Generic Netlink headers. The header is constructed based on the specified 68 * parameters and passed on to nl_send_simple() to send it on the specified 69 * socket. 70 * 71 * @par Example: 72 * @code 73 * #include <netlink/genl/genl.h> 74 * #include <linux/genetlink.h> 75 * 76 * err = genl_send_simple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION, 77 * NLM_F_DUMP); 78 * @endcode 79 * 80 * @see nl_send_simple() 81 * 82 * @return 0 on success or a negative error code. 83 */ 84 int genl_send_simple(struct nl_sock *sk, int family, int cmd, 85 int version, int flags) 86 { 87 struct genlmsghdr hdr = { 88 .cmd = cmd, 89 .version = version, 90 }; 91 92 return nl_send_simple(sk, family, flags, &hdr, sizeof(hdr)); 93 } 94 95 /** @} */ 96 97 /** 98 * @name Message Parsing 99 * @{ 100 */ 101 102 /** 103 * Validate Generic Netlink message headers 104 * @arg nlh Pointer to Netlink message header 105 * @arg hdrlen Length of user header 106 * 107 * Verifies the integrity of the Netlink and Generic Netlink headers by 108 * enforcing the following requirements: 109 * - Valid Netlink message header (nlmsg_valid_hdr()) 110 * - Presence of a complete Generic Netlink header 111 * - At least \c hdrlen bytes of payload included after the generic 112 * netlink header. 113 * 114 * @return A positive integer (true) if the headers are valid or 115 * 0 (false) if not. 116 */ 117 int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) 118 { 119 struct genlmsghdr *ghdr; 120 121 if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) 122 return 0; 123 124 ghdr = nlmsg_data(nlh); 125 if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) 126 return 0; 127 128 return 1; 129 } 130 131 /** 132 * Validate Generic Netlink message including attributes 133 * @arg nlh Pointer to Netlink message header 134 * @arg hdrlen Length of user header 135 * @arg maxtype Maximum attribtue id expected 136 * @arg policy Attribute validation policy 137 * 138 * Verifies the validity of the Netlink and Generic Netlink headers using 139 * genlmsg_valid_hdr() and calls nla_validate() on the message payload to 140 * verify the integrity of eventual attributes. 141 * 142 * @note You may call genlmsg_parse() directly to perform validation and 143 * parsing in a single step. 144 * 145 * @see genlmsg_valid_hdr() 146 * @see nla_validate() 147 * @see genlmsg_parse() 148 * 149 * @return 0 on success or a negative error code. 150 */ 151 int genlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, 152 struct nla_policy *policy) 153 { 154 struct genlmsghdr *ghdr; 155 156 if (!genlmsg_valid_hdr(nlh, hdrlen)) 157 return -NLE_MSG_TOOSHORT; 158 159 ghdr = nlmsg_data(nlh); 160 return nla_validate(genlmsg_attrdata(ghdr, hdrlen), 161 genlmsg_attrlen(ghdr, hdrlen), maxtype, policy); 162 } 163 164 /** 165 * Parse Generic Netlink message including attributes 166 * @arg nlh Pointer to Netlink message header 167 * @arg hdrlen Length of user header 168 * @arg tb Array to store parsed attributes 169 * @arg maxtype Maximum attribute id expected 170 * @arg policy Attribute validation policy 171 * 172 * Verifies the validity of the Netlink and Generic Netlink headers using 173 * genlmsg_valid_hdr() and calls nla_parse() on the message payload to 174 * parse eventual attributes. 175 * 176 * @par Example: 177 * @code 178 * struct nlattr *attrs[MY_TYPE_MAX+1]; 179 * 180 * if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs, 181 * MY_TYPE_MAX, attr_policy)) < 0) 182 * // ERROR 183 * @endcode 184 * 185 * @see genlmsg_valid_hdr() 186 * @see genlmsg_validate() 187 * @see nla_parse() 188 * 189 * @return 0 on success or a negative error code. 190 */ 191 int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], 192 int maxtype, struct nla_policy *policy) 193 { 194 struct genlmsghdr *ghdr; 195 196 if (!genlmsg_valid_hdr(nlh, hdrlen)) 197 return -NLE_MSG_TOOSHORT; 198 199 ghdr = nlmsg_data(nlh); 200 return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen), 201 genlmsg_attrlen(ghdr, hdrlen), policy); 202 } 203 204 /** 205 * Return pointer to Generic Netlink header 206 * @arg nlh Netlink message header 207 * 208 * @return Pointer to Generic Netlink message header 209 */ 210 struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh) 211 { 212 return nlmsg_data(nlh); 213 } 214 215 /** 216 * Return length of message payload including user header 217 * @arg gnlh Generic Netlink message header 218 * 219 * @see genlmsg_data() 220 * 221 * @return Length of user payload including an eventual user header in 222 * number of bytes. 223 */ 224 int genlmsg_len(const struct genlmsghdr *gnlh) 225 { 226 const struct nlmsghdr *nlh; 227 228 nlh = (const struct nlmsghdr *)((const unsigned char *) gnlh - NLMSG_HDRLEN); 229 return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); 230 } 231 232 233 /** 234 * Return pointer to user header 235 * @arg gnlh Generic Netlink message header 236 * 237 * Calculates the pointer to the user header based on the pointer to 238 * the Generic Netlink message header. 239 * 240 * @return Pointer to the user header 241 */ 242 void *genlmsg_user_hdr(const struct genlmsghdr *gnlh) 243 { 244 return genlmsg_data(gnlh); 245 } 246 247 /** 248 * Return pointer to user data 249 * @arg gnlh Generic netlink message header 250 * @arg hdrlen Length of user header 251 * 252 * Calculates the pointer to the user data based on the pointer to 253 * the Generic Netlink message header. 254 * 255 * @see genlmsg_user_datalen() 256 * 257 * @return Pointer to the user data 258 */ 259 void *genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) 260 { 261 return genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); 262 } 263 264 /** 265 * Return length of user data 266 * @arg gnlh Generic Netlink message header 267 * @arg hdrlen Length of user header 268 * 269 * @see genlmsg_user_data() 270 * 271 * @return Length of user data in bytes 272 */ 273 int genlmsg_user_datalen(const struct genlmsghdr *gnlh, const int hdrlen) 274 { 275 return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); 276 } 277 278 /** 279 * Return pointer to message attributes 280 * @arg gnlh Generic Netlink message header 281 * @arg hdrlen Length of user header 282 * 283 * @see genlmsg_attrlen() 284 * 285 * @return Pointer to the start of the message's attributes section. 286 */ 287 struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) 288 { 289 return genlmsg_user_data(gnlh, hdrlen); 290 } 291 292 /** 293 * Return length of message attributes 294 * @arg gnlh Generic Netlink message header 295 * @arg hdrlen Length of user header 296 * 297 * @see genlmsg_attrdata() 298 * 299 * @return Length of the message section containing attributes in number 300 * of bytes. 301 */ 302 int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) 303 { 304 return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); 305 } 306 307 /** @} */ 308 309 /** 310 * @name Message Construction 311 * @{ 312 */ 313 314 /** 315 * Add Generic Netlink headers to Netlink message 316 * @arg msg Netlink message object 317 * @arg port Netlink port or NL_AUTO_PORT 318 * @arg seq Sequence number of message or NL_AUTO_SEQ 319 * @arg family Numeric family identifier 320 * @arg hdrlen Length of user header 321 * @arg flags Additional Netlink message flags (optional) 322 * @arg cmd Numeric command identifier 323 * @arg version Interface version 324 * 325 * Calls nlmsg_put() on the specified message object to reserve space for 326 * the Netlink header, the Generic Netlink header, and a user header of 327 * specified length. Fills out the header fields with the specified 328 * parameters. 329 * 330 * @par Example: 331 * @code 332 * struct nl_msg *msg; 333 * struct my_hdr *user_hdr; 334 * 335 * if (!(msg = nlmsg_alloc())) 336 * // ERROR 337 * 338 * user_hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id, 339 * sizeof(struct my_hdr), 0, MY_CMD_FOO, 0); 340 * if (!user_hdr) 341 * // ERROR 342 * @endcode 343 * 344 * @see nlmsg_put() 345 * 346 * Returns Pointer to user header or NULL if an error occurred. 347 */ 348 void *genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, 349 int hdrlen, int flags, uint8_t cmd, uint8_t version) 350 { 351 struct nlmsghdr *nlh; 352 struct genlmsghdr hdr = { 353 .cmd = cmd, 354 .version = version, 355 }; 356 357 nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); 358 if (nlh == NULL) 359 return NULL; 360 361 memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); 362 NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n", 363 msg, cmd, version); 364 365 return nlmsg_data(nlh) + GENL_HDRLEN; 366 } 367 368 /** @} */ 369 370 /** 371 * @name Deprecated 372 * @{ 373 */ 374 375 /** 376 * Return pointer to message payload 377 * @arg gnlh Generic Netlink message header 378 * 379 * @deprecated This function has been deprecated due to inability to specify 380 * the length of the user header. Use genlmsg_user_hdr() 381 * respectively genlmsg_user_data(). 382 * 383 * @return Pointer to payload section 384 */ 385 void *genlmsg_data(const struct genlmsghdr *gnlh) 386 { 387 return ((unsigned char *) gnlh + GENL_HDRLEN); 388 } 389 390 /** @} */ 391 /** @} */ 392