Whamcloud - gitweb
65bea40321df0e89f543bc5d04d55923fd204422
[fs/lustre-release.git] / lnet / utils / lnetconfig / liblnetconfig_netlink.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the GNU Lesser General Public License
8  * LGPL version 2.1 or (at your discretion) any later version.
9  * LGPL version 2.1 accompanies this distribution, and is available at
10  * http://www.gnu.org/licenses/lgpl-2.1.html
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * LGPL HEADER END
18  */
19 /**
20  * Netlink handling.
21  *
22  * Copyright (c) 2021  UT-Battelle, LLC
23  *
24  * Author: James Simmons <jsimmons@infradead.org>
25  */
26
27 #include <ctype.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <yaml.h>
31
32 #include <linux/lnet/lnet-nl.h>
33 #include "liblnetconfig.h"
34
35 #ifndef fallthrough
36 #define fallthrough do {} while (0)  /* fallthrough */
37 #endif
38
39 #ifndef SOL_NETLINK /* for glibc < 2.24 */
40 # define SOL_NETLINK 270
41 #endif
42
43 #ifndef NETLINK_EXT_ACK
44 #define NETLINK_EXT_ACK 11
45 #endif
46
47 #ifndef NLM_F_ACK_TLVS
48 #define NLM_F_ACK_TLVS  0x200   /* extended ACK TVLs were included */
49 #endif
50
51 #ifndef NLA_NUL_STRING
52 # define NLA_NUL_STRING 10
53 #endif
54
55 #ifndef NLA_S16
56 # define NLA_S16 13
57 #endif
58
59 #ifndef HAVE_NLA_GET_S32
60
61 #define NLA_S32 14
62
63 /**
64  * Return payload of 32 bit signed integer attribute.
65  *
66  * @arg nla             32 bit integer attribute.
67  *
68  * @return Payload as 32 bit integer.
69  */
70 int32_t nla_get_s32(const struct nlattr *nla)
71 {
72         return *(const int32_t *) nla_data(nla);
73 }
74 #endif /* ! HAVE_NLA_GET_S32 */
75
76 #ifndef HAVE_NLA_GET_S64
77
78 #define NLA_S64 15
79
80 /**
81  * Return payload of s64 attribute
82  *
83  * @arg nla     s64 netlink attribute
84  *
85  * @return Payload as 64 bit integer.
86  */
87 int64_t nla_get_s64(const struct nlattr *nla)
88 {
89         int64_t tmp = 0;
90
91         if (nla && nla_len(nla) >= sizeof(tmp))
92                 memcpy(&tmp, nla_data(nla), sizeof(tmp));
93
94         return tmp;
95 }
96
97 #define NLA_PUT_S64(msg, attrtype, value) \
98         NLA_PUT_TYPE(msg, int64_t, attrtype, value)
99
100 #endif /* ! HAVE_NLA_GET_S64 */
101
102 /**
103  * Set NETLINK_BROADCAST_ERROR flags on socket to report ENOBUFS errors.
104  *
105  * @sk          Socket to change the flags.
106  *
107  * Return       0 on success or a Netlink error code.
108  */
109 int nl_socket_enable_broadcast_error(struct nl_sock *sk)
110 {
111         const int state = 1; /* enable errors */
112         int err;
113
114         if (nl_socket_get_fd(sk) < 0)
115                 return -NLE_BAD_SOCK;
116
117         err = setsockopt(nl_socket_get_fd(sk), SOL_NETLINK,
118                          NETLINK_BROADCAST_ERROR, &state, sizeof(state));
119         if (err < 0)
120                 return -nl_syserr2nlerr(errno);
121
122         return 0;
123 }
124
125 /**
126  * Enable/disable extending ACK for netlink socket. Used for
127  * sending extra debugging information.
128  *
129  * @arg sk              Netlink socket.
130  * @arg state           New state (0 - disabled, 1 - enabled)
131  *
132  * @return 0 on success or a negative error code
133  */
134 int nl_socket_set_ext_ack(struct nl_sock *sk, int state)
135 {
136         int err;
137
138         if (nl_socket_get_fd(sk) < 0)
139                 return -NLE_BAD_SOCK;
140
141         err = setsockopt(nl_socket_get_fd(sk), SOL_NETLINK,
142                          NETLINK_EXT_ACK, &state, sizeof(state));
143         if (err < 0 && errno != ENOPROTOOPT)
144                 return -nl_syserr2nlerr(errno);
145
146         return 0;
147 }
148
149 /**
150  * Create a Netlink socket
151  *
152  * @sk                  The nl_sock which we used to handle the Netlink
153  *                      connection.
154  * @async_events        tell the Netlink socket this will receive asynchronous
155  *                      data
156  *
157  * Return               0 on success or a negative error code.
158  */
159 int lustre_netlink_register(struct nl_sock *sk, bool async_events)
160 {
161         int rc;
162
163         rc = genl_connect(sk);
164         if (rc < 0)
165                 return rc;
166
167         rc = nl_socket_enable_broadcast_error(sk);
168         if (rc < 0)
169                 return rc;
170
171         rc = nl_socket_set_ext_ack(sk, true);
172         if (rc < 0)
173                 return rc;
174
175         if (async_events) {
176                 /* Required to receive async netlink event notifications */
177                 nl_socket_disable_seq_check(sk);
178                 /* Don't need ACK for events generated by kernel */
179                 nl_socket_disable_auto_ack(sk);
180         }
181
182         return rc;
183 }
184
185 /**
186  * Filter Netlink socket by groups
187  *
188  * @nl          Netlink socket
189  * @family      The family name of the Netlink socket.
190  * @group       Netlink messages will only been sent if they belong to this
191  *              group
192  *
193  * Return       0 on success or a negative error code.
194  */
195 int lustre_netlink_add_group(struct nl_sock *nl, const char *family,
196                              const char *group)
197 {
198         int group_id;
199
200         /* Get group ID */
201         group_id = genl_ctrl_resolve_grp(nl, family, group);
202         if (group_id < 0)
203                 return group_id;
204
205         /* subscribe to generic netlink multicast group */
206         return nl_socket_add_membership(nl, group_id);
207 }
208
209 /* A YAML file is used to describe data. In a YAML document the content is
210  * all about a collection of scalars used to create new data types such as
211  * key-value pairs. This allows complex documents to represent anything from
212  * a string to a tree.
213  *
214  * Scalar:
215  * ---------
216  * YAML scalars are a simple value which can be a string, number or Boolean.
217  * They are the simplest data types. They can exist in a YAML document but
218  * are typically used to build more complex data formats.
219  *
220  * Collections:
221  * ------------
222  * In YAML collections are scalar elements presented in the form of
223  * an array, called a sequence, or mappings (hashes) that are scalar
224  * key value pairs. All elements belonging to the same collection are
225  * the lines that begin at the same indentation level
226  *
227  * Sequences use a dash followed by a space.
228  * Mappings use a colon followed by a space (: ) to mark each key/value pair:
229  *
230  * Collections can be represented in two forms, flow and block.
231  * Note they are equivalent. Example of block sequence is;
232  *
233  * - string
234  * - integer
235  * - boolean
236  *
237  * and a block mapping example is:
238  *
239  * string: hello
240  * integer: 5
241  * boolean: False
242  *
243  * YAML flow styles for collections uses explicit indicators rather than
244  * indentation to denote scope.
245  *
246  * A sequence can be written as a comma separated list within
247  * square brackets ([]):
248  *
249  * [ PHP, Perl, Python ]
250  *
251  * A mapping can be written as a comma separated list of key/values within
252  * curly braces ({}):
253  *
254  * { PHP: 5.2, MySQL: 5.1, Apache: 2.2.20 }
255  *
256  * NOTE!! flow and block are equivalent.
257  *
258  * List:
259  * ------
260  * A list is a defined array of data which can be either an flow or block
261  * sequence. Lists can be nested. Example
262  *
263  * numbers: [ 1, 2, 3, 4 ]
264  *
265  * numbers:
266  *  - 1
267  *  - 2
268  *  - 3
269  *  - 4
270  *
271  * Dictionaries:
272  * --------------
273  * Are comprised of a key: value format with contents indented. This is
274  * built on top of the flow or block mapping. Like lists they can be nested.
275  *
276  * ports:
277  * - port: 8080
278  *     targetPort: 8080
279  *       nodePort: 30012
280  */
281
282 /* In YAML you have the concept of parsers and emitters. Parser
283  * consume YAML input from a file, character buffer, or in our
284  * case Netlink and emitters take data from some source and
285  * present it in a YAML format.
286  *
287  * In this section of the code we are handling the parsing of the
288  * Netlink packets coming in and using them to piece together a
289  * YAML document. We could in theory just dump a YAML document
290  * one line at a time over Netlink but the amount of data could
291  * become very large and impact performance. Additionally, having
292  * pseudo-YAML code in the kernel would be frowned on. We can
293  * optimize the network traffic by taking advantage of the fact
294  * that for key/value pairs the keys rarely change. We can
295  * break up the data into keys and the values. The first Netlink
296  * data packets received will be a nested keys table which we
297  * can cache locally. As we receive the value pairs we can then
298  * reconstruct the key : value pair by looking up the the key
299  * in the stored table. In effect we end up with a one key to
300  * many values stream of data.
301  *
302  * The data structures below are used to create a tree data
303  * structure which is the natural flow of both YAML and
304  * Netlink.
305  */
306 struct yaml_nl_node {
307         struct nl_list_head     list;
308         struct nl_list_head     children;
309         struct ln_key_list      keys;
310 };
311
312 struct yaml_netlink_input {
313         yaml_parser_t           *parser;
314         void                    *buffer;
315         const char              *errmsg;
316         int                     error;
317         struct nl_sock          *nl;
318         bool                    complete;
319         bool                    async;
320         unsigned int            indent;
321         unsigned int            version;
322         struct yaml_nl_node     *cur;
323         struct yaml_nl_node     *root;
324 };
325
326 /* Sadly this is not exported out of libyaml. We want to
327  * give descent error message to help people track down
328  * issues. This is internal only to this code. The end
329  * user will never need to use this.
330  */
331 static int
332 yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
333                              size_t offset, int value)
334 {
335         parser->error = YAML_READER_ERROR;
336         parser->problem = problem;
337         parser->problem_offset = offset;
338         parser->problem_value = value;
339
340         return 0;
341 }
342
343 /* This is used to handle all the Netlink packets containing the keys
344  * for the key/value pairs. Instead of creating unique code to handle
345  * every type of Netlink attributes possible we create a generic
346  * abstract so the same code be used with everything. To make this
347  * work the key table trasmitted must report the tree structure and
348  * state of the keys. We use nested attributes as a way to notify libyaml
349  * we have a new collection. This is used to create the tree structure
350  * of the YAML document. Each collection of attributes define the following:
351  *
352  * LN_SCALAR_ATTR_INDEX:
353  *      enum XXX_ATTR that defines which value we are dealing with. This
354  *      varies greatly depending on the subsystem we have developed for.
355  *
356  * LN_SCALAR_ATTR_NLA_TYPE:
357  *      The Netlink attribute type (NLA_STRING, NLA_U32, etc..) the coming
358  *      value will be.
359  *
360  * LN_SCALAR_ATTR_VALUE:
361  *      The string represnting key's actually scalar value.
362  *
363  * LN_SCALAR_ATTR_INT_VALUE:
364  *      For this case the key is an integer value. This shouldn't be
365  *      sent for the receive case since we are going to just turn it
366  *      into a string for YAML. Sending packets will make use of this.
367  *
368  * LN_SCALAR_ATTR_KEY_TYPE:
369  *      What YAML format is it? block or flow. Only useful for
370  *      LN_SCALAR_ATTR_NLA_TYPE of type NLA_NESTED or NLA_NUL_STRING
371  *
372  * LN_SCALAR_ATTR_LIST + LN_SCALAR_LIST_SIZE:
373  *      Defined the next collection which is a collection of nested
374  *      attributes of the above.
375  */
376 static struct nla_policy scalar_attr_policy[LN_SCALAR_MAX + 1] = {
377         [LN_SCALAR_ATTR_LIST]           = { .type = NLA_NESTED },
378         [LN_SCALAR_ATTR_LIST_SIZE]      = { .type = NLA_U16 },
379         [LN_SCALAR_ATTR_INDEX]          = { .type = NLA_U16 },
380         [LN_SCALAR_ATTR_NLA_TYPE]       = { .type = NLA_U16 },
381         [LN_SCALAR_ATTR_VALUE]          = { .type = NLA_STRING },
382         [LN_SCALAR_ATTR_INT_VALUE]      = { .type = NLA_S64 },
383         [LN_SCALAR_ATTR_KEY_FORMAT]     = { .type = NLA_U16 },
384 };
385
386 static int yaml_parse_key_list(struct yaml_netlink_input *data,
387                                struct yaml_nl_node *parent,
388                                struct nlattr *list)
389 {
390         struct nlattr *tbl_info[LN_SCALAR_MAX + 1];
391         struct yaml_nl_node *node = NULL;
392         struct nlattr *attr;
393         int rem;
394
395         nla_for_each_nested(attr, list, rem) {
396                 uint16_t index = 0;
397
398                 if (nla_parse_nested(tbl_info, LN_SCALAR_MAX, attr,
399                                      scalar_attr_policy))
400                         break;
401
402                 if (tbl_info[LN_SCALAR_ATTR_LIST_SIZE]) {
403                         size_t cnt;
404
405                         cnt = nla_get_u16(tbl_info[LN_SCALAR_ATTR_LIST_SIZE]) + 1;
406                         if (!node) {
407                                 size_t len = sizeof(struct nl_list_head) * 2;
408
409                                 len += sizeof(struct ln_key_props) * cnt;
410                                 node = calloc(1, len);
411                                 if (!node)
412                                         return NL_STOP;
413
414                                 node->keys.lkl_maxattr = cnt;
415                                 NL_INIT_LIST_HEAD(&node->children);
416                                 nl_init_list_head(&node->list);
417
418                                 if (!data->root)
419                                         data->root = node;
420                                 if (!data->cur)
421                                         data->cur = node;
422                                 if (parent)
423                                         nl_list_add_tail(&node->list,
424                                                          &parent->children);
425                         }
426                 }
427
428                 if (tbl_info[LN_SCALAR_ATTR_INDEX])
429                         index = nla_get_u16(tbl_info[LN_SCALAR_ATTR_INDEX]);
430
431                 if (!node || index == 0)
432                         return NL_STOP;
433
434                 if (tbl_info[LN_SCALAR_ATTR_KEY_FORMAT]) {
435                         uint16_t format;
436
437                         format = nla_get_u16(tbl_info[LN_SCALAR_ATTR_KEY_FORMAT]);
438                         node->keys.lkl_list[index].lkp_key_format = format;
439                 }
440
441                 if (tbl_info[LN_SCALAR_ATTR_NLA_TYPE]) {
442                         uint16_t type;
443
444                         type = nla_get_u16(tbl_info[LN_SCALAR_ATTR_NLA_TYPE]);
445                         node->keys.lkl_list[index].lkp_data_type = type;
446                 }
447
448                 if (tbl_info[LN_SCALAR_ATTR_VALUE]) {
449                         char *name;
450
451                         name = nla_strdup(tbl_info[LN_SCALAR_ATTR_VALUE]);
452                         if (!name)
453                                 return NL_STOP;
454                         node->keys.lkl_list[index].lkp_value = name;
455                 }
456
457                 if (tbl_info[LN_SCALAR_ATTR_LIST]) {
458                         int rc = yaml_parse_key_list(data, node,
459                                                      tbl_info[LN_SCALAR_ATTR_LIST]);
460                         if (rc != NL_OK)
461                                 return rc;
462                 }
463         }
464         return NL_OK;
465 }
466
467 static struct yaml_nl_node *get_next_child(struct yaml_nl_node *node,
468                                            unsigned int idx)
469 {
470         struct yaml_nl_node *child;
471         unsigned int i = 0;
472
473         nl_list_for_each_entry(child, &node->children, list)
474                 if (idx == i++)
475                         return child;
476
477         return NULL;
478 }
479
480 /**
481  * In the YAML C implementation the scanner transforms the input stream
482  * (Netlink in this case) into a sequence of keys. First we need to
483  * examine the potential keys involved to see the mapping to Netlink.
484  * We have chosen to examine the YAML stack with keys since they are
485  * more detailed when compared to yaml_document_t / yaml_nodes and
486  * yaml_event_t.
487  *
488  *      STREAM-START(encoding)          # The stream start.
489  *      STREAM-END                      # The stream end.
490  *      VERSION-DIRECTIVE(major,minor)  # The '%YAML' directive.
491  *      TAG-DIRECTIVE(handle,prefix)    # The '%TAG' directive.
492  *      DOCUMENT-START                  # '---'
493  *      DOCUMENT-END                    # '...'
494  *      BLOCK-SEQUENCE-START            # Indentation increase denoting a block
495  *      BLOCK-MAPPING-START             # sequence or a block mapping.
496  *      BLOCK-END                       # Indentation decrease.
497  *      FLOW-SEQUENCE-START             # '['
498  *      FLOW-SEQUENCE-END               # ']'
499  *      FLOW-MAPPING-START              # '{'
500  *      FLOW-MAPPING-END                # '}'
501  *      BLOCK-ENTRY                     # '-'
502  *      FLOW-ENTRY                      # ','
503  *      KEY                             # '?' or nothing (simple keys).
504  *      VALUE                           # ':'
505  *      ALIAS(anchor)                   # '*anchor'
506  *      ANCHOR(anchor)                  # '&anchor'
507  *      TAG(handle,suffix)              # '!handle!suffix'
508  *      SCALAR(value,style)             # A scalar.
509  *
510  * For our read_handler / write_handler STREAM-START / STREAM-END,
511  * VERSION-DIRECTIVE, and TAG-DIRECTIVE are hanndler by the libyaml
512  * internal scanner so we don't need to deal with it. Normally for
513  * LNet / Lustre DOCUMENT-START / DOCUMENT-END are not needed but it
514  * could be easily handled. In the case of multiplex streams we could
515  * see these used to differentiate data coming in.
516  *
517  * It is here we handle any simple scalars or values of the key /value
518  * pair. How the YAML document is formated is dependent on the key
519  * table's data.
520  */
521 static void yaml_parse_value_list(struct yaml_netlink_input *data, int *size,
522                                   struct nlattr *attr_array[],
523                                   struct ln_key_props *parent)
524 {
525         struct yaml_nl_node *node = data->cur;
526         struct ln_key_props *keys = node->keys.lkl_list;
527         int mapping = parent->lkp_key_format;
528         int child_idx = 0, len = 0, i;
529
530         for (i = 1; i < node->keys.lkl_maxattr; i++) {
531                 struct nlattr *attr;
532
533                 attr = attr_array[i];
534                 if (!attr && !keys[i].lkp_value)
535                         continue;
536
537                 if (keys[i].lkp_data_type != NLA_NUL_STRING &&
538                     keys[i].lkp_data_type != NLA_NESTED) {
539                         if (!attr && keys[i].lkp_data_type != NLA_FLAG)
540                                 continue;
541
542                         if (!(mapping & LNKF_FLOW)) {
543                                 unsigned int indent = data->indent ?
544                                                       data->indent : 2;
545
546                                 memset(data->buffer, ' ', indent);
547                                 if (mapping & LNKF_SEQUENCE) {
548                                         ((char *)data->buffer)[indent - 2] = '-';
549                                         if (mapping & LNKF_MAPPING)
550                                                 mapping &= ~LNKF_SEQUENCE;
551                                 }
552                                 data->buffer += indent;
553                                 *size -= indent;
554                         }
555
556                         if (mapping & LNKF_MAPPING) {
557                                 len = snprintf(data->buffer, *size, "%s: ",
558                                                keys[i].lkp_value);
559                                 if (len < 0)
560                                         goto unwind;
561                                 data->buffer += len;
562                                 *size -= len;
563                         }
564                 }
565
566                 switch (keys[i].lkp_data_type) {
567                 case NLA_NESTED: {
568                         struct yaml_nl_node *next = get_next_child(node,
569                                                                    child_idx++);
570                         int num = next->keys.lkl_maxattr;
571                         struct nla_policy nest_policy[num];
572                         struct yaml_nl_node *old;
573                         struct nlattr *cnt_attr;
574                         int rem, j;
575
576                         if (!attr)
577                                 continue;
578
579                         memset(nest_policy, 0, sizeof(struct nla_policy) * num);
580                         for (j = 1; j < num; j++)
581                                 nest_policy[j].type = next->keys.lkl_list[j].lkp_data_type;
582
583                         old = data->cur;
584                         data->cur = next;
585                         nla_for_each_nested(cnt_attr, attr, rem) {
586                                 struct nlattr *nest_info[num];
587                                 uint16_t indent = 0;
588
589                                 if (nla_parse_nested(nest_info, num, cnt_attr,
590                                                      nest_policy))
591                                         break;
592
593                                 if (keys[i].lkp_key_format & LNKF_FLOW) {
594                                         char brace = '{';
595
596                                         if (keys[i].lkp_key_format &
597                                             LNKF_SEQUENCE)
598                                                 brace = '[';
599
600                                         len = snprintf(data->buffer, *size,
601                                                        "%*s%s: %c ",
602                                                        data->indent, "",
603                                                        keys[i].lkp_value,
604                                                        brace);
605                                 } else {
606                                         if (keys[i].lkp_key_format &
607                                             LNKF_MAPPING)
608                                                 indent += 2;
609                                         if (keys[i].lkp_key_format &
610                                             LNKF_SEQUENCE)
611                                                 indent += 2;
612
613                                         if (keys[i].lkp_value) {
614                                                 len = snprintf(data->buffer,
615                                                                *size,
616                                                                "%*s%s:\n",
617                                                                data->indent, "",
618                                                                keys[i].lkp_value);
619                                         } else {
620                                                 len = 0;
621                                         }
622                                 }
623                                 if (len < 0)
624                                         goto unwind;
625                                 data->buffer += len;
626                                 *size -= len;
627                                 len = 0;
628
629                                 data->indent += indent;
630                                 yaml_parse_value_list(data, size, nest_info,
631                                                       &keys[i]);
632                                 data->indent -= indent;
633
634                                 if (keys[i].lkp_key_format & LNKF_FLOW) {
635                                         char *tmp = (char *)data->buffer - 2;
636                                         char *brace = " }\n";
637
638                                         if (keys[i].lkp_key_format &
639                                             LNKF_SEQUENCE)
640                                                 brace = " ]\n";
641
642                                         memcpy(tmp, brace, strlen(brace));
643                                         data->buffer++;
644                                         *size -= 1;
645                                 }
646                         }
647                         data->cur = old;
648                         break;
649                 }
650
651                 case NLA_NUL_STRING:
652                         if (i == 1) {
653                                 if (data->cur != data->root)
654                                         goto not_first;
655
656                                 /* The top level is special so only print
657                                  * once
658                                  */
659                                 if (strlen(keys[i].lkp_value)) {
660                                         len = snprintf(data->buffer,
661                                                        *size, "%s:\n",
662                                                        keys[i].lkp_value);
663                                         if (len < 0)
664                                                 goto unwind;
665                                         data->buffer += len;
666                                         *size -= len;
667                                         len = 0;
668                                 }
669                                 data->indent = 0;
670                                 if (!(mapping & LNKF_FLOW)) {
671                                         if (mapping & LNKF_SEQUENCE)
672                                                 data->indent += 2;
673                                         else if (mapping & LNKF_MAPPING)
674                                                 data->indent += 2;
675                                 }
676 not_first:
677                                 if (attr && parent->lkp_value) {
678                                         free(parent->lkp_value);
679                                         parent->lkp_value = nla_strdup(attr);
680                                 }
681                         }
682                         break;
683
684                 case NLA_STRING:
685                         len = snprintf(data->buffer, *size, "%s",
686                                        nla_get_string(attr));
687                         break;
688
689                 case NLA_FLAG:
690                         len = snprintf(data->buffer, *size, "%s",
691                                        attr ? "true" : "false");
692                         break;
693
694                 case NLA_U16:
695                         len = snprintf(data->buffer, *size, "%hu",
696                                        nla_get_u16(attr));
697                         break;
698
699                 case NLA_U32:
700                         len = snprintf(data->buffer, *size, "%u",
701                                        nla_get_u32(attr));
702                         break;
703
704                 case NLA_U64:
705                         len = snprintf(data->buffer, *size, "%ju",
706                                        nla_get_u64(attr));
707                         break;
708
709                 case NLA_S16:
710                         len = snprintf(data->buffer, *size, "%hd",
711                                        nla_get_u16(attr));
712                         break;
713
714                 case NLA_S32:
715                         len = snprintf(data->buffer, *size, "%d",
716                                        nla_get_s32(attr));
717                         break;
718
719                 case NLA_S64:
720                         len = snprintf(data->buffer, *size, "%jd",
721                                        nla_get_s64(attr));
722                         fallthrough;
723                 default:
724                         break;
725                 }
726
727                 if (len) {
728                         if (mapping & LNKF_FLOW) {
729                                 strcat((char *)data->buffer, ", ");
730                                 len += 2;
731                         } else {
732                                 if ((mapping == LNKF_SEQUENCE) &&
733                                     !keys[i].lkp_value)
734                                         ((char *)data->buffer)[len++] = ':';
735
736                                 ((char *)data->buffer)[len++] = '\n';
737                         }
738                         data->buffer += len;
739                         *size += len;
740                 } else if (len < 0) {
741 unwind:
742                         data->buffer -= data->indent + 2;
743                         *size -= data->indent + 2;
744                 }
745         }
746 }
747
748 /* This is the CB_VALID callback for the Netlink library that we
749  * have hooked into. Any successful Netlink message is passed to
750  * this function which handles both the incoming key tables and
751  * the values of the key/value pairs being received. We use
752  * the NLM_F_CREATE flag to determine if the incoming Netlink
753  * message is a key table or a packet containing value pairs.
754  */
755 static int yaml_netlink_msg_parse(struct nl_msg *msg, void *arg)
756 {
757         struct yaml_netlink_input *data = arg;
758         struct nlmsghdr *nlh = nlmsg_hdr(msg);
759
760         if (nlh->nlmsg_flags & NLM_F_CREATE) {
761                 struct genlmsghdr *ghdr = genlmsg_hdr(nlh);
762                 struct nlattr *attrs[LN_SCALAR_MAX + 1];
763
764                 if (genlmsg_parse(nlh, 0, attrs, LN_SCALAR_MAX,
765                                   scalar_attr_policy))
766                         return NL_SKIP;
767
768                 if (attrs[LN_SCALAR_ATTR_LIST]) {
769                         int rc = yaml_parse_key_list(data, NULL,
770                                                      attrs[LN_SCALAR_ATTR_LIST]);
771                         if (rc != NL_OK)
772                                 return rc;
773
774                         /* reset to root node */
775                         data->cur = data->root;
776                 }
777
778                 /* For streaming insert '---' to define start of
779                  * YAML document. This allows use to extract
780                  * documents out of a multiplexed stream.
781                  */
782                 if (data->async) {
783                         char *start_doc = "---\n";
784                         size_t len = strlen(start_doc) + 1;
785
786                         strncpy(data->buffer, start_doc, len);
787                         data->buffer += len - 1;
788                 }
789                 data->version = ghdr->version;
790         } else {
791                 uint16_t maxtype = data->cur->keys.lkl_maxattr;
792                 struct nla_policy policy[maxtype];
793                 struct nlattr *attrs[maxtype];
794                 int size, i;
795
796                 memset(policy, 0, sizeof(struct nla_policy) * maxtype);
797                 for (i = 1; i < maxtype; i++)
798                         policy[i].type = data->cur->keys.lkl_list[i].lkp_data_type;
799
800                 if (genlmsg_parse(nlh, 0, attrs, maxtype, policy))
801                         return NL_SKIP;
802
803                 size = data->parser->raw_buffer.end -
804                        (unsigned char *)data->buffer;
805                 yaml_parse_value_list(data, &size, attrs,
806                                       &data->cur->keys.lkl_list[1]);
807         }
808
809         /* Let yaml_netlink_msg_complete end collecting data */
810         return NL_OK;
811 }
812
813 /* This is the libnl callback for when an error has happened
814  * kernel side. An error message is sent back to the user.
815  */
816 static int yaml_netlink_msg_error(struct sockaddr_nl *who,
817                                   struct nlmsgerr *errmsg, void *arg)
818 {
819         struct nlmsghdr *nlh = (void *)errmsg - NLMSG_HDRLEN;
820         struct yaml_netlink_input *data = arg;
821
822         if ((nlh->nlmsg_type == NLMSG_ERROR ||
823              nlh->nlmsg_flags & NLM_F_ACK_TLVS) && errmsg->error) {
824                 /* libyaml stomps on the reader error so we need to
825                  * cache the source of the error.
826                  */
827                 const char *errstr = nl_geterror(nl_syserr2nlerr(errmsg->error));
828
829 #ifdef HAVE_USRSPC_NLMSGERR
830                 /* Newer kernels support NLM_F_ACK_TLVS in nlmsg_flags
831                  * which gives greater detail why we failed.
832                  */
833                 if ((nlh->nlmsg_flags & NLM_F_ACK_TLVS) &&
834                     !(nlh->nlmsg_flags & NLM_F_CAPPED)) {
835                         struct nlattr *head = ((void *)&errmsg->msg);
836                         struct nlattr *tb[NLMSGERR_ATTR_MAX];
837
838                         if (nla_parse(tb, NLMSGERR_ATTR_MAX, head,
839                                       nlmsg_attrlen(nlh, 0), NULL) == 0) {
840                                 if (tb[NLMSGERR_ATTR_MSG])
841                                         errstr = nla_strdup(tb[NLMSGERR_ATTR_MSG]);
842                         }
843                 }
844 #endif /* HAVE_USRSPC_NLMSGERR */
845                 data->errmsg = errstr;
846                 data->error = errmsg->error;
847                 data->parser->error = YAML_READER_ERROR;
848                 data->complete = true;
849         }
850         return NL_STOP;
851 }
852
853 static bool cleanup_children(struct yaml_nl_node *parent)
854 {
855         struct yaml_nl_node *child;
856
857         if (nl_list_empty(&parent->children)) {
858                 struct ln_key_props *keys = parent->keys.lkl_list;
859                 int i;
860
861                 for (i = 1; i < parent->keys.lkl_maxattr; i++)
862                         if (keys[i].lkp_value)
863                                 free(keys[i].lkp_value);
864                 nl_list_del(&parent->list);
865                 return true;
866         }
867
868         while ((child = get_next_child(parent, 0)) != NULL) {
869                 if (cleanup_children(child))
870                         free(child);
871         }
872
873         return false;
874 }
875
876 /* This is the libnl callback for when the last Netlink packet
877  * is finished being parsed or its called right away in case
878  * the Linux kernel reports back an error from the Netlink layer.
879  */
880 static int yaml_netlink_msg_complete(struct nl_msg *msg, void *arg)
881 {
882         struct yaml_netlink_input *data = arg;
883         struct nlmsghdr *nlh = nlmsg_hdr(msg);
884
885         /* For the case of NLM_F_DUMP the kernel will send error msgs
886          * yet not be labled NLMSG_ERROR which results in this code
887          * path being executed.
888          */
889         yaml_netlink_msg_error(NULL, nlmsg_data(nlh), arg);
890         if (data->parser->error == YAML_READER_ERROR)
891                 return NL_STOP;
892
893         /* Free internal data. */
894         if (data->root) {
895                 cleanup_children(data->root);
896                 free(data->root);
897                 data->root = NULL;
898         }
899
900         /* For streaming insert '...' to define end of
901          * YAML document
902          */
903         if (data->async) {
904                 char *end_doc = "...\n";
905                 size_t len = strlen(end_doc) + 1;
906
907                 strncpy(data->buffer, end_doc, len);
908                 data->buffer += len - 1;
909         } else {
910                 data->complete = true;
911         }
912
913         return data->async ? NL_OK : NL_STOP;
914 }
915
916 /**
917  * In order for yaml_parser_set_input_netlink() to work we have to
918  * register a yaml_read_handler_t callback. This is that call back
919  * which listens for Netlink packets. Internally nl_recvmsg_report()
920  * calls the various callbacks discussed above.
921  */
922 static int yaml_netlink_read_handler(void *arg, unsigned char *buffer,
923                                      size_t size, size_t *size_read)
924 {
925         struct yaml_netlink_input *data = arg;
926         struct nl_sock *nl = data->nl;
927         struct nl_cb *cb;
928         int rc = 0;
929
930         if (data->complete) {
931                 *size_read = 0;
932                 return 1;
933         }
934
935         data->buffer = buffer;
936
937         cb = nl_socket_get_cb(nl);
938         rc = nl_recvmsgs_report(nl, cb);
939         if (rc == -NLE_INTR) {
940                 *size_read = 0;
941                 return 1;
942         } else if (!data->errmsg && rc < 0) {
943                 data->errmsg = nl_geterror(rc);
944                 return 0;
945         } else if (data->parser->error) {
946                 /* data->errmsg is set in NL_CB_FINISH */
947                 return 0;
948         }
949
950         rc = (unsigned char *)data->buffer - buffer;
951         if ((int)size > rc)
952                 size = rc;
953
954         *size_read = size;
955         return 1;
956 }
957
958 /* libyaml by default just reports "input error" for parser read_handler_t
959  * issues which is not useful. This provides away to get better debugging
960  * info.
961  */
962 YAML_DECLARE(const char *)
963 yaml_parser_get_reader_error(yaml_parser_t *parser)
964 {
965         struct yaml_netlink_input *buf = parser->read_handler_data;
966
967         if (!buf)
968                 return NULL;
969
970         errno = buf->error;
971         return buf->errmsg;
972 }
973
974 YAML_DECLARE(int)
975 yaml_parser_get_reader_proto_version(yaml_parser_t *parser)
976 {
977         struct yaml_netlink_input *buf = parser->read_handler_data;
978
979         if (!buf)
980                 return 0;
981
982         return buf->version;
983 }
984
985 /* yaml_parser_set_input_netlink() mirrors the libyaml function
986  * yaml_parser_set_input_file(). Internally it does setup of the
987  * libnl socket callbacks to parse the Netlink messages received
988  * as well as register the special yaml_read_handler_t for libyaml.
989  * This is exposed for public use.
990  */
991 YAML_DECLARE(int)
992 yaml_parser_set_input_netlink(yaml_parser_t *reply, struct nl_sock *nl,
993                               bool stream)
994 {
995         struct yaml_netlink_input *buf;
996         int rc;
997
998         buf = calloc(1, sizeof(*buf));
999         if (!buf) {
1000                 reply->error = YAML_MEMORY_ERROR;
1001                 return false;
1002         }
1003
1004         rc = lustre_netlink_register(nl, stream);
1005         if (rc < 0) {
1006                 yaml_parser_set_reader_error(reply,
1007                                              "netlink setup failed", 0,
1008                                              -rc);
1009                 goto failed;
1010         }
1011
1012         buf->nl = nl;
1013         buf->async = stream;
1014         buf->parser = reply;
1015         yaml_parser_set_input(buf->parser, yaml_netlink_read_handler, buf);
1016
1017         rc = nl_socket_modify_cb(buf->nl, NL_CB_VALID, NL_CB_CUSTOM,
1018                                  yaml_netlink_msg_parse, buf);
1019         if (rc < 0) {
1020                 yaml_parser_set_reader_error(reply,
1021                                              "netlink msg recv setup failed",
1022                                              0, -rc);
1023                 goto failed;
1024         }
1025
1026         rc = nl_socket_modify_cb(buf->nl, NL_CB_FINISH, NL_CB_CUSTOM,
1027                                  yaml_netlink_msg_complete, buf);
1028         if (rc < 0) {
1029                 yaml_parser_set_reader_error(reply,
1030                                              "netlink msg cleanup setup failed",
1031                                              0, -rc);
1032                 goto failed;
1033         }
1034
1035         rc = nl_socket_modify_err_cb(nl, NL_CB_CUSTOM, yaml_netlink_msg_error,
1036                                      buf);
1037         if (rc < 0) {
1038                 yaml_parser_set_reader_error(reply,
1039                                              "failed to register error handling",
1040                                              0, -rc);
1041 failed:
1042                 free(buf);
1043         }
1044
1045         return rc < 0 ? false : true;
1046 }
1047
1048 /* The role of the YAML emitter for us is to take a YAML document and
1049  * change into a Netlink stream to send to the kernel to be processed.
1050  * This provides the infrastructure to do this.
1051  */
1052 struct yaml_netlink_output {
1053         yaml_emitter_t          *emitter;
1054         struct nl_sock          *nl;
1055         char                    *family;
1056         int                     family_id;
1057         int                     version;
1058         int                     cmd;
1059         int                     pid;
1060         int                     flags;
1061 };
1062
1063 /* Internal use for this file only. We fill in details of why creating
1064  * a Netlink packet to send failed. The end user will be able to debug
1065  * what went wrong.
1066  */
1067 static int
1068 yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
1069 {
1070         emitter->error = YAML_WRITER_ERROR;
1071         emitter->problem = problem;
1072
1073         return 0;
1074 }
1075
1076 static unsigned int indent_level(const char *str)
1077 {
1078         char *tmp = (char *)str;
1079
1080         while (isspace(*tmp))
1081                 ++tmp;
1082         return tmp - str;
1083 }
1084
1085 #define LNKF_END 8
1086
1087 static enum lnet_nl_key_format yaml_format_type(yaml_emitter_t *emitter,
1088                                                 char *line,
1089                                                 unsigned int *offset)
1090 {
1091         unsigned int indent = *offset, new_indent = 0;
1092         enum lnet_nl_key_format fmt = 0;
1093         char *tmp, *flow;
1094
1095         new_indent = indent_level(line);
1096         if (new_indent < indent) {
1097                 *offset = indent - emitter->best_indent;
1098                 return LNKF_END;
1099         }
1100
1101         if (strncmp(line + new_indent, "- ", 2) == 0) {
1102                 memset(line + new_indent, ' ', 2);
1103                 new_indent += 2;
1104         }
1105
1106         /* hdr: [ a : 1, b : 2, c : 3 ] */
1107         tmp = strstr(line + new_indent, ": ");
1108         if (!tmp)
1109                 tmp = line + new_indent;
1110         else
1111                 fmt |= LNKF_MAPPING;
1112
1113         flow = strchr(line + new_indent, '{');
1114         if (!flow)
1115                 flow = strchr(line + new_indent, '[');
1116         if (flow) {
1117                 if (flow < tmp)
1118                         fmt &= ~LNKF_MAPPING;
1119                 fmt |= LNKF_FLOW;
1120         } else if (strchr(tmp, '}') || strchr(tmp, ']')) {
1121                 if (strchr(tmp, ']'))
1122                         fmt &= ~LNKF_MAPPING;
1123                 fmt |= LNKF_FLOW;
1124         }
1125
1126         if (indent != new_indent) {
1127                 *offset = new_indent;
1128                 fmt |= LNKF_SEQUENCE;
1129         }
1130
1131         return fmt;
1132 }
1133
1134 static int yaml_fill_scalar_data(struct nl_msg *msg,
1135                                  enum lnet_nl_key_format fmt,
1136                                  char *line)
1137 {
1138         char *sep = strstr(line, ": "); /* handle mappings */
1139         int rc = 0;
1140         long num;
1141
1142         if (!sep) {
1143                 char *tmp = strchr(line, ':');
1144
1145                 if (tmp && strlen(tmp) == 1) /* handle simple scalar */
1146                         sep = tmp;
1147         }
1148         if (sep)
1149                 *sep++ = '\0';
1150
1151         if (strspn(line, "-0123456789") == strlen(line)) {
1152                 num = strtoll(line, NULL, 0);
1153
1154                 NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1155         } else {
1156                 NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, line);
1157         }
1158
1159         if (fmt & LNKF_FLOW) {
1160                 memset(line, ' ', strlen(line) + 1);
1161                 goto nla_put_failure;
1162         }
1163
1164         if (fmt & LNKF_MAPPING && sep) {
1165                 while (isspace(*sep))
1166                         ++sep;
1167
1168                 if (!strlen(sep))
1169                         goto nla_put_failure;
1170
1171                 if (strspn(sep, "-0123456789") == strlen(sep)) {
1172                         num = strtoll(sep, NULL, 0);
1173                         NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1174                 } else {
1175                         NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, sep);
1176                 }
1177         }
1178 nla_put_failure:
1179         return rc;
1180 }
1181
1182 static int yaml_create_nested_list(struct yaml_netlink_output *out,
1183                                    struct nl_msg *msg, char **hdr,
1184                                    char **entry, unsigned int *indent,
1185                                    enum lnet_nl_key_format fmt)
1186 {
1187         bool nested = fmt & LNKF_SEQUENCE;
1188         struct nlattr *list = NULL;
1189         char *line;
1190         int rc = 0;
1191
1192         /* Not needed for FLOW only case */
1193         if (nested) {
1194                 list = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1195                 if (!list) {
1196                         yaml_emitter_set_writer_error(out->emitter,
1197                                                       "Emmitter netlink list creation failed");
1198                         rc = -EINVAL;
1199                         goto nla_put_failure;
1200                 }
1201         }
1202
1203         if (fmt != LNKF_FLOW) {
1204                 rc = yaml_fill_scalar_data(msg, fmt, *hdr + *indent);
1205                 if (rc < 0)
1206                         goto nla_put_failure;
1207         }
1208
1209         if (fmt & LNKF_FLOW) {
1210                 char *tmp = strchr(*hdr, '{'), *split = NULL;
1211                 bool format = false;
1212
1213                 if (!tmp) {
1214                         tmp = strchr(*hdr, '[');
1215                         if (!tmp) {
1216                                 yaml_emitter_set_writer_error(out->emitter,
1217                                                               "Emmitter flow format invalid");
1218                                 rc = -EINVAL;
1219                                 goto nla_put_failure;
1220                         }
1221                         fmt |= LNKF_SEQUENCE;
1222                 } else
1223                         fmt |= LNKF_MAPPING;
1224                 *tmp = ' ';
1225
1226                 list = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1227                 if (!list) {
1228                         yaml_emitter_set_writer_error(out->emitter,
1229                                                       "Emmitter netlink list creation failed");
1230                         rc = -EINVAL;
1231                         goto nla_put_failure;
1232                 }
1233
1234                 fmt &= ~LNKF_FLOW;
1235                 while ((line = strsep(hdr, ",")) != NULL) {
1236                         while (!isalnum(line[0]))
1237                                 line++;
1238
1239                         /* Flow can be splt across lines by libyaml library. */
1240                         if (strchr(line, ',')) {
1241                                 split = line;
1242                                 *hdr = line;
1243                                 continue;
1244                         }
1245
1246                         tmp = strchr(line, '}');
1247                         if (!tmp)
1248                                 tmp = strchr(line, ']');
1249                         if (tmp) {
1250                                 format = true;
1251                                 *tmp = '\0';
1252                         }
1253
1254                         rc = yaml_fill_scalar_data(msg, fmt, line);
1255                         if (rc < 0)
1256                                 goto nla_put_failure;
1257
1258                         /* Move to next YAML line */
1259                         if (format) {
1260                                 if (!split)
1261                                         line = *entry;
1262                                 else
1263                                         *entry = NULL;
1264                                 break;
1265                         }
1266                 }
1267
1268                 if (!format) {
1269                         yaml_emitter_set_writer_error(out->emitter,
1270                                                       "Emmitter flow format invalid");
1271                         rc = -EINVAL;
1272                         goto nla_put_failure;
1273                 }
1274
1275                 if (line && line[0] == '-')
1276                         *indent = 0;
1277
1278                 nla_nest_end(msg, list);
1279         } else {
1280                 do {
1281                         line = strsep(entry, "\n");
1282 have_next_line:
1283                         if (!line || !strlen(line) || strcmp(line, "...") == 0)
1284                                 break;
1285
1286                         fmt = yaml_format_type(out->emitter, line, indent);
1287                         if (fmt == LNKF_END)
1288                                 break;
1289
1290                         if (fmt & ~LNKF_MAPPING) { /* Filter out mappings */
1291                                 rc = yaml_create_nested_list(out, msg, &line,
1292                                                              entry, indent,
1293                                                              fmt);
1294                                 if (rc < 0)
1295                                         goto nla_put_failure;
1296                                 if (line)
1297                                         goto have_next_line;
1298                         } else {
1299                                 rc = yaml_fill_scalar_data(msg, fmt,
1300                                                            line + *indent);
1301                                 if (rc < 0)
1302                                         goto nla_put_failure;
1303                         }
1304                 } while (strcmp(*entry, ""));
1305
1306                 if (line && line[*indent] == '-') {
1307                         line[*indent] = ' ';
1308                         *indent += 2;
1309                         goto have_next_line;
1310                 }
1311                 if (*entry && !strlen(*entry))
1312                         line = NULL;
1313                 /* strsep in the above loop moves entry to a value pass the
1314                  * end of the nested list. So to avoid losing this value we
1315                  * replace hdr with line.
1316                  */
1317                 *hdr = line;
1318         }
1319
1320         if (nested)
1321                 nla_nest_end(msg, list);
1322 nla_put_failure:
1323         return rc;
1324 }
1325
1326 /* YAML allows ' and " in its documents but those characters really
1327  * confuse libc string handling. The workaround is to replace
1328  * ' and " with another reserved character for YAML '%' which is
1329  * for tags which shouldn't matter if we send in a Netlink packet.
1330  * The kernel side will need to handle % in a special way.
1331  */
1332 static void yaml_quotation_handling(char *buf)
1333 {
1334         char *tmp = buf, *line;
1335
1336         line = strstr(tmp, "! \'");
1337         if (line)
1338                 line[0] = ' ';
1339
1340         while ((line = strchr(tmp, '\"')) != NULL) {
1341                 line[0] = ' ';
1342                 tmp = strchr(line, '\"');
1343                 tmp[0] = ' ';
1344         }
1345
1346         while ((line = strchr(tmp, '\'')) != NULL) {
1347                 line[0] = ' ';
1348                 tmp = strchr(line, '\'');
1349                 tmp[0] = ' ';
1350         }
1351 }
1352
1353 /* libyaml takes the YAML documents and places the data into an
1354  * internal buffer to the library. We take each line and turn it
1355  * into a Netlink message using the same format as the key table.
1356  * The reason for this approach is that we can do filters at the
1357  * key level or the key + value level.
1358  */
1359 static int yaml_netlink_write_handler(void *data, unsigned char *buffer,
1360                                       size_t size)
1361 {
1362         struct yaml_netlink_output *out = data;
1363         char *buf = strndup((char *)buffer, size);
1364         char *entry = buf, *tmp = buf, *line;
1365         enum lnet_nl_key_format fmt = 0;
1366         struct nl_msg *msg = NULL;
1367         unsigned int indent = 0;
1368         bool nogroups = true;
1369         int rc = 0;
1370
1371         yaml_quotation_handling(entry);
1372
1373         while (entry && strcmp(line = strsep(&entry, "\n"), "")) {
1374 already_have_line:
1375                 if (strcmp(line, "---") == 0 || strcmp(line, "...") == 0)
1376                         continue;
1377
1378                 /* In theory we could have a sequence of groups but a bug in
1379                  * libyaml prevents this from happing
1380                  */
1381                 if (line[0] != ' ' && line[0] != '-') {
1382                         bool extra = false;
1383
1384                         if (strchr(line, '{') || strchr(line, '['))
1385                                 extra = true;
1386
1387                         tmp = strchr(line, ':');
1388                         if (!tmp)
1389                                 continue;
1390                         *tmp = '\0';
1391
1392                         rc = lustre_netlink_add_group(out->nl, out->family,
1393                                                       line);
1394                         if (rc < 0) {
1395                                 yaml_emitter_set_writer_error(out->emitter,
1396                                                               "Netlink group does not exist");
1397                                 goto nla_put_failure;
1398                         }
1399                         nogroups = false;
1400                         /* Handle case first line contains more than a
1401                          * simple key
1402                          */
1403                         if (extra) {
1404                                 *tmp = ' ';
1405                                 line = tmp;
1406                                 goto already_have_line;
1407                         }
1408                 } else {
1409                         if (!msg) {
1410                                 void *usr_hdr;
1411
1412                                 msg = nlmsg_alloc();
1413                                 if (!msg) {
1414                                         out->emitter->error = YAML_MEMORY_ERROR;
1415                                         goto nla_put_failure;
1416                                 }
1417
1418                                 usr_hdr = genlmsg_put(msg, out->pid,
1419                                                       NL_AUTO_SEQ,
1420                                                       out->family_id, 0,
1421                                                       out->flags, out->cmd,
1422                                                       out->version);
1423                                 if (!usr_hdr) {
1424                                         out->emitter->error = YAML_MEMORY_ERROR;
1425                                         nlmsg_free(msg);
1426                                         goto nla_put_failure;
1427                                 }
1428
1429                                 if (line[0] != '-')
1430                                         indent = 2;
1431                         }
1432
1433                         fmt = yaml_format_type(out->emitter, line, &indent);
1434                         if (fmt & ~LNKF_MAPPING) {
1435                                 rc = yaml_create_nested_list(out, msg, &line,
1436                                                              &entry, &indent,
1437                                                              fmt);
1438                                 if (rc < 0) {
1439                                         yaml_emitter_set_writer_error(out->emitter,
1440                                                                       nl_geterror(rc));
1441                                         nlmsg_free(msg);
1442                                         goto nla_put_failure;
1443                                 }
1444                                 /* yaml_create_nested_list set line to the next
1445                                  * entry. We can just add it to the msg directly.
1446                                  */
1447                                 if (line)
1448                                         goto already_have_line;
1449                         } else {
1450                                 rc = yaml_fill_scalar_data(msg, fmt,
1451                                                            line + indent);
1452                                 if (rc < 0) {
1453                                         yaml_emitter_set_writer_error(out->emitter,
1454                                                                       nl_geterror(rc));
1455                                         nlmsg_free(msg);
1456                                         goto nla_put_failure;
1457                                 }
1458                         }
1459                 }
1460         }
1461
1462         /* Don't success if no valid groups found */
1463         if (nogroups) {
1464                 yaml_emitter_set_writer_error(out->emitter,
1465                                               "Emitter contains no valid Netlink groups");
1466                 goto nla_put_failure;
1467         }
1468
1469         if (msg) {
1470                 rc = nl_send_auto(out->nl, msg);
1471                 nlmsg_free(msg);
1472         } else {
1473                 rc = genl_send_simple(out->nl, out->family_id, out->cmd,
1474                                       out->version, out->flags);
1475         }
1476         if (rc < 0)
1477                 yaml_emitter_set_writer_error(out->emitter,
1478                                               nl_geterror(rc));
1479 nla_put_failure:
1480         free(buf);
1481         return out->emitter->error == YAML_NO_ERROR ? 1 : 0;
1482 }
1483
1484 /* This function is used by external utilities to use Netlink with
1485  * libyaml so we can turn YAML documentations into Netlink message
1486  * to send. This behavior mirrors yaml_emitter_set_output_file()
1487  * which is used to write out a YAML document to a file.
1488  */
1489 YAML_DECLARE(int)
1490 yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
1491                                 char *family, int version, int cmd, int flags)
1492 {
1493         struct yaml_netlink_output *out;
1494
1495         out = calloc(1, sizeof(*out));
1496         if (!out) {
1497                 sender->error = YAML_MEMORY_ERROR;
1498                 return false;
1499         }
1500
1501         /* Get family ID */
1502         out->family_id = genl_ctrl_resolve(nl, family);
1503         if (out->family_id < 0) {
1504                 yaml_emitter_set_writer_error(sender,
1505                                               "failed to resolve Netlink family id");
1506                 free(out);
1507                 return false;
1508         }
1509
1510         out->emitter = sender;
1511         out->nl = nl;
1512         out->family = family;
1513         out->version = version;
1514         out->cmd = cmd;
1515         out->flags = flags;
1516         out->pid = nl_socket_get_local_port(nl);
1517         yaml_emitter_set_output(sender, yaml_netlink_write_handler, out);
1518         return true;
1519 }
1520
1521 /* Error handling helpers */
1522 void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log)
1523 {
1524         /* YAML_WRITER_ERROR means no Netlink support so use old API */
1525         switch (emitter->error) {
1526         case YAML_MEMORY_ERROR:
1527                 fprintf(log, "Memory error: Not enough memory for emitting\n");
1528                         break;
1529         case YAML_WRITER_ERROR:
1530                 fprintf(log, "Writer error: %s\n", emitter->problem);
1531                 break;
1532         case YAML_EMITTER_ERROR:
1533                 fprintf(log, "Emitter error: %s\n", emitter->problem);
1534         default:
1535                 break;
1536         }
1537 }
1538
1539 void yaml_parser_log_error(yaml_parser_t *parser, FILE *log, const char *errmsg)
1540 {
1541         const char *extra;
1542
1543         switch (parser->error) {
1544         case YAML_MEMORY_ERROR:
1545                 fprintf(log, "Memory error: Not enough memory for parser\n");
1546                 break;
1547
1548         case YAML_SCANNER_ERROR:
1549         case YAML_PARSER_ERROR:
1550                 if (parser->context) {
1551                         fprintf(log,
1552                                 "%s error: %s at line %d, column %d\n%s at line %d, column %d\n",
1553                                 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1554                                 parser->context,
1555                                 (int)parser->context_mark.line + 1,
1556                                 (int)parser->context_mark.column + 1,
1557                                 parser->problem,
1558                                 (int)parser->problem_mark.line + 1,
1559                                 (int)parser->problem_mark.column + 1);
1560                 } else {
1561                         fprintf(log, "%s error: %s at line %d, column %d\n",
1562                                 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1563                                 parser->problem,
1564                                 (int)parser->problem_mark.line + 1,
1565                                 (int)parser->problem_mark.column + 1);
1566                 }
1567                 break;
1568
1569         case YAML_READER_ERROR:
1570                 extra = yaml_parser_get_reader_error(parser);
1571                 if (!extra)
1572                         extra = parser->problem;
1573
1574                 if (parser->problem_value != -1) {
1575                         fprintf(log, "Reader error: '%s':#%X at %ld'\n",
1576                                 extra, parser->problem_value,
1577                                 (long)parser->problem_offset);
1578                 } else {
1579                         fprintf(log, "Reader error: '%s' at %ld\n",
1580                                 extra, (long)parser->problem_offset);
1581                 }
1582                 fallthrough;
1583         default:
1584                 break;
1585         }
1586 }