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