Whamcloud - gitweb
LU-10003 lnet: use Netlink to support LNet ping commands
[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                         uint16_t indent = 0;
575                         int rem, j;
576
577                         if (!attr)
578                                 continue;
579
580                         memset(nest_policy, 0, sizeof(struct nla_policy) * num);
581                         for (j = 1; j < num; j++)
582                                 nest_policy[j].type = next->keys.lkl_list[j].lkp_data_type;
583
584                         if (keys[i].lkp_key_format & LNKF_FLOW) {
585                                 char brace = '{';
586
587                                 if (keys[i].lkp_key_format &
588                                     LNKF_SEQUENCE)
589                                         brace = '[';
590                                 len = snprintf(data->buffer, *size,
591                                                "%*s%s: %c ",
592                                                data->indent, "",
593                                                keys[i].lkp_value,
594                                                brace);
595                         } else {
596                                 if (keys[i].lkp_key_format &
597                                     LNKF_MAPPING)
598                                         indent += 2;
599                                 if (keys[i].lkp_key_format &
600                                     LNKF_SEQUENCE)
601                                         indent += 2;
602
603                                 if (keys[i].lkp_value) {
604                                         len = snprintf(data->buffer,
605                                                        *size,
606                                                        "%*s%s:\n",
607                                                        data->indent, "",
608                                                        keys[i].lkp_value);
609                                 } else {
610                                         len = 0;
611                                 }
612                         }
613                         if (len < 0)
614                                 goto unwind;
615                         data->buffer += len;
616                         *size -= len;
617                         len = 0;
618
619                         old = data->cur;
620                         data->cur = next;
621                         nla_for_each_nested(cnt_attr, attr, rem) {
622                                 struct nlattr *nest_info[num];
623
624                                 if (nla_parse_nested(nest_info, num, cnt_attr,
625                                                      nest_policy))
626                                         break;
627
628                                 data->indent += indent;
629                                 yaml_parse_value_list(data, size, nest_info,
630                                                       &keys[i]);
631                                 data->indent -= indent;
632                         }
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                         data->cur = old;
647                         break;
648                 }
649
650                 case NLA_NUL_STRING:
651                         if (i == 1) {
652                                 if (data->cur != data->root)
653                                         goto not_first;
654
655                                 /* The top level is special so only print
656                                  * once
657                                  */
658                                 if (strlen(keys[i].lkp_value)) {
659                                         len = snprintf(data->buffer,
660                                                        *size, "%s:\n",
661                                                        keys[i].lkp_value);
662                                         if (len < 0)
663                                                 goto unwind;
664                                         data->buffer += len;
665                                         *size -= len;
666                                         len = 0;
667                                 }
668                                 data->indent = 0;
669                                 if (!(mapping & LNKF_FLOW)) {
670                                         if (mapping & LNKF_SEQUENCE)
671                                                 data->indent += 2;
672                                         else if (mapping & LNKF_MAPPING)
673                                                 data->indent += 2;
674                                 }
675 not_first:
676                                 if (attr && parent->lkp_value) {
677                                         free(parent->lkp_value);
678                                         parent->lkp_value = nla_strdup(attr);
679                                 }
680                         }
681                         break;
682
683                 case NLA_STRING:
684                         len = snprintf(data->buffer, *size, "%s",
685                                        nla_get_string(attr));
686                         break;
687
688                 case NLA_FLAG:
689                         len = snprintf(data->buffer, *size, "%s",
690                                        attr ? "true" : "false");
691                         break;
692
693                 case NLA_U16:
694                         len = snprintf(data->buffer, *size, "%hu",
695                                        nla_get_u16(attr));
696                         break;
697
698                 case NLA_U32:
699                         len = snprintf(data->buffer, *size, "%u",
700                                        nla_get_u32(attr));
701                         break;
702
703                 case NLA_U64:
704                         len = snprintf(data->buffer, *size, "%ju",
705                                        nla_get_u64(attr));
706                         break;
707
708                 case NLA_S16:
709                         len = snprintf(data->buffer, *size, "%hd",
710                                        nla_get_u16(attr));
711                         break;
712
713                 case NLA_S32:
714                         len = snprintf(data->buffer, *size, "%d",
715                                        nla_get_s32(attr));
716                         break;
717
718                 case NLA_S64:
719                         len = snprintf(data->buffer, *size, "%jd",
720                                        nla_get_s64(attr));
721                         fallthrough;
722                 default:
723                         break;
724                 }
725
726                 if (len) {
727                         if (mapping & LNKF_FLOW) {
728                                 strcat((char *)data->buffer, ", ");
729                                 len += 2;
730                         } else {
731                                 if ((mapping == LNKF_SEQUENCE) &&
732                                     !keys[i].lkp_value)
733                                         ((char *)data->buffer)[len++] = ':';
734
735                                 ((char *)data->buffer)[len++] = '\n';
736                         }
737                         data->buffer += len;
738                         *size += len;
739                 } else if (len < 0) {
740 unwind:
741                         data->buffer -= data->indent + 2;
742                         *size -= data->indent + 2;
743                 }
744         }
745 }
746
747 /* This is the CB_VALID callback for the Netlink library that we
748  * have hooked into. Any successful Netlink message is passed to
749  * this function which handles both the incoming key tables and
750  * the values of the key/value pairs being received. We use
751  * the NLM_F_CREATE flag to determine if the incoming Netlink
752  * message is a key table or a packet containing value pairs.
753  */
754 static int yaml_netlink_msg_parse(struct nl_msg *msg, void *arg)
755 {
756         struct yaml_netlink_input *data = arg;
757         struct nlmsghdr *nlh = nlmsg_hdr(msg);
758
759         if (nlh->nlmsg_flags & NLM_F_CREATE) {
760                 struct genlmsghdr *ghdr = genlmsg_hdr(nlh);
761                 struct nlattr *attrs[LN_SCALAR_MAX + 1];
762
763                 if (genlmsg_parse(nlh, 0, attrs, LN_SCALAR_MAX,
764                                   scalar_attr_policy))
765                         return NL_SKIP;
766
767                 if (attrs[LN_SCALAR_ATTR_LIST]) {
768                         int rc = yaml_parse_key_list(data, NULL,
769                                                      attrs[LN_SCALAR_ATTR_LIST]);
770                         if (rc != NL_OK)
771                                 return rc;
772
773                         /* reset to root node */
774                         data->cur = data->root;
775                 }
776
777                 /* For streaming insert '---' to define start of
778                  * YAML document. This allows use to extract
779                  * documents out of a multiplexed stream.
780                  */
781                 if (data->async) {
782                         char *start_doc = "---\n";
783                         size_t len = strlen(start_doc) + 1;
784
785                         strncpy(data->buffer, start_doc, len);
786                         data->buffer += len - 1;
787                 }
788                 data->version = ghdr->version;
789         } else {
790                 uint16_t maxtype = data->cur->keys.lkl_maxattr;
791                 struct nla_policy policy[maxtype];
792                 struct nlattr *attrs[maxtype];
793                 int size, i;
794
795                 memset(policy, 0, sizeof(struct nla_policy) * maxtype);
796                 for (i = 1; i < maxtype; i++)
797                         policy[i].type = data->cur->keys.lkl_list[i].lkp_data_type;
798
799                 if (genlmsg_parse(nlh, 0, attrs, maxtype, policy))
800                         return NL_SKIP;
801
802                 size = data->parser->raw_buffer.end -
803                        (unsigned char *)data->buffer;
804                 yaml_parse_value_list(data, &size, attrs,
805                                       &data->cur->keys.lkl_list[1]);
806         }
807
808         /* Let yaml_netlink_msg_complete end collecting data */
809         return NL_OK;
810 }
811
812 /* This is the libnl callback for when an error has happened
813  * kernel side. An error message is sent back to the user.
814  */
815 static int yaml_netlink_msg_error(struct sockaddr_nl *who,
816                                   struct nlmsgerr *errmsg, void *arg)
817 {
818         struct nlmsghdr *nlh = (void *)errmsg - NLMSG_HDRLEN;
819         struct yaml_netlink_input *data = arg;
820
821         if ((nlh->nlmsg_type == NLMSG_ERROR ||
822              nlh->nlmsg_flags & NLM_F_ACK_TLVS) && errmsg->error) {
823                 /* libyaml stomps on the reader error so we need to
824                  * cache the source of the error.
825                  */
826                 const char *errstr = nl_geterror(nl_syserr2nlerr(errmsg->error));
827
828 #ifdef HAVE_USRSPC_NLMSGERR
829                 /* Newer kernels support NLM_F_ACK_TLVS in nlmsg_flags
830                  * which gives greater detail why we failed.
831                  */
832                 if ((nlh->nlmsg_flags & NLM_F_ACK_TLVS) &&
833                     !(nlh->nlmsg_flags & NLM_F_CAPPED)) {
834                         struct nlattr *head = ((void *)&errmsg->msg);
835                         struct nlattr *tb[NLMSGERR_ATTR_MAX];
836
837                         if (nla_parse(tb, NLMSGERR_ATTR_MAX, head,
838                                       nlmsg_attrlen(nlh, 0), NULL) == 0) {
839                                 if (tb[NLMSGERR_ATTR_MSG])
840                                         errstr = nla_strdup(tb[NLMSGERR_ATTR_MSG]);
841                         }
842                 }
843 #endif /* HAVE_USRSPC_NLMSGERR */
844                 data->errmsg = errstr;
845                 data->error = errmsg->error;
846                 data->parser->error = YAML_READER_ERROR;
847                 data->complete = true;
848         }
849         return NL_STOP;
850 }
851
852 static bool cleanup_children(struct yaml_nl_node *parent)
853 {
854         struct yaml_nl_node *child;
855
856         if (nl_list_empty(&parent->children)) {
857                 struct ln_key_props *keys = parent->keys.lkl_list;
858                 int i;
859
860                 for (i = 1; i < parent->keys.lkl_maxattr; i++)
861                         if (keys[i].lkp_value)
862                                 free(keys[i].lkp_value);
863                 nl_list_del(&parent->list);
864                 return true;
865         }
866
867         while ((child = get_next_child(parent, 0)) != NULL) {
868                 if (cleanup_children(child))
869                         free(child);
870         }
871
872         return false;
873 }
874
875 /* This is the libnl callback for when the last Netlink packet
876  * is finished being parsed or its called right away in case
877  * the Linux kernel reports back an error from the Netlink layer.
878  */
879 static int yaml_netlink_msg_complete(struct nl_msg *msg, void *arg)
880 {
881         struct yaml_netlink_input *data = arg;
882         struct nlmsghdr *nlh = nlmsg_hdr(msg);
883
884         /* For the case of NLM_F_DUMP the kernel will send error msgs
885          * yet not be labled NLMSG_ERROR which results in this code
886          * path being executed.
887          */
888         yaml_netlink_msg_error(NULL, nlmsg_data(nlh), arg);
889         if (data->parser->error == YAML_READER_ERROR)
890                 return NL_STOP;
891
892         /* Free internal data. */
893         if (data->root) {
894                 cleanup_children(data->root);
895                 free(data->root);
896                 data->root = NULL;
897         }
898
899         /* For streaming insert '...' to define end of
900          * YAML document
901          */
902         if (data->async) {
903                 char *end_doc = "...\n";
904                 size_t len = strlen(end_doc) + 1;
905
906                 strncpy(data->buffer, end_doc, len);
907                 data->buffer += len - 1;
908         } else {
909                 data->complete = true;
910         }
911
912         return data->async ? NL_OK : NL_STOP;
913 }
914
915 /**
916  * In order for yaml_parser_set_input_netlink() to work we have to
917  * register a yaml_read_handler_t callback. This is that call back
918  * which listens for Netlink packets. Internally nl_recvmsg_report()
919  * calls the various callbacks discussed above.
920  */
921 static int yaml_netlink_read_handler(void *arg, unsigned char *buffer,
922                                      size_t size, size_t *size_read)
923 {
924         struct yaml_netlink_input *data = arg;
925         struct nl_sock *nl = data->nl;
926         struct nl_cb *cb;
927         int rc = 0;
928
929         if (data->complete) {
930                 *size_read = 0;
931                 return 1;
932         }
933
934         data->buffer = buffer;
935
936         cb = nl_socket_get_cb(nl);
937         rc = nl_recvmsgs_report(nl, cb);
938         if (rc == -NLE_INTR) {
939                 *size_read = 0;
940                 return 1;
941         } else if (!data->errmsg && rc < 0) {
942                 data->errmsg = nl_geterror(rc);
943                 return 0;
944         } else if (data->parser->error) {
945                 /* data->errmsg is set in NL_CB_FINISH */
946                 return 0;
947         }
948
949         rc = (unsigned char *)data->buffer - buffer;
950         if ((int)size > rc)
951                 size = rc;
952
953         *size_read = size;
954         return 1;
955 }
956
957 /* libyaml by default just reports "input error" for parser read_handler_t
958  * issues which is not useful. This provides away to get better debugging
959  * info.
960  */
961 YAML_DECLARE(const char *)
962 yaml_parser_get_reader_error(yaml_parser_t *parser)
963 {
964         struct yaml_netlink_input *buf = parser->read_handler_data;
965
966         if (!buf)
967                 return NULL;
968
969         errno = buf->error;
970         return buf->errmsg;
971 }
972
973 YAML_DECLARE(int)
974 yaml_parser_get_reader_proto_version(yaml_parser_t *parser)
975 {
976         struct yaml_netlink_input *buf = parser->read_handler_data;
977
978         if (!buf)
979                 return 0;
980
981         return buf->version;
982 }
983
984 /* yaml_parser_set_input_netlink() mirrors the libyaml function
985  * yaml_parser_set_input_file(). Internally it does setup of the
986  * libnl socket callbacks to parse the Netlink messages received
987  * as well as register the special yaml_read_handler_t for libyaml.
988  * This is exposed for public use.
989  */
990 YAML_DECLARE(int)
991 yaml_parser_set_input_netlink(yaml_parser_t *reply, struct nl_sock *nl,
992                               bool stream)
993 {
994         struct yaml_netlink_input *buf;
995         int rc;
996
997         buf = calloc(1, sizeof(*buf));
998         if (!buf) {
999                 reply->error = YAML_MEMORY_ERROR;
1000                 return false;
1001         }
1002
1003         rc = lustre_netlink_register(nl, stream);
1004         if (rc < 0) {
1005                 yaml_parser_set_reader_error(reply,
1006                                              "netlink setup failed", 0,
1007                                              -rc);
1008                 goto failed;
1009         }
1010
1011         buf->nl = nl;
1012         buf->async = stream;
1013         buf->parser = reply;
1014         yaml_parser_set_input(buf->parser, yaml_netlink_read_handler, buf);
1015
1016         rc = nl_socket_modify_cb(buf->nl, NL_CB_VALID, NL_CB_CUSTOM,
1017                                  yaml_netlink_msg_parse, buf);
1018         if (rc < 0) {
1019                 yaml_parser_set_reader_error(reply,
1020                                              "netlink msg recv setup failed",
1021                                              0, -rc);
1022                 goto failed;
1023         }
1024
1025         rc = nl_socket_modify_cb(buf->nl, NL_CB_FINISH, NL_CB_CUSTOM,
1026                                  yaml_netlink_msg_complete, buf);
1027         if (rc < 0) {
1028                 yaml_parser_set_reader_error(reply,
1029                                              "netlink msg cleanup setup failed",
1030                                              0, -rc);
1031                 goto failed;
1032         }
1033
1034         rc = nl_socket_modify_err_cb(nl, NL_CB_CUSTOM, yaml_netlink_msg_error,
1035                                      buf);
1036         if (rc < 0) {
1037                 yaml_parser_set_reader_error(reply,
1038                                              "failed to register error handling",
1039                                              0, -rc);
1040 failed:
1041                 free(buf);
1042         }
1043
1044         return rc < 0 ? false : true;
1045 }
1046
1047 /* The role of the YAML emitter for us is to take a YAML document and
1048  * change into a Netlink stream to send to the kernel to be processed.
1049  * This provides the infrastructure to do this.
1050  */
1051 struct yaml_netlink_output {
1052         yaml_emitter_t          *emitter;
1053         struct nl_sock          *nl;
1054         char                    *family;
1055         int                     family_id;
1056         int                     version;
1057         int                     cmd;
1058         int                     pid;
1059         int                     flags;
1060 };
1061
1062 /* Internal use for this file only. We fill in details of why creating
1063  * a Netlink packet to send failed. The end user will be able to debug
1064  * what went wrong.
1065  */
1066 static int
1067 yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
1068 {
1069         emitter->error = YAML_WRITER_ERROR;
1070         emitter->problem = problem;
1071
1072         return 0;
1073 }
1074
1075 static unsigned int indent_level(const char *str)
1076 {
1077         char *tmp = (char *)str;
1078
1079         while (isspace(*tmp))
1080                 ++tmp;
1081         return tmp - str;
1082 }
1083
1084 #define LNKF_END 8
1085
1086 static enum lnet_nl_key_format yaml_format_type(yaml_emitter_t *emitter,
1087                                                 char *line,
1088                                                 unsigned int *offset)
1089 {
1090         unsigned int indent = *offset, new_indent = 0;
1091         enum lnet_nl_key_format fmt = 0;
1092         char *tmp, *flow;
1093
1094         new_indent = indent_level(line);
1095         if (new_indent < indent) {
1096                 *offset = indent - emitter->best_indent;
1097                 return LNKF_END;
1098         }
1099
1100         if (strncmp(line + new_indent, "- ", 2) == 0) {
1101                 memset(line + new_indent, ' ', 2);
1102                 new_indent += 2;
1103         }
1104
1105         /* hdr: [ a : 1, b : 2, c : 3 ] */
1106         tmp = strstr(line + new_indent, ": ");
1107         if (!tmp)
1108                 tmp = line + new_indent;
1109         else
1110                 fmt |= LNKF_MAPPING;
1111
1112         flow = strchr(line + new_indent, '{');
1113         if (!flow)
1114                 flow = strchr(line + new_indent, '[');
1115         if (flow) {
1116                 if (flow < tmp)
1117                         fmt &= ~LNKF_MAPPING;
1118                 fmt |= LNKF_FLOW;
1119         } else if (strchr(tmp, '}') || strchr(tmp, ']')) {
1120                 if (strchr(tmp, ']'))
1121                         fmt &= ~LNKF_MAPPING;
1122                 fmt |= LNKF_FLOW;
1123         }
1124
1125         if (indent != new_indent) {
1126                 *offset = new_indent;
1127                 fmt |= LNKF_SEQUENCE;
1128         }
1129
1130         return fmt;
1131 }
1132
1133 static int yaml_fill_scalar_data(struct nl_msg *msg,
1134                                  enum lnet_nl_key_format fmt,
1135                                  char *line)
1136 {
1137         char *sep = strstr(line, ": "); /* handle mappings */
1138         int rc = 0;
1139         long num;
1140
1141         if (!sep) {
1142                 char *tmp = strchr(line, ':');
1143
1144                 if (tmp && strlen(tmp) == 1) /* handle simple scalar */
1145                         sep = tmp;
1146         }
1147         if (sep)
1148                 *sep++ = '\0';
1149
1150         if (strspn(line, "-0123456789") == strlen(line)) {
1151                 num = strtoll(line, NULL, 0);
1152
1153                 NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1154         } else {
1155                 NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, line);
1156         }
1157
1158         if (fmt & LNKF_FLOW) {
1159                 memset(line, ' ', strlen(line) + 1);
1160                 goto nla_put_failure;
1161         }
1162
1163         if (fmt & LNKF_MAPPING && sep) {
1164                 while (isspace(*sep))
1165                         ++sep;
1166
1167                 if (!strlen(sep))
1168                         goto nla_put_failure;
1169
1170                 if (strspn(sep, "-0123456789") == strlen(sep)) {
1171                         num = strtoll(sep, NULL, 0);
1172                         NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1173                 } else {
1174                         NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, sep);
1175                 }
1176         }
1177 nla_put_failure:
1178         return rc;
1179 }
1180
1181 static int yaml_create_nested_list(struct yaml_netlink_output *out,
1182                                    struct nl_msg *msg, char **hdr,
1183                                    char **entry, unsigned int *indent,
1184                                    enum lnet_nl_key_format fmt)
1185 {
1186         bool nested = fmt & LNKF_SEQUENCE;
1187         struct nlattr *list = NULL;
1188         char *line;
1189         int rc = 0;
1190
1191         /* Not needed for FLOW only case */
1192         if (nested) {
1193                 list = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1194                 if (!list) {
1195                         yaml_emitter_set_writer_error(out->emitter,
1196                                                       "Emmitter netlink list creation failed");
1197                         rc = -EINVAL;
1198                         goto nla_put_failure;
1199                 }
1200         }
1201
1202         if (fmt != LNKF_FLOW) {
1203                 rc = yaml_fill_scalar_data(msg, fmt, *hdr + *indent);
1204                 if (rc < 0)
1205                         goto nla_put_failure;
1206         }
1207
1208         if (fmt & LNKF_FLOW) {
1209                 char *tmp = strchr(*hdr, '{'), *split = NULL;
1210                 bool format = false;
1211
1212                 if (!tmp) {
1213                         tmp = strchr(*hdr, '[');
1214                         if (!tmp) {
1215                                 yaml_emitter_set_writer_error(out->emitter,
1216                                                               "Emmitter flow format invalid");
1217                                 rc = -EINVAL;
1218                                 goto nla_put_failure;
1219                         }
1220                         fmt |= LNKF_SEQUENCE;
1221                 } else
1222                         fmt |= LNKF_MAPPING;
1223                 *tmp = ' ';
1224
1225                 list = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1226                 if (!list) {
1227                         yaml_emitter_set_writer_error(out->emitter,
1228                                                       "Emmitter netlink list creation failed");
1229                         rc = -EINVAL;
1230                         goto nla_put_failure;
1231                 }
1232
1233                 fmt &= ~LNKF_FLOW;
1234                 while ((line = strsep(hdr, ",")) != NULL) {
1235                         while (!isalnum(line[0]))
1236                                 line++;
1237
1238                         /* Flow can be splt across lines by libyaml library. */
1239                         if (strchr(line, ',')) {
1240                                 split = line;
1241                                 *hdr = line;
1242                                 continue;
1243                         }
1244
1245                         tmp = strchr(line, '}');
1246                         if (!tmp)
1247                                 tmp = strchr(line, ']');
1248                         if (tmp) {
1249                                 format = true;
1250                                 *tmp = '\0';
1251                         }
1252
1253                         rc = yaml_fill_scalar_data(msg, fmt, line);
1254                         if (rc < 0)
1255                                 goto nla_put_failure;
1256
1257                         /* Move to next YAML line */
1258                         if (format) {
1259                                 if (!split)
1260                                         line = *entry;
1261                                 else
1262                                         *entry = NULL;
1263                                 break;
1264                         }
1265                 }
1266
1267                 if (!format) {
1268                         yaml_emitter_set_writer_error(out->emitter,
1269                                                       "Emmitter flow format invalid");
1270                         rc = -EINVAL;
1271                         goto nla_put_failure;
1272                 }
1273
1274                 if (line && line[0] == '-')
1275                         *indent = 0;
1276
1277                 nla_nest_end(msg, list);
1278         } else {
1279                 do {
1280                         line = strsep(entry, "\n");
1281 have_next_line:
1282                         if (!line || !strlen(line) || strcmp(line, "...") == 0)
1283                                 break;
1284
1285                         fmt = yaml_format_type(out->emitter, line, indent);
1286                         if (fmt == LNKF_END)
1287                                 break;
1288
1289                         if (fmt & ~LNKF_MAPPING) { /* Filter out mappings */
1290                                 rc = yaml_create_nested_list(out, msg, &line,
1291                                                              entry, indent,
1292                                                              fmt);
1293                                 if (rc < 0)
1294                                         goto nla_put_failure;
1295                                 if (line)
1296                                         goto have_next_line;
1297                         } else {
1298                                 rc = yaml_fill_scalar_data(msg, fmt,
1299                                                            line + *indent);
1300                                 if (rc < 0)
1301                                         goto nla_put_failure;
1302                         }
1303                 } while (strcmp(*entry, ""));
1304
1305                 if (line && line[*indent] == '-') {
1306                         line[*indent] = ' ';
1307                         *indent += 2;
1308                         goto have_next_line;
1309                 }
1310                 if (*entry && !strlen(*entry))
1311                         line = NULL;
1312                 /* strsep in the above loop moves entry to a value pass the
1313                  * end of the nested list. So to avoid losing this value we
1314                  * replace hdr with line.
1315                  */
1316                 *hdr = line;
1317         }
1318
1319         if (nested)
1320                 nla_nest_end(msg, list);
1321 nla_put_failure:
1322         return rc;
1323 }
1324
1325 /* YAML allows ' and " in its documents but those characters really
1326  * confuse libc string handling. The workaround is to replace
1327  * ' and " with another reserved character for YAML '%' which is
1328  * for tags which shouldn't matter if we send in a Netlink packet.
1329  * The kernel side will need to handle % in a special way.
1330  */
1331 static void yaml_quotation_handling(char *buf)
1332 {
1333         char *tmp = buf, *line;
1334
1335         line = strstr(tmp, "! \'");
1336         if (line)
1337                 line[0] = ' ';
1338
1339         while ((line = strchr(tmp, '\"')) != NULL) {
1340                 line[0] = ' ';
1341                 tmp = strchr(line, '\"');
1342                 tmp[0] = ' ';
1343         }
1344
1345         while ((line = strchr(tmp, '\'')) != NULL) {
1346                 line[0] = ' ';
1347                 tmp = strchr(line, '\'');
1348                 tmp[0] = ' ';
1349         }
1350 }
1351
1352 /* libyaml takes the YAML documents and places the data into an
1353  * internal buffer to the library. We take each line and turn it
1354  * into a Netlink message using the same format as the key table.
1355  * The reason for this approach is that we can do filters at the
1356  * key level or the key + value level.
1357  */
1358 static int yaml_netlink_write_handler(void *data, unsigned char *buffer,
1359                                       size_t size)
1360 {
1361         struct yaml_netlink_output *out = data;
1362         char *buf = strndup((char *)buffer, size);
1363         char *entry = buf, *tmp = buf, *line;
1364         enum lnet_nl_key_format fmt = 0;
1365         struct nl_msg *msg = NULL;
1366         unsigned int indent = 0;
1367         bool nogroups = true;
1368         int rc = 0;
1369
1370         yaml_quotation_handling(entry);
1371
1372         while (entry && strcmp(line = strsep(&entry, "\n"), "")) {
1373 already_have_line:
1374                 if (strcmp(line, "---") == 0 || strcmp(line, "...") == 0)
1375                         continue;
1376
1377                 /* In theory we could have a sequence of groups but a bug in
1378                  * libyaml prevents this from happing
1379                  */
1380                 if (line[0] != ' ' && line[0] != '-') {
1381                         bool extra = false;
1382
1383                         if (strchr(line, '{') || strchr(line, '['))
1384                                 extra = true;
1385
1386                         tmp = strchr(line, ':');
1387                         if (!tmp)
1388                                 continue;
1389                         *tmp = '\0';
1390
1391                         rc = lustre_netlink_add_group(out->nl, out->family,
1392                                                       line);
1393                         if (rc < 0) {
1394                                 yaml_emitter_set_writer_error(out->emitter,
1395                                                               "Netlink group does not exist");
1396                                 goto nla_put_failure;
1397                         }
1398                         nogroups = false;
1399                         /* Handle case first line contains more than a
1400                          * simple key
1401                          */
1402                         if (extra) {
1403                                 *tmp = ' ';
1404                                 line = tmp;
1405                                 goto already_have_line;
1406                         }
1407                 } else {
1408                         if (!msg) {
1409                                 void *usr_hdr;
1410
1411                                 msg = nlmsg_alloc();
1412                                 if (!msg) {
1413                                         out->emitter->error = YAML_MEMORY_ERROR;
1414                                         goto nla_put_failure;
1415                                 }
1416
1417                                 usr_hdr = genlmsg_put(msg, out->pid,
1418                                                       NL_AUTO_SEQ,
1419                                                       out->family_id, 0,
1420                                                       out->flags, out->cmd,
1421                                                       out->version);
1422                                 if (!usr_hdr) {
1423                                         out->emitter->error = YAML_MEMORY_ERROR;
1424                                         nlmsg_free(msg);
1425                                         goto nla_put_failure;
1426                                 }
1427
1428                                 if (line[0] != '-')
1429                                         indent = 2;
1430                         }
1431
1432                         fmt = yaml_format_type(out->emitter, line, &indent);
1433                         if (fmt & ~LNKF_MAPPING) {
1434                                 rc = yaml_create_nested_list(out, msg, &line,
1435                                                              &entry, &indent,
1436                                                              fmt);
1437                                 if (rc < 0) {
1438                                         yaml_emitter_set_writer_error(out->emitter,
1439                                                                       nl_geterror(rc));
1440                                         nlmsg_free(msg);
1441                                         goto nla_put_failure;
1442                                 }
1443                                 /* yaml_create_nested_list set line to the next
1444                                  * entry. We can just add it to the msg directly.
1445                                  */
1446                                 if (line)
1447                                         goto already_have_line;
1448                         } else {
1449                                 rc = yaml_fill_scalar_data(msg, fmt,
1450                                                            line + indent);
1451                                 if (rc < 0) {
1452                                         yaml_emitter_set_writer_error(out->emitter,
1453                                                                       nl_geterror(rc));
1454                                         nlmsg_free(msg);
1455                                         goto nla_put_failure;
1456                                 }
1457                         }
1458                 }
1459         }
1460
1461         /* Don't success if no valid groups found */
1462         if (nogroups) {
1463                 yaml_emitter_set_writer_error(out->emitter,
1464                                               "Emitter contains no valid Netlink groups");
1465                 goto nla_put_failure;
1466         }
1467
1468         if (msg) {
1469                 rc = nl_send_auto(out->nl, msg);
1470                 nlmsg_free(msg);
1471         } else {
1472                 rc = genl_send_simple(out->nl, out->family_id, out->cmd,
1473                                       out->version, out->flags);
1474         }
1475         if (rc < 0)
1476                 yaml_emitter_set_writer_error(out->emitter,
1477                                               nl_geterror(rc));
1478 nla_put_failure:
1479         free(buf);
1480         return out->emitter->error == YAML_NO_ERROR ? 1 : 0;
1481 }
1482
1483 /* This function is used by external utilities to use Netlink with
1484  * libyaml so we can turn YAML documentations into Netlink message
1485  * to send. This behavior mirrors yaml_emitter_set_output_file()
1486  * which is used to write out a YAML document to a file.
1487  */
1488 YAML_DECLARE(int)
1489 yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
1490                                 char *family, int version, int cmd, int flags)
1491 {
1492         struct yaml_netlink_output *out;
1493
1494         out = calloc(1, sizeof(*out));
1495         if (!out) {
1496                 sender->error = YAML_MEMORY_ERROR;
1497                 return false;
1498         }
1499
1500         /* Get family ID */
1501         out->family_id = genl_ctrl_resolve(nl, family);
1502         if (out->family_id < 0) {
1503                 yaml_emitter_set_writer_error(sender,
1504                                               "failed to resolve Netlink family id");
1505                 free(out);
1506                 return false;
1507         }
1508
1509         out->emitter = sender;
1510         out->nl = nl;
1511         out->family = family;
1512         out->version = version;
1513         out->cmd = cmd;
1514         out->flags = flags;
1515         out->pid = nl_socket_get_local_port(nl);
1516         yaml_emitter_set_output(sender, yaml_netlink_write_handler, out);
1517         return true;
1518 }
1519
1520 /* Error handling helpers */
1521 void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log)
1522 {
1523         /* YAML_WRITER_ERROR means no Netlink support so use old API */
1524         switch (emitter->error) {
1525         case YAML_MEMORY_ERROR:
1526                 fprintf(log, "Memory error: Not enough memory for emitting\n");
1527                         break;
1528         case YAML_WRITER_ERROR:
1529                 fprintf(log, "Writer error: %s\n", emitter->problem);
1530                 break;
1531         case YAML_EMITTER_ERROR:
1532                 fprintf(log, "Emitter error: %s\n", emitter->problem);
1533         default:
1534                 break;
1535         }
1536 }
1537
1538 void yaml_parser_log_error(yaml_parser_t *parser, FILE *log, const char *errmsg)
1539 {
1540         const char *extra;
1541
1542         switch (parser->error) {
1543         case YAML_MEMORY_ERROR:
1544                 fprintf(log, "Memory error: Not enough memory for parser\n");
1545                 break;
1546
1547         case YAML_SCANNER_ERROR:
1548         case YAML_PARSER_ERROR:
1549                 if (parser->context) {
1550                         fprintf(log,
1551                                 "%s error: %s at line %d, column %d\n%s at line %d, column %d\n",
1552                                 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1553                                 parser->context,
1554                                 (int)parser->context_mark.line + 1,
1555                                 (int)parser->context_mark.column + 1,
1556                                 parser->problem,
1557                                 (int)parser->problem_mark.line + 1,
1558                                 (int)parser->problem_mark.column + 1);
1559                 } else {
1560                         fprintf(log, "%s error: %s at line %d, column %d\n",
1561                                 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1562                                 parser->problem,
1563                                 (int)parser->problem_mark.line + 1,
1564                                 (int)parser->problem_mark.column + 1);
1565                 }
1566                 break;
1567
1568         case YAML_READER_ERROR:
1569                 extra = yaml_parser_get_reader_error(parser);
1570                 if (!extra)
1571                         extra = parser->problem;
1572
1573                 if (parser->problem_value != -1) {
1574                         fprintf(log, "Reader error: '%s':#%X at %ld'\n",
1575                                 extra, parser->problem_value,
1576                                 (long)parser->problem_offset);
1577                 } else {
1578                         fprintf(log, "Reader error: '%s' at %ld\n",
1579                                 extra, (long)parser->problem_offset);
1580                 }
1581                 fallthrough;
1582         default:
1583                 break;
1584         }
1585 }