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