libnl
3.2.3
|
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 /** @} */