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