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