Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drbd: prepare the transition from connector to genetlink

This adds the new API header and helper files.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>

authored by

Lars Ellenberg and committed by
Philipp Reisner
ec2c35ac 3cb7a2a9

+1081
+349
include/linux/drbd_genl.h
··· 1 + /* 2 + * General overview: 3 + * full generic netlink message: 4 + * |nlmsghdr|genlmsghdr|<payload> 5 + * 6 + * payload: 7 + * |optional fixed size family header|<sequence of netlink attributes> 8 + * 9 + * sequence of netlink attributes: 10 + * I chose to have all "top level" attributes NLA_NESTED, 11 + * corresponding to some real struct. 12 + * So we have a sequence of |tla, len|<nested nla sequence> 13 + * 14 + * nested nla sequence: 15 + * may be empty, or contain a sequence of netlink attributes 16 + * representing the struct fields. 17 + * 18 + * The tag number of any field (regardless of containing struct) 19 + * will be available as T_ ## field_name, 20 + * so you cannot have the same field name in two differnt structs. 21 + * 22 + * The tag numbers themselves are per struct, though, 23 + * so should always begin at 1 (not 0, that is the special "NLA_UNSPEC" type, 24 + * which we won't use here). 25 + * The tag numbers are used as index in the respective nla_policy array. 26 + * 27 + * GENL_struct(tag_name, tag_number, struct name, struct fields) - struct and policy 28 + * genl_magic_struct.h 29 + * generates the struct declaration, 30 + * generates an entry in the tla enum, 31 + * genl_magic_func.h 32 + * generates an entry in the static tla policy 33 + * with .type = NLA_NESTED 34 + * generates the static <struct_name>_nl_policy definition, 35 + * and static conversion functions 36 + * 37 + * genl_magic_func.h 38 + * 39 + * GENL_mc_group(group) 40 + * genl_magic_struct.h 41 + * does nothing 42 + * genl_magic_func.h 43 + * defines and registers the mcast group, 44 + * and provides a send helper 45 + * 46 + * GENL_notification(op_name, op_num, mcast_group, tla list) 47 + * These are notifications to userspace. 48 + * 49 + * genl_magic_struct.h 50 + * generates an entry in the genl_ops enum, 51 + * genl_magic_func.h 52 + * does nothing 53 + * 54 + * mcast group: the name of the mcast group this notification should be 55 + * expected on 56 + * tla list: the list of expected top level attributes, 57 + * for documentation and sanity checking. 58 + * 59 + * GENL_op(op_name, op_num, flags and handler, tla list) - "genl operations" 60 + * These are requests from userspace. 61 + * 62 + * _op and _notification share the same "number space", 63 + * op_nr will be assigned to "genlmsghdr->cmd" 64 + * 65 + * genl_magic_struct.h 66 + * generates an entry in the genl_ops enum, 67 + * genl_magic_func.h 68 + * generates an entry in the static genl_ops array, 69 + * and static register/unregister functions to 70 + * genl_register_family_with_ops(). 71 + * 72 + * flags and handler: 73 + * GENL_op_init( .doit = x, .dumpit = y, .flags = something) 74 + * GENL_doit(x) => .dumpit = NULL, .flags = GENL_ADMIN_PERM 75 + * tla list: the list of expected top level attributes, 76 + * for documentation and sanity checking. 77 + */ 78 + 79 + /* 80 + * STRUCTS 81 + */ 82 + 83 + /* this is sent kernel -> userland on various error conditions, and contains 84 + * informational textual info, which is supposedly human readable. 85 + * The computer relevant return code is in the drbd_genlmsghdr. 86 + */ 87 + GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply, 88 + /* "arbitrary" size strings, nla_policy.len = 0 */ 89 + __str_field(1, GENLA_F_MANDATORY, info_text, 0) 90 + ) 91 + 92 + /* Configuration requests typically need a context to operate on. 93 + * Possible keys are device minor (fits in the drbd_genlmsghdr), 94 + * the replication link (aka connection) name, 95 + * and/or the replication group (aka resource) name, 96 + * and the volume id within the resource. */ 97 + GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context, 98 + /* currently only 256 volumes per group, 99 + * but maybe we still change that */ 100 + __u32_field(1, GENLA_F_MANDATORY, ctx_volume) 101 + __str_field(2, GENLA_F_MANDATORY, ctx_conn_name, 128) 102 + ) 103 + 104 + GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf, 105 + __u64_field(1, GENLA_F_MANDATORY, disk_size) 106 + __str_field(2, GENLA_F_REQUIRED, backing_dev, 128) 107 + __str_field(3, GENLA_F_REQUIRED, meta_dev, 128) 108 + __u32_field(4, GENLA_F_REQUIRED, meta_dev_idx) 109 + __u32_field(5, GENLA_F_MANDATORY, max_bio_bvecs) 110 + __u32_field(6, GENLA_F_MANDATORY, on_io_error) 111 + __u32_field(7, GENLA_F_MANDATORY, fencing) 112 + __flg_field(8, GENLA_F_MANDATORY, no_disk_barrier) 113 + __flg_field(9, GENLA_F_MANDATORY, no_disk_flush) 114 + __flg_field(10, GENLA_F_MANDATORY, no_disk_drain) 115 + __flg_field(11, GENLA_F_MANDATORY, no_md_flush) 116 + __flg_field(12, GENLA_F_MANDATORY, use_bmbv) 117 + ) 118 + 119 + GENL_struct(DRBD_NLA_SYNCER_CONF, 4, syncer_conf, 120 + __u32_field(1, GENLA_F_MANDATORY, rate) 121 + __u32_field(2, GENLA_F_MANDATORY, after) 122 + __u32_field(3, GENLA_F_MANDATORY, al_extents) 123 + __str_field(4, GENLA_F_MANDATORY, cpu_mask, 32) 124 + __str_field(5, GENLA_F_MANDATORY, verify_alg, SHARED_SECRET_MAX) 125 + __str_field(6, GENLA_F_MANDATORY, csums_alg, SHARED_SECRET_MAX) 126 + __flg_field(7, GENLA_F_MANDATORY, use_rle) 127 + __u32_field(8, GENLA_F_MANDATORY, on_no_data) 128 + __u32_field(9, GENLA_F_MANDATORY, c_plan_ahead) 129 + __u32_field(10, GENLA_F_MANDATORY, c_delay_target) 130 + __u32_field(11, GENLA_F_MANDATORY, c_fill_target) 131 + __u32_field(12, GENLA_F_MANDATORY, c_max_rate) 132 + __u32_field(13, GENLA_F_MANDATORY, c_min_rate) 133 + ) 134 + 135 + GENL_struct(DRBD_NLA_NET_CONF, 5, net_conf, 136 + __str_field(1, GENLA_F_MANDATORY | GENLA_F_SENSITIVE, 137 + shared_secret, SHARED_SECRET_MAX) 138 + __str_field(2, GENLA_F_MANDATORY, cram_hmac_alg, SHARED_SECRET_MAX) 139 + __str_field(3, GENLA_F_MANDATORY, integrity_alg, SHARED_SECRET_MAX) 140 + __str_field(4, GENLA_F_REQUIRED, my_addr, 128) 141 + __str_field(5, GENLA_F_REQUIRED, peer_addr, 128) 142 + __u32_field(6, GENLA_F_REQUIRED, wire_protocol) 143 + __u32_field(7, GENLA_F_MANDATORY, try_connect_int) 144 + __u32_field(8, GENLA_F_MANDATORY, timeout) 145 + __u32_field(9, GENLA_F_MANDATORY, ping_int) 146 + __u32_field(10, GENLA_F_MANDATORY, ping_timeo) 147 + __u32_field(11, GENLA_F_MANDATORY, sndbuf_size) 148 + __u32_field(12, GENLA_F_MANDATORY, rcvbuf_size) 149 + __u32_field(13, GENLA_F_MANDATORY, ko_count) 150 + __u32_field(14, GENLA_F_MANDATORY, max_buffers) 151 + __u32_field(15, GENLA_F_MANDATORY, max_epoch_size) 152 + __u32_field(16, GENLA_F_MANDATORY, unplug_watermark) 153 + __u32_field(17, GENLA_F_MANDATORY, after_sb_0p) 154 + __u32_field(18, GENLA_F_MANDATORY, after_sb_1p) 155 + __u32_field(19, GENLA_F_MANDATORY, after_sb_2p) 156 + __u32_field(20, GENLA_F_MANDATORY, rr_conflict) 157 + __u32_field(21, GENLA_F_MANDATORY, on_congestion) 158 + __u32_field(22, GENLA_F_MANDATORY, cong_fill) 159 + __u32_field(23, GENLA_F_MANDATORY, cong_extents) 160 + __flg_field(24, GENLA_F_MANDATORY, two_primaries) 161 + __flg_field(25, GENLA_F_MANDATORY, want_lose) 162 + __flg_field(26, GENLA_F_MANDATORY, no_cork) 163 + __flg_field(27, GENLA_F_MANDATORY, always_asbp) 164 + __flg_field(28, GENLA_F_MANDATORY, dry_run) 165 + ) 166 + 167 + GENL_struct(DRBD_NLA_SET_ROLE_PARMS, 6, set_role_parms, 168 + __flg_field(1, GENLA_F_MANDATORY, assume_uptodate) 169 + ) 170 + 171 + GENL_struct(DRBD_NLA_RESIZE_PARMS, 7, resize_parms, 172 + __u64_field(1, GENLA_F_MANDATORY, resize_size) 173 + __flg_field(2, GENLA_F_MANDATORY, resize_force) 174 + __flg_field(3, GENLA_F_MANDATORY, no_resync) 175 + ) 176 + 177 + GENL_struct(DRBD_NLA_STATE_INFO, 8, state_info, 178 + /* the reason of the broadcast, 179 + * if this is an event triggered broadcast. */ 180 + __u32_field(1, GENLA_F_MANDATORY, sib_reason) 181 + __u32_field(2, GENLA_F_REQUIRED, current_state) 182 + __u64_field(3, GENLA_F_MANDATORY, capacity) 183 + __u64_field(4, GENLA_F_MANDATORY, ed_uuid) 184 + 185 + /* These are for broadcast from after state change work. 186 + * prev_state and new_state are from the moment the state change took 187 + * place, new_state is not neccessarily the same as current_state, 188 + * there may have been more state changes since. Which will be 189 + * broadcasted soon, in their respective after state change work. */ 190 + __u32_field(5, GENLA_F_MANDATORY, prev_state) 191 + __u32_field(6, GENLA_F_MANDATORY, new_state) 192 + 193 + /* if we have a local disk: */ 194 + __bin_field(7, GENLA_F_MANDATORY, uuids, (UI_SIZE*sizeof(__u64))) 195 + __u32_field(8, GENLA_F_MANDATORY, disk_flags) 196 + __u64_field(9, GENLA_F_MANDATORY, bits_total) 197 + __u64_field(10, GENLA_F_MANDATORY, bits_oos) 198 + /* and in case resync or online verify is active */ 199 + __u64_field(11, GENLA_F_MANDATORY, bits_rs_total) 200 + __u64_field(12, GENLA_F_MANDATORY, bits_rs_failed) 201 + 202 + /* for pre and post notifications of helper execution */ 203 + __str_field(13, GENLA_F_MANDATORY, helper, 32) 204 + __u32_field(14, GENLA_F_MANDATORY, helper_exit_code) 205 + ) 206 + 207 + GENL_struct(DRBD_NLA_START_OV_PARMS, 9, start_ov_parms, 208 + __u64_field(1, GENLA_F_MANDATORY, ov_start_sector) 209 + ) 210 + 211 + GENL_struct(DRBD_NLA_NEW_C_UUID_PARMS, 10, new_c_uuid_parms, 212 + __flg_field(1, GENLA_F_MANDATORY, clear_bm) 213 + ) 214 + 215 + GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms, 216 + __u32_field(1, GENLA_F_REQUIRED, timeout_type) 217 + ) 218 + 219 + GENL_struct(DRBD_NLA_DISCONNECT_PARMS, 12, disconnect_parms, 220 + __flg_field(1, GENLA_F_MANDATORY, force_disconnect) 221 + ) 222 + 223 + /* 224 + * Notifications and commands (genlmsghdr->cmd) 225 + */ 226 + GENL_mc_group(events) 227 + 228 + /* kernel -> userspace announcement of changes */ 229 + GENL_notification( 230 + DRBD_EVENT, 1, events, 231 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 232 + GENL_tla_expected(DRBD_NLA_STATE_INFO, GENLA_F_REQUIRED) 233 + GENL_tla_expected(DRBD_NLA_NET_CONF, GENLA_F_MANDATORY) 234 + GENL_tla_expected(DRBD_NLA_DISK_CONF, GENLA_F_MANDATORY) 235 + GENL_tla_expected(DRBD_NLA_SYNCER_CONF, GENLA_F_MANDATORY) 236 + ) 237 + 238 + /* query kernel for specific or all info */ 239 + GENL_op( 240 + DRBD_ADM_GET_STATUS, 2, 241 + GENL_op_init( 242 + .doit = drbd_adm_get_status, 243 + .dumpit = drbd_adm_get_status_all, 244 + /* anyone may ask for the status, 245 + * it is broadcasted anyways */ 246 + ), 247 + /* To select the object .doit. 248 + * Or a subset of objects in .dumpit. */ 249 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_MANDATORY) 250 + ) 251 + 252 + #if 0 253 + /* TO BE DONE */ 254 + /* create or destroy resources, aka replication groups */ 255 + GENL_op(DRBD_ADM_CREATE_RESOURCE, 3, GENL_doit(drbd_adm_create_resource), 256 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 257 + GENL_op(DRBD_ADM_DELETE_RESOURCE, 4, GENL_doit(drbd_adm_delete_resource), 258 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 259 + #endif 260 + 261 + /* add DRBD minor devices as volumes to resources */ 262 + GENL_op(DRBD_ADM_ADD_MINOR, 5, GENL_doit(drbd_adm_add_minor), 263 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 264 + GENL_op(DRBD_ADM_DEL_MINOR, 6, GENL_doit(drbd_adm_delete_minor), 265 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 266 + 267 + /* add or delete replication links to resources */ 268 + GENL_op(DRBD_ADM_ADD_LINK, 7, GENL_doit(drbd_adm_create_connection), 269 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 270 + GENL_op(DRBD_ADM_DEL_LINK, 8, GENL_doit(drbd_adm_delete_connection), 271 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 272 + 273 + /* operates on replication links */ 274 + GENL_op(DRBD_ADM_SYNCER, 9, 275 + GENL_doit(drbd_adm_syncer), 276 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 277 + GENL_tla_expected(DRBD_NLA_SYNCER_CONF, GENLA_F_MANDATORY) 278 + ) 279 + 280 + GENL_op( 281 + DRBD_ADM_CONNECT, 10, 282 + GENL_doit(drbd_adm_connect), 283 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 284 + GENL_tla_expected(DRBD_NLA_NET_CONF, GENLA_F_REQUIRED) 285 + ) 286 + 287 + GENL_op(DRBD_ADM_DISCONNECT, 11, GENL_doit(drbd_adm_disconnect), 288 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 289 + 290 + /* operates on minors */ 291 + GENL_op(DRBD_ADM_ATTACH, 12, 292 + GENL_doit(drbd_adm_attach), 293 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 294 + GENL_tla_expected(DRBD_NLA_DISK_CONF, GENLA_F_REQUIRED) 295 + ) 296 + 297 + GENL_op( 298 + DRBD_ADM_RESIZE, 13, 299 + GENL_doit(drbd_adm_resize), 300 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 301 + GENL_tla_expected(DRBD_NLA_RESIZE_PARMS, GENLA_F_MANDATORY) 302 + ) 303 + 304 + /* operates on all volumes within a resource */ 305 + GENL_op( 306 + DRBD_ADM_PRIMARY, 14, 307 + GENL_doit(drbd_adm_set_role), 308 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 309 + GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, GENLA_F_REQUIRED) 310 + ) 311 + 312 + GENL_op( 313 + DRBD_ADM_SECONDARY, 15, 314 + GENL_doit(drbd_adm_set_role), 315 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 316 + GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, GENLA_F_REQUIRED) 317 + ) 318 + 319 + GENL_op( 320 + DRBD_ADM_NEW_C_UUID, 16, 321 + GENL_doit(drbd_adm_new_c_uuid), 322 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED) 323 + GENL_tla_expected(DRBD_NLA_NEW_C_UUID_PARMS, GENLA_F_MANDATORY) 324 + ) 325 + 326 + GENL_op( 327 + DRBD_ADM_START_OV, 17, 328 + GENL_doit(drbd_adm_start_ov), 329 + GENL_tla_expected(DRBD_NLA_START_OV_PARMS, GENLA_F_MANDATORY) 330 + ) 331 + 332 + GENL_op(DRBD_ADM_DETACH, 18, GENL_doit(drbd_adm_detach), 333 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 334 + GENL_op(DRBD_ADM_INVALIDATE, 19, GENL_doit(drbd_adm_invalidate), 335 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 336 + GENL_op(DRBD_ADM_INVAL_PEER, 20, GENL_doit(drbd_adm_invalidate_peer), 337 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 338 + GENL_op(DRBD_ADM_PAUSE_SYNC, 21, GENL_doit(drbd_adm_pause_sync), 339 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 340 + GENL_op(DRBD_ADM_RESUME_SYNC, 22, GENL_doit(drbd_adm_resume_sync), 341 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 342 + GENL_op(DRBD_ADM_SUSPEND_IO, 23, GENL_doit(drbd_adm_suspend_io), 343 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 344 + GENL_op(DRBD_ADM_RESUME_IO, 24, GENL_doit(drbd_adm_resume_io), 345 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 346 + GENL_op(DRBD_ADM_OUTDATE, 25, GENL_doit(drbd_adm_outdate), 347 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED)) 348 + GENL_op(DRBD_ADM_GET_TIMEOUT_TYPE, 26, GENL_doit(drbd_adm_get_timeout_type), 349 + GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, GENLA_F_REQUIRED))
+55
include/linux/drbd_genl_api.h
··· 1 + #ifndef DRBD_GENL_STRUCT_H 2 + #define DRBD_GENL_STRUCT_H 3 + 4 + /** 5 + * struct drbd_genlmsghdr - DRBD specific header used in NETLINK_GENERIC requests 6 + * @minor: 7 + * For admin requests (user -> kernel): which minor device to operate on. 8 + * For (unicast) replies or informational (broadcast) messages 9 + * (kernel -> user): which minor device the information is about. 10 + * If we do not operate on minors, but on connections or resources, 11 + * the minor value shall be (~0), and the attribute DRBD_NLA_CFG_CONTEXT 12 + * is used instead. 13 + * @flags: possible operation modifiers (relevant only for user->kernel): 14 + * DRBD_GENL_F_SET_DEFAULTS 15 + * @volume: 16 + * When creating a new minor (adding it to a resource), the resource needs 17 + * to know which volume number within the resource this is supposed to be. 18 + * The volume number corresponds to the same volume number on the remote side, 19 + * whereas the minor number on the remote side may be different 20 + * (union with flags). 21 + * @ret_code: kernel->userland unicast cfg reply return code (union with flags); 22 + */ 23 + struct drbd_genlmsghdr { 24 + __u32 minor; 25 + union { 26 + __u32 flags; 27 + __s32 ret_code; 28 + }; 29 + }; 30 + 31 + /* To be used in drbd_genlmsghdr.flags */ 32 + enum { 33 + DRBD_GENL_F_SET_DEFAULTS = 1, 34 + }; 35 + 36 + enum drbd_state_info_bcast_reason { 37 + SIB_GET_STATUS_REPLY = 1, 38 + SIB_STATE_CHANGE = 2, 39 + SIB_HELPER_PRE = 3, 40 + SIB_HELPER_POST = 4, 41 + SIB_SYNC_PROGRESS = 5, 42 + }; 43 + 44 + /* hack around predefined gcc/cpp "linux=1", 45 + * we cannot possibly include <1/drbd_genl.h> */ 46 + #undef linux 47 + 48 + #include <linux/drbd.h> 49 + #define GENL_MAGIC_VERSION API_VERSION 50 + #define GENL_MAGIC_FAMILY drbd 51 + #define GENL_MAGIC_FAMILY_HDRSZ sizeof(struct drbd_genlmsghdr) 52 + #define GENL_MAGIC_INCLUDE_FILE <linux/drbd_genl.h> 53 + #include <linux/genl_magic_struct.h> 54 + 55 + #endif
+417
include/linux/genl_magic_func.h
··· 1 + #ifndef GENL_MAGIC_FUNC_H 2 + #define GENL_MAGIC_FUNC_H 3 + 4 + #include <linux/genl_magic_struct.h> 5 + 6 + /* 7 + * Extension of genl attribute validation policies {{{1 8 + * {{{2 9 + */ 10 + 11 + /** 12 + * nla_is_required - return true if this attribute is required 13 + * @nla: netlink attribute 14 + */ 15 + static inline int nla_is_required(const struct nlattr *nla) 16 + { 17 + return nla->nla_type & GENLA_F_REQUIRED; 18 + } 19 + 20 + /** 21 + * nla_is_mandatory - return true if understanding this attribute is mandatory 22 + * @nla: netlink attribute 23 + * Note: REQUIRED attributes are implicitly MANDATORY as well 24 + */ 25 + static inline int nla_is_mandatory(const struct nlattr *nla) 26 + { 27 + return nla->nla_type & (GENLA_F_MANDATORY | GENLA_F_REQUIRED); 28 + } 29 + 30 + /* Functionality to be integrated into nla_parse(), and validate_nla(), 31 + * respectively. 32 + * 33 + * Enforcing the "mandatory" bit is done here, 34 + * by rejecting unknown mandatory attributes. 35 + * 36 + * Part of enforcing the "required" flag would mean to embed it into 37 + * nla_policy.type, and extending validate_nla(), which currently does 38 + * BUG_ON(pt->type > NLA_TYPE_MAX); we have to work on existing kernels, 39 + * so we cannot do that. Thats why enforcing "required" is done in the 40 + * generated assignment functions below. */ 41 + static int nla_check_unknown(int maxtype, struct nlattr *head, int len) 42 + { 43 + struct nlattr *nla; 44 + int rem; 45 + nla_for_each_attr(nla, head, len, rem) { 46 + __u16 type = nla_type(nla); 47 + if (type > maxtype && nla_is_mandatory(nla)) 48 + return -EOPNOTSUPP; 49 + } 50 + return 0; 51 + } 52 + 53 + /* 54 + * Magic: declare tla policy {{{1 55 + * Magic: declare nested policies 56 + * {{{2 57 + */ 58 + #undef GENL_mc_group 59 + #define GENL_mc_group(group) 60 + 61 + #undef GENL_notification 62 + #define GENL_notification(op_name, op_num, mcast_group, tla_list) 63 + 64 + #undef GENL_op 65 + #define GENL_op(op_name, op_num, handler, tla_list) 66 + 67 + #undef GENL_struct 68 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 69 + [tag_name] = { .type = NLA_NESTED }, 70 + 71 + static struct nla_policy CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy)[] = { 72 + #include GENL_MAGIC_INCLUDE_FILE 73 + }; 74 + 75 + #undef GENL_struct 76 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 77 + static struct nla_policy s_name ## _nl_policy[] __read_mostly = \ 78 + { s_fields }; 79 + 80 + #undef __field 81 + #define __field(attr_nr, attr_flag, name, nla_type, _type, __get, __put) \ 82 + [__nla_type(attr_nr)] = { .type = nla_type }, 83 + 84 + #undef __array 85 + #define __array(attr_nr, attr_flag, name, nla_type, _type, maxlen, \ 86 + __get, __put) \ 87 + [__nla_type(attr_nr)] = { .type = nla_type, \ 88 + .len = maxlen - (nla_type == NLA_NUL_STRING) }, 89 + 90 + #include GENL_MAGIC_INCLUDE_FILE 91 + 92 + #ifndef __KERNEL__ 93 + #ifndef pr_info 94 + #define pr_info(args...) fprintf(stderr, args); 95 + #endif 96 + #endif 97 + 98 + #if 1 99 + static void dprint_field(const char *dir, int nla_type, 100 + const char *name, void *valp) 101 + { 102 + __u64 val = valp ? *(__u32 *)valp : 1; 103 + switch (nla_type) { 104 + case NLA_U8: val = (__u8)val; 105 + case NLA_U16: val = (__u16)val; 106 + case NLA_U32: val = (__u32)val; 107 + pr_info("%s attr %s: %d 0x%08x\n", dir, 108 + name, (int)val, (unsigned)val); 109 + break; 110 + case NLA_U64: 111 + val = *(__u64*)valp; 112 + pr_info("%s attr %s: %lld 0x%08llx\n", dir, 113 + name, (long long)val, (unsigned long long)val); 114 + break; 115 + case NLA_FLAG: 116 + if (val) 117 + pr_info("%s attr %s: set\n", dir, name); 118 + break; 119 + } 120 + } 121 + 122 + static void dprint_array(const char *dir, int nla_type, 123 + const char *name, const char *val, unsigned len) 124 + { 125 + switch (nla_type) { 126 + case NLA_NUL_STRING: 127 + if (len && val[len-1] == '\0') 128 + len--; 129 + pr_info("%s attr %s: [len:%u] '%s'\n", dir, name, len, val); 130 + break; 131 + default: 132 + /* we can always show 4 byte, 133 + * thats what nlattr are aligned to. */ 134 + pr_info("%s attr %s: [len:%u] %02x%02x%02x%02x ...\n", 135 + dir, name, len, val[0], val[1], val[2], val[3]); 136 + } 137 + } 138 + 139 + #define DPRINT_TLA(a, op, b) pr_info("%s %s %s\n", a, op, b); 140 + 141 + /* Name is a member field name of the struct s. 142 + * If s is NULL (only parsing, no copy requested in *_from_attrs()), 143 + * nla is supposed to point to the attribute containing the information 144 + * corresponding to that struct member. */ 145 + #define DPRINT_FIELD(dir, nla_type, name, s, nla) \ 146 + do { \ 147 + if (s) \ 148 + dprint_field(dir, nla_type, #name, &s->name); \ 149 + else if (nla) \ 150 + dprint_field(dir, nla_type, #name, \ 151 + (nla_type == NLA_FLAG) ? NULL \ 152 + : nla_data(nla)); \ 153 + } while (0) 154 + 155 + #define DPRINT_ARRAY(dir, nla_type, name, s, nla) \ 156 + do { \ 157 + if (s) \ 158 + dprint_array(dir, nla_type, #name, \ 159 + s->name, s->name ## _len); \ 160 + else if (nla) \ 161 + dprint_array(dir, nla_type, #name, \ 162 + nla_data(nla), nla_len(nla)); \ 163 + } while (0) 164 + #else 165 + #define DPRINT_TLA(a, op, b) do {} while (0) 166 + #define DPRINT_FIELD(dir, nla_type, name, s, nla) do {} while (0) 167 + #define DPRINT_ARRAY(dir, nla_type, name, s, nla) do {} while (0) 168 + #endif 169 + 170 + /* 171 + * Magic: provide conversion functions {{{1 172 + * populate struct from attribute table: 173 + * {{{2 174 + */ 175 + 176 + /* processing of generic netlink messages is serialized. 177 + * use one static buffer for parsing of nested attributes */ 178 + static struct nlattr *nested_attr_tb[128]; 179 + 180 + #ifndef BUILD_BUG_ON 181 + /* Force a compilation error if condition is true */ 182 + #define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition)) 183 + /* Force a compilation error if condition is true, but also produce a 184 + result (of value 0 and type size_t), so the expression can be used 185 + e.g. in a structure initializer (or where-ever else comma expressions 186 + aren't permitted). */ 187 + #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 188 + #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) 189 + #endif 190 + 191 + #undef GENL_struct 192 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 193 + /* static, potentially unused */ \ 194 + int s_name ## _from_attrs(struct s_name *s, struct nlattr *tb[]) \ 195 + { \ 196 + const int maxtype = ARRAY_SIZE(s_name ## _nl_policy)-1; \ 197 + struct nlattr *tla = tb[tag_number]; \ 198 + struct nlattr **ntb = nested_attr_tb; \ 199 + struct nlattr *nla; \ 200 + int err; \ 201 + BUILD_BUG_ON(ARRAY_SIZE(s_name ## _nl_policy) > ARRAY_SIZE(nested_attr_tb)); \ 202 + if (!tla) \ 203 + return -ENOMSG; \ 204 + DPRINT_TLA(#s_name, "<=-", #tag_name); \ 205 + err = nla_parse_nested(ntb, maxtype, tla, s_name ## _nl_policy); \ 206 + if (err) \ 207 + return err; \ 208 + err = nla_check_unknown(maxtype, nla_data(tla), nla_len(tla)); \ 209 + if (err) \ 210 + return err; \ 211 + \ 212 + s_fields \ 213 + return 0; \ 214 + } 215 + 216 + #undef __field 217 + #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \ 218 + nla = ntb[__nla_type(attr_nr)]; \ 219 + if (nla) { \ 220 + if (s) \ 221 + s->name = __get(nla); \ 222 + DPRINT_FIELD("<<", nla_type, name, s, nla); \ 223 + } else if ((attr_flag) & GENLA_F_REQUIRED) { \ 224 + pr_info("<< missing attr: %s\n", #name); \ 225 + return -ENOMSG; \ 226 + } 227 + 228 + /* validate_nla() already checked nla_len <= maxlen appropriately. */ 229 + #undef __array 230 + #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \ 231 + nla = ntb[__nla_type(attr_nr)]; \ 232 + if (nla) { \ 233 + if (s) \ 234 + s->name ## _len = \ 235 + __get(s->name, nla, maxlen); \ 236 + DPRINT_ARRAY("<<", nla_type, name, s, nla); \ 237 + } else if ((attr_flag) & GENLA_F_REQUIRED) { \ 238 + pr_info("<< missing attr: %s\n", #name); \ 239 + return -ENOMSG; \ 240 + } \ 241 + 242 + #include GENL_MAGIC_INCLUDE_FILE 243 + 244 + #undef GENL_struct 245 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) 246 + 247 + /* 248 + * Magic: define op number to op name mapping {{{1 249 + * {{{2 250 + */ 251 + const char *CONCAT_(GENL_MAGIC_FAMILY, _genl_cmd_to_str)(__u8 cmd) 252 + { 253 + switch (cmd) { 254 + #undef GENL_op 255 + #define GENL_op(op_name, op_num, handler, tla_list) \ 256 + case op_num: return #op_name; 257 + #include GENL_MAGIC_INCLUDE_FILE 258 + default: 259 + return "unknown"; 260 + } 261 + } 262 + 263 + #ifdef __KERNEL__ 264 + #include <linux/stringify.h> 265 + /* 266 + * Magic: define genl_ops {{{1 267 + * {{{2 268 + */ 269 + 270 + #undef GENL_op 271 + #define GENL_op(op_name, op_num, handler, tla_list) \ 272 + { \ 273 + handler \ 274 + .cmd = op_name, \ 275 + .policy = CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy), \ 276 + }, 277 + 278 + #define ZZZ_genl_ops CONCAT_(GENL_MAGIC_FAMILY, _genl_ops) 279 + static struct genl_ops ZZZ_genl_ops[] __read_mostly = { 280 + #include GENL_MAGIC_INCLUDE_FILE 281 + }; 282 + 283 + #undef GENL_op 284 + #define GENL_op(op_name, op_num, handler, tla_list) 285 + 286 + /* 287 + * Define the genl_family, multicast groups, {{{1 288 + * and provide register/unregister functions. 289 + * {{{2 290 + */ 291 + #define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family) 292 + static struct genl_family ZZZ_genl_family __read_mostly = { 293 + .id = GENL_ID_GENERATE, 294 + .name = __stringify(GENL_MAGIC_FAMILY), 295 + .version = GENL_MAGIC_VERSION, 296 + #ifdef GENL_MAGIC_FAMILY_HDRSZ 297 + .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ), 298 + #endif 299 + .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1, 300 + }; 301 + 302 + /* 303 + * Magic: define multicast groups 304 + * Magic: define multicast group registration helper 305 + */ 306 + #undef GENL_mc_group 307 + #define GENL_mc_group(group) \ 308 + static struct genl_multicast_group \ 309 + CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \ 310 + .name = #group, \ 311 + }; \ 312 + static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ 313 + struct sk_buff *skb, gfp_t flags) \ 314 + { \ 315 + unsigned int group_id = \ 316 + CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \ 317 + if (!group_id) \ 318 + return -EINVAL; \ 319 + return genlmsg_multicast(skb, 0, group_id, flags); \ 320 + } 321 + 322 + #include GENL_MAGIC_INCLUDE_FILE 323 + 324 + int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) 325 + { 326 + int err = genl_register_family_with_ops(&ZZZ_genl_family, 327 + ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops)); 328 + if (err) 329 + return err; 330 + #undef GENL_mc_group 331 + #define GENL_mc_group(group) \ 332 + err = genl_register_mc_group(&ZZZ_genl_family, \ 333 + &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \ 334 + if (err) \ 335 + goto fail; \ 336 + else \ 337 + pr_info("%s: mcg %s: %u\n", #group, \ 338 + __stringify(GENL_MAGIC_FAMILY), \ 339 + CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id); 340 + 341 + #include GENL_MAGIC_INCLUDE_FILE 342 + 343 + #undef GENL_mc_group 344 + #define GENL_mc_group(group) 345 + return 0; 346 + fail: 347 + genl_unregister_family(&ZZZ_genl_family); 348 + return err; 349 + } 350 + 351 + void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) 352 + { 353 + genl_unregister_family(&ZZZ_genl_family); 354 + } 355 + 356 + /* 357 + * Magic: provide conversion functions {{{1 358 + * populate skb from struct. 359 + * {{{2 360 + */ 361 + 362 + #undef GENL_op 363 + #define GENL_op(op_name, op_num, handler, tla_list) 364 + 365 + #undef GENL_struct 366 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 367 + static int s_name ## _to_skb(struct sk_buff *skb, struct s_name *s, \ 368 + const bool exclude_sensitive) \ 369 + { \ 370 + struct nlattr *tla = nla_nest_start(skb, tag_number); \ 371 + if (!tla) \ 372 + goto nla_put_failure; \ 373 + DPRINT_TLA(#s_name, "-=>", #tag_name); \ 374 + s_fields \ 375 + nla_nest_end(skb, tla); \ 376 + return 0; \ 377 + \ 378 + nla_put_failure: \ 379 + if (tla) \ 380 + nla_nest_cancel(skb, tla); \ 381 + return -EMSGSIZE; \ 382 + } \ 383 + static inline int s_name ## _to_priv_skb(struct sk_buff *skb, \ 384 + struct s_name *s) \ 385 + { \ 386 + return s_name ## _to_skb(skb, s, 0); \ 387 + } \ 388 + static inline int s_name ## _to_unpriv_skb(struct sk_buff *skb, \ 389 + struct s_name *s) \ 390 + { \ 391 + return s_name ## _to_skb(skb, s, 1); \ 392 + } 393 + 394 + 395 + #undef __field 396 + #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \ 397 + if (!exclude_sensitive || !((attr_flag) & GENLA_F_SENSITIVE)) { \ 398 + DPRINT_FIELD(">>", nla_type, name, s, NULL); \ 399 + __put(skb, attr_nr, s->name); \ 400 + } 401 + 402 + #undef __array 403 + #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \ 404 + if (!exclude_sensitive || !((attr_flag) & GENLA_F_SENSITIVE)) { \ 405 + DPRINT_ARRAY(">>",nla_type, name, s, NULL); \ 406 + __put(skb, attr_nr, min_t(int, maxlen, \ 407 + s->name ## _len + (nla_type == NLA_NUL_STRING)),\ 408 + s->name); \ 409 + } 410 + 411 + #include GENL_MAGIC_INCLUDE_FILE 412 + 413 + #endif /* __KERNEL__ */ 414 + 415 + /* }}}1 */ 416 + #endif /* GENL_MAGIC_FUNC_H */ 417 + /* vim: set foldmethod=marker foldlevel=1 nofoldenable : */
+260
include/linux/genl_magic_struct.h
··· 1 + #ifndef GENL_MAGIC_STRUCT_H 2 + #define GENL_MAGIC_STRUCT_H 3 + 4 + #ifndef GENL_MAGIC_FAMILY 5 + # error "you need to define GENL_MAGIC_FAMILY before inclusion" 6 + #endif 7 + 8 + #ifndef GENL_MAGIC_VERSION 9 + # error "you need to define GENL_MAGIC_VERSION before inclusion" 10 + #endif 11 + 12 + #ifndef GENL_MAGIC_INCLUDE_FILE 13 + # error "you need to define GENL_MAGIC_INCLUDE_FILE before inclusion" 14 + #endif 15 + 16 + #include <linux/genetlink.h> 17 + #include <linux/types.h> 18 + 19 + #define CONCAT__(a,b) a ## b 20 + #define CONCAT_(a,b) CONCAT__(a,b) 21 + 22 + extern int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void); 23 + extern void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void); 24 + 25 + /* 26 + * Extension of genl attribute validation policies {{{2 27 + */ 28 + 29 + /** 30 + * GENLA_F_FLAGS - policy type flags to ease compatible ABI evolvement 31 + * 32 + * @GENLA_F_REQUIRED: attribute has to be present, or message is considered invalid. 33 + * Adding new REQUIRED attributes breaks ABI compatibility, so don't do that. 34 + * 35 + * @GENLA_F_MANDATORY: if present, receiver _must_ understand it. 36 + * Without this, unknown attributes (> maxtype) are _silently_ ignored 37 + * by validate_nla(). 38 + * 39 + * To be used for API extensions, so older kernel can reject requests for not 40 + * yet implemented features, if newer userland tries to use them even though 41 + * the genl_family version clearly indicates they are not available. 42 + * 43 + * @GENLA_F_MAY_IGNORE: To clearly document the fact, for good measure. 44 + * To be used for API extensions for things that have sane defaults, 45 + * so newer userland can still talk to older kernel, knowing it will 46 + * silently ignore these attributes if not yet known. 47 + * 48 + * NOTE: These flags overload 49 + * NLA_F_NESTED (1 << 15) 50 + * NLA_F_NET_BYTEORDER (1 << 14) 51 + * from linux/netlink.h, which are not useful for validate_nla(): 52 + * NET_BYTEORDER is not used anywhere, and NESTED would be specified by setting 53 + * .type = NLA_NESTED in the appropriate policy. 54 + * 55 + * See also: nla_type() 56 + */ 57 + enum { 58 + GENLA_F_MAY_IGNORE = 0, 59 + GENLA_F_MANDATORY = 1 << 14, 60 + GENLA_F_REQUIRED = 1 << 15, 61 + 62 + /* This will not be present in the __u16 .nla_type, but can be 63 + * triggered on in <struct>_to_skb, to exclude "sensitive" 64 + * information from broadcasts, or on unpriviledged get requests. 65 + * This is useful because genetlink multicast groups can be listened in 66 + * on by anyone. */ 67 + GENLA_F_SENSITIVE = 1 << 16, 68 + }; 69 + 70 + #define __nla_type(x) ((__u16)((__u16)(x) & (__u16)NLA_TYPE_MASK)) 71 + 72 + /* }}}1 73 + * MAGIC 74 + * multi-include macro expansion magic starts here 75 + */ 76 + 77 + /* MAGIC helpers {{{2 */ 78 + 79 + /* possible field types */ 80 + #define __flg_field(attr_nr, attr_flag, name) \ 81 + __field(attr_nr, attr_flag, name, NLA_FLAG, char, \ 82 + nla_get_flag, __nla_put_flag) 83 + #define __u8_field(attr_nr, attr_flag, name) \ 84 + __field(attr_nr, attr_flag, name, NLA_U8, unsigned char, \ 85 + nla_get_u8, NLA_PUT_U8) 86 + #define __u16_field(attr_nr, attr_flag, name) \ 87 + __field(attr_nr, attr_flag, name, NLA_U16, __u16, \ 88 + nla_get_u16, NLA_PUT_U16) 89 + #define __u32_field(attr_nr, attr_flag, name) \ 90 + __field(attr_nr, attr_flag, name, NLA_U32, __u32, \ 91 + nla_get_u32, NLA_PUT_U32) 92 + #define __u64_field(attr_nr, attr_flag, name) \ 93 + __field(attr_nr, attr_flag, name, NLA_U64, __u64, \ 94 + nla_get_u64, NLA_PUT_U64) 95 + #define __str_field(attr_nr, attr_flag, name, maxlen) \ 96 + __array(attr_nr, attr_flag, name, NLA_NUL_STRING, char, maxlen, \ 97 + nla_strlcpy, NLA_PUT) 98 + #define __bin_field(attr_nr, attr_flag, name, maxlen) \ 99 + __array(attr_nr, attr_flag, name, NLA_BINARY, char, maxlen, \ 100 + nla_memcpy, NLA_PUT) 101 + 102 + #define __nla_put_flag(skb, attrtype, value) \ 103 + do { \ 104 + if (value) \ 105 + NLA_PUT_FLAG(skb, attrtype); \ 106 + } while (0) 107 + 108 + #define GENL_op_init(args...) args 109 + #define GENL_doit(handler) \ 110 + .doit = handler, \ 111 + .flags = GENL_ADMIN_PERM, 112 + #define GENL_dumpit(handler) \ 113 + .dumpit = handler, \ 114 + .flags = GENL_ADMIN_PERM, 115 + 116 + /* }}}1 117 + * Magic: define the enum symbols for genl_ops 118 + * Magic: define the enum symbols for top level attributes 119 + * Magic: define the enum symbols for nested attributes 120 + * {{{2 121 + */ 122 + 123 + #undef GENL_struct 124 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) 125 + 126 + #undef GENL_mc_group 127 + #define GENL_mc_group(group) 128 + 129 + #undef GENL_notification 130 + #define GENL_notification(op_name, op_num, mcast_group, tla_list) \ 131 + op_name = op_num, 132 + 133 + #undef GENL_op 134 + #define GENL_op(op_name, op_num, handler, tla_list) \ 135 + op_name = op_num, 136 + 137 + enum { 138 + #include GENL_MAGIC_INCLUDE_FILE 139 + }; 140 + 141 + #undef GENL_notification 142 + #define GENL_notification(op_name, op_num, mcast_group, tla_list) 143 + 144 + #undef GENL_op 145 + #define GENL_op(op_name, op_num, handler, attr_list) 146 + 147 + #undef GENL_struct 148 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 149 + tag_name = tag_number, 150 + 151 + enum { 152 + #include GENL_MAGIC_INCLUDE_FILE 153 + }; 154 + 155 + #undef GENL_struct 156 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 157 + enum { \ 158 + s_fields \ 159 + }; 160 + 161 + #undef __field 162 + #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \ 163 + T_ ## name = (__u16)(attr_nr | attr_flag), 164 + 165 + #undef __array 166 + #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \ 167 + T_ ## name = (__u16)(attr_nr | attr_flag), 168 + 169 + #include GENL_MAGIC_INCLUDE_FILE 170 + 171 + /* }}}1 172 + * Magic: compile time assert unique numbers for operations 173 + * Magic: -"- unique numbers for top level attributes 174 + * Magic: -"- unique numbers for nested attributes 175 + * {{{2 176 + */ 177 + 178 + #undef GENL_struct 179 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) 180 + 181 + #undef GENL_op 182 + #define GENL_op(op_name, op_num, handler, attr_list) \ 183 + case op_name: 184 + 185 + #undef GENL_notification 186 + #define GENL_notification(op_name, op_num, mcast_group, tla_list) \ 187 + case op_name: 188 + 189 + static inline void ct_assert_unique_operations(void) 190 + { 191 + switch (0) { 192 + #include GENL_MAGIC_INCLUDE_FILE 193 + ; 194 + } 195 + } 196 + 197 + #undef GENL_op 198 + #define GENL_op(op_name, op_num, handler, attr_list) 199 + 200 + #undef GENL_notification 201 + #define GENL_notification(op_name, op_num, mcast_group, tla_list) 202 + 203 + #undef GENL_struct 204 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 205 + case tag_number: 206 + 207 + static inline void ct_assert_unique_top_level_attributes(void) 208 + { 209 + switch (0) { 210 + #include GENL_MAGIC_INCLUDE_FILE 211 + ; 212 + } 213 + } 214 + 215 + #undef GENL_struct 216 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 217 + static inline void ct_assert_unique_ ## s_name ## _attributes(void) \ 218 + { \ 219 + switch (0) { \ 220 + s_fields \ 221 + ; \ 222 + } \ 223 + } 224 + 225 + #undef __field 226 + #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \ 227 + case attr_nr: 228 + 229 + #undef __array 230 + #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \ 231 + case attr_nr: 232 + 233 + #include GENL_MAGIC_INCLUDE_FILE 234 + 235 + /* }}}1 236 + * Magic: declare structs 237 + * struct <name> { 238 + * fields 239 + * }; 240 + * {{{2 241 + */ 242 + 243 + #undef GENL_struct 244 + #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ 245 + struct s_name { s_fields }; 246 + 247 + #undef __field 248 + #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \ 249 + type name; 250 + 251 + #undef __array 252 + #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \ 253 + type name[maxlen]; \ 254 + __u32 name ## _len; 255 + 256 + #include GENL_MAGIC_INCLUDE_FILE 257 + 258 + /* }}}1 */ 259 + #endif /* GENL_MAGIC_STRUCT_H */ 260 + /* vim: set foldmethod=marker nofoldenable : */