1 // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 2 /* Do not edit directly, auto-generated from: */ 3 /* Documentation/netlink/specs/handshake.yaml */ 4 /* YNL-GEN user source */ 5 6 #include <stdlib.h> 7 #include <string.h> 8 #include "handshake-user.h" 9 #include "ynl.h" 10 #include <linux/handshake.h> 11 12 #include <libmnl/libmnl.h> 13 #include <linux/genetlink.h> 14 15 /* Enums */ 16 static const char * const handshake_op_strmap[] = { 17 [HANDSHAKE_CMD_READY] = "ready", 18 [HANDSHAKE_CMD_ACCEPT] = "accept", 19 [HANDSHAKE_CMD_DONE] = "done", 20 }; 21 22 const char *handshake_op_str(int op) 23 { 24 if (op < 0 || op >= (int)MNL_ARRAY_SIZE(handshake_op_strmap)) 25 return NULL; 26 return handshake_op_strmap[op]; 27 } 28 29 static const char * const handshake_handler_class_strmap[] = { 30 [0] = "none", 31 [1] = "tlshd", 32 [2] = "max", 33 }; 34 35 const char *handshake_handler_class_str(enum handshake_handler_class value) 36 { 37 if (value < 0 || value >= (int)MNL_ARRAY_SIZE(handshake_handler_class_strmap)) 38 return NULL; 39 return handshake_handler_class_strmap[value]; 40 } 41 42 static const char * const handshake_msg_type_strmap[] = { 43 [0] = "unspec", 44 [1] = "clienthello", 45 [2] = "serverhello", 46 }; 47 48 const char *handshake_msg_type_str(enum handshake_msg_type value) 49 { 50 if (value < 0 || value >= (int)MNL_ARRAY_SIZE(handshake_msg_type_strmap)) 51 return NULL; 52 return handshake_msg_type_strmap[value]; 53 } 54 55 static const char * const handshake_auth_strmap[] = { 56 [0] = "unspec", 57 [1] = "unauth", 58 [2] = "psk", 59 [3] = "x509", 60 }; 61 62 const char *handshake_auth_str(enum handshake_auth value) 63 { 64 if (value < 0 || value >= (int)MNL_ARRAY_SIZE(handshake_auth_strmap)) 65 return NULL; 66 return handshake_auth_strmap[value]; 67 } 68 69 /* Policies */ 70 struct ynl_policy_attr handshake_x509_policy[HANDSHAKE_A_X509_MAX + 1] = { 71 [HANDSHAKE_A_X509_CERT] = { .name = "cert", .type = YNL_PT_U32, }, 72 [HANDSHAKE_A_X509_PRIVKEY] = { .name = "privkey", .type = YNL_PT_U32, }, 73 }; 74 75 struct ynl_policy_nest handshake_x509_nest = { 76 .max_attr = HANDSHAKE_A_X509_MAX, 77 .table = handshake_x509_policy, 78 }; 79 80 struct ynl_policy_attr handshake_accept_policy[HANDSHAKE_A_ACCEPT_MAX + 1] = { 81 [HANDSHAKE_A_ACCEPT_SOCKFD] = { .name = "sockfd", .type = YNL_PT_U32, }, 82 [HANDSHAKE_A_ACCEPT_HANDLER_CLASS] = { .name = "handler-class", .type = YNL_PT_U32, }, 83 [HANDSHAKE_A_ACCEPT_MESSAGE_TYPE] = { .name = "message-type", .type = YNL_PT_U32, }, 84 [HANDSHAKE_A_ACCEPT_TIMEOUT] = { .name = "timeout", .type = YNL_PT_U32, }, 85 [HANDSHAKE_A_ACCEPT_AUTH_MODE] = { .name = "auth-mode", .type = YNL_PT_U32, }, 86 [HANDSHAKE_A_ACCEPT_PEER_IDENTITY] = { .name = "peer-identity", .type = YNL_PT_U32, }, 87 [HANDSHAKE_A_ACCEPT_CERTIFICATE] = { .name = "certificate", .type = YNL_PT_NEST, .nest = &handshake_x509_nest, }, 88 [HANDSHAKE_A_ACCEPT_PEERNAME] = { .name = "peername", .type = YNL_PT_NUL_STR, }, 89 }; 90 91 struct ynl_policy_nest handshake_accept_nest = { 92 .max_attr = HANDSHAKE_A_ACCEPT_MAX, 93 .table = handshake_accept_policy, 94 }; 95 96 struct ynl_policy_attr handshake_done_policy[HANDSHAKE_A_DONE_MAX + 1] = { 97 [HANDSHAKE_A_DONE_STATUS] = { .name = "status", .type = YNL_PT_U32, }, 98 [HANDSHAKE_A_DONE_SOCKFD] = { .name = "sockfd", .type = YNL_PT_U32, }, 99 [HANDSHAKE_A_DONE_REMOTE_AUTH] = { .name = "remote-auth", .type = YNL_PT_U32, }, 100 }; 101 102 struct ynl_policy_nest handshake_done_nest = { 103 .max_attr = HANDSHAKE_A_DONE_MAX, 104 .table = handshake_done_policy, 105 }; 106 107 /* Common nested types */ 108 void handshake_x509_free(struct handshake_x509 *obj) 109 { 110 } 111 112 int handshake_x509_parse(struct ynl_parse_arg *yarg, 113 const struct nlattr *nested) 114 { 115 struct handshake_x509 *dst = yarg->data; 116 const struct nlattr *attr; 117 118 mnl_attr_for_each_nested(attr, nested) { 119 unsigned int type = mnl_attr_get_type(attr); 120 121 if (type == HANDSHAKE_A_X509_CERT) { 122 if (ynl_attr_validate(yarg, attr)) 123 return MNL_CB_ERROR; 124 dst->_present.cert = 1; 125 dst->cert = mnl_attr_get_u32(attr); 126 } else if (type == HANDSHAKE_A_X509_PRIVKEY) { 127 if (ynl_attr_validate(yarg, attr)) 128 return MNL_CB_ERROR; 129 dst->_present.privkey = 1; 130 dst->privkey = mnl_attr_get_u32(attr); 131 } 132 } 133 134 return 0; 135 } 136 137 /* ============== HANDSHAKE_CMD_ACCEPT ============== */ 138 /* HANDSHAKE_CMD_ACCEPT - do */ 139 void handshake_accept_req_free(struct handshake_accept_req *req) 140 { 141 free(req); 142 } 143 144 void handshake_accept_rsp_free(struct handshake_accept_rsp *rsp) 145 { 146 unsigned int i; 147 148 free(rsp->peer_identity); 149 for (i = 0; i < rsp->n_certificate; i++) 150 handshake_x509_free(&rsp->certificate[i]); 151 free(rsp->certificate); 152 free(rsp->peername); 153 free(rsp); 154 } 155 156 int handshake_accept_rsp_parse(const struct nlmsghdr *nlh, void *data) 157 { 158 struct ynl_parse_arg *yarg = data; 159 struct handshake_accept_rsp *dst; 160 unsigned int n_peer_identity = 0; 161 unsigned int n_certificate = 0; 162 const struct nlattr *attr; 163 struct ynl_parse_arg parg; 164 int i; 165 166 dst = yarg->data; 167 parg.ys = yarg->ys; 168 169 if (dst->certificate) 170 return ynl_error_parse(yarg, "attribute already present (accept.certificate)"); 171 if (dst->peer_identity) 172 return ynl_error_parse(yarg, "attribute already present (accept.peer-identity)"); 173 174 mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { 175 unsigned int type = mnl_attr_get_type(attr); 176 177 if (type == HANDSHAKE_A_ACCEPT_SOCKFD) { 178 if (ynl_attr_validate(yarg, attr)) 179 return MNL_CB_ERROR; 180 dst->_present.sockfd = 1; 181 dst->sockfd = mnl_attr_get_u32(attr); 182 } else if (type == HANDSHAKE_A_ACCEPT_MESSAGE_TYPE) { 183 if (ynl_attr_validate(yarg, attr)) 184 return MNL_CB_ERROR; 185 dst->_present.message_type = 1; 186 dst->message_type = mnl_attr_get_u32(attr); 187 } else if (type == HANDSHAKE_A_ACCEPT_TIMEOUT) { 188 if (ynl_attr_validate(yarg, attr)) 189 return MNL_CB_ERROR; 190 dst->_present.timeout = 1; 191 dst->timeout = mnl_attr_get_u32(attr); 192 } else if (type == HANDSHAKE_A_ACCEPT_AUTH_MODE) { 193 if (ynl_attr_validate(yarg, attr)) 194 return MNL_CB_ERROR; 195 dst->_present.auth_mode = 1; 196 dst->auth_mode = mnl_attr_get_u32(attr); 197 } else if (type == HANDSHAKE_A_ACCEPT_PEER_IDENTITY) { 198 n_peer_identity++; 199 } else if (type == HANDSHAKE_A_ACCEPT_CERTIFICATE) { 200 n_certificate++; 201 } else if (type == HANDSHAKE_A_ACCEPT_PEERNAME) { 202 unsigned int len; 203 204 if (ynl_attr_validate(yarg, attr)) 205 return MNL_CB_ERROR; 206 207 len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); 208 dst->_present.peername_len = len; 209 dst->peername = malloc(len + 1); 210 memcpy(dst->peername, mnl_attr_get_str(attr), len); 211 dst->peername[len] = 0; 212 } 213 } 214 215 if (n_certificate) { 216 dst->certificate = calloc(n_certificate, sizeof(*dst->certificate)); 217 dst->n_certificate = n_certificate; 218 i = 0; 219 parg.rsp_policy = &handshake_x509_nest; 220 mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { 221 if (mnl_attr_get_type(attr) == HANDSHAKE_A_ACCEPT_CERTIFICATE) { 222 parg.data = &dst->certificate[i]; 223 if (handshake_x509_parse(&parg, attr)) 224 return MNL_CB_ERROR; 225 i++; 226 } 227 } 228 } 229 if (n_peer_identity) { 230 dst->peer_identity = calloc(n_peer_identity, sizeof(*dst->peer_identity)); 231 dst->n_peer_identity = n_peer_identity; 232 i = 0; 233 mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { 234 if (mnl_attr_get_type(attr) == HANDSHAKE_A_ACCEPT_PEER_IDENTITY) { 235 dst->peer_identity[i] = mnl_attr_get_u32(attr); 236 i++; 237 } 238 } 239 } 240 241 return MNL_CB_OK; 242 } 243 244 struct handshake_accept_rsp * 245 handshake_accept(struct ynl_sock *ys, struct handshake_accept_req *req) 246 { 247 struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; 248 struct handshake_accept_rsp *rsp; 249 struct nlmsghdr *nlh; 250 int err; 251 252 nlh = ynl_gemsg_start_req(ys, ys->family_id, HANDSHAKE_CMD_ACCEPT, 1); 253 ys->req_policy = &handshake_accept_nest; 254 yrs.yarg.rsp_policy = &handshake_accept_nest; 255 256 if (req->_present.handler_class) 257 mnl_attr_put_u32(nlh, HANDSHAKE_A_ACCEPT_HANDLER_CLASS, req->handler_class); 258 259 rsp = calloc(1, sizeof(*rsp)); 260 yrs.yarg.data = rsp; 261 yrs.cb = handshake_accept_rsp_parse; 262 yrs.rsp_cmd = HANDSHAKE_CMD_ACCEPT; 263 264 err = ynl_exec(ys, nlh, &yrs); 265 if (err < 0) 266 goto err_free; 267 268 return rsp; 269 270 err_free: 271 handshake_accept_rsp_free(rsp); 272 return NULL; 273 } 274 275 /* HANDSHAKE_CMD_ACCEPT - notify */ 276 void handshake_accept_ntf_free(struct handshake_accept_ntf *rsp) 277 { 278 unsigned int i; 279 280 free(rsp->obj.peer_identity); 281 for (i = 0; i < rsp->obj.n_certificate; i++) 282 handshake_x509_free(&rsp->obj.certificate[i]); 283 free(rsp->obj.certificate); 284 free(rsp->obj.peername); 285 free(rsp); 286 } 287 288 /* ============== HANDSHAKE_CMD_DONE ============== */ 289 /* HANDSHAKE_CMD_DONE - do */ 290 void handshake_done_req_free(struct handshake_done_req *req) 291 { 292 free(req->remote_auth); 293 free(req); 294 } 295 296 int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req) 297 { 298 struct nlmsghdr *nlh; 299 int err; 300 301 nlh = ynl_gemsg_start_req(ys, ys->family_id, HANDSHAKE_CMD_DONE, 1); 302 ys->req_policy = &handshake_done_nest; 303 304 if (req->_present.status) 305 mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_STATUS, req->status); 306 if (req->_present.sockfd) 307 mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_SOCKFD, req->sockfd); 308 for (unsigned int i = 0; i < req->n_remote_auth; i++) 309 mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_REMOTE_AUTH, req->remote_auth[i]); 310 311 err = ynl_exec(ys, nlh, NULL); 312 if (err < 0) 313 return -1; 314 315 return 0; 316 } 317 318 static const struct ynl_ntf_info handshake_ntf_info[] = { 319 [HANDSHAKE_CMD_READY] = { 320 .alloc_sz = sizeof(struct handshake_accept_ntf), 321 .cb = handshake_accept_rsp_parse, 322 .policy = &handshake_accept_nest, 323 .free = (void *)handshake_accept_ntf_free, 324 }, 325 }; 326 327 const struct ynl_family ynl_handshake_family = { 328 .name = "handshake", 329 .ntf_info = handshake_ntf_info, 330 .ntf_info_size = MNL_ARRAY_SIZE(handshake_ntf_info), 331 }; 332