Whamcloud - gitweb
3c7e7f700dc3e27bb3761bf8fd8e093105688718
[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 static 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 static 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 static 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 static 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 /* We translate Netlink nested list into either a YAML mappping or sequence.
582  * This generates the start of such a YAML block.
583  */
584 static int yaml_nested_header(struct yaml_netlink_input *data,
585                               int *size, unsigned int *indent,
586                               int mapping, struct ln_key_props *keys)
587 {
588         int len = 0;
589
590         if (keys->lkp_key_format & LNKF_FLOW) {
591                 char brace = '{';
592
593                 if (keys->lkp_key_format & LNKF_SEQUENCE)
594                         brace = '[';
595
596                 len = snprintf(data->buffer, *size, "%*s%s: %c ", data->indent,
597                                "", keys->lkp_value, brace);
598         } else {
599                 int count = mapping & LNKF_SEQUENCE ? 0 : data->indent;
600
601                 if (keys->lkp_key_format & LNKF_MAPPING)
602                         *indent += 2;
603                 if (keys->lkp_key_format & LNKF_SEQUENCE)
604                         *indent += 2;
605
606                 len = snprintf(data->buffer, *size, "%*s%s:\n", count, "",
607                                keys->lkp_value);
608         }
609
610         return len;
611 }
612
613 static struct yaml_nl_node *get_next_child(struct yaml_nl_node *node,
614                                            unsigned int idx)
615 {
616         struct yaml_nl_node *child;
617         unsigned int i = 0;
618
619         nl_list_for_each_entry(child, &node->children, list)
620                 if (idx == i++)
621                         return child;
622
623         return NULL;
624 }
625
626 /**
627  * In the YAML C implementation the scanner transforms the input stream
628  * (Netlink in this case) into a sequence of keys. First we need to
629  * examine the potential keys involved to see the mapping to Netlink.
630  * We have chosen to examine the YAML stack with keys since they are
631  * more detailed when compared to yaml_document_t / yaml_nodes and
632  * yaml_event_t.
633  *
634  *      STREAM-START(encoding)          # The stream start.
635  *      STREAM-END                      # The stream end.
636  *      VERSION-DIRECTIVE(major,minor)  # The '%YAML' directive.
637  *      TAG-DIRECTIVE(handle,prefix)    # The '%TAG' directive.
638  *      DOCUMENT-START                  # '---'
639  *      DOCUMENT-END                    # '...'
640  *      BLOCK-SEQUENCE-START            # Indentation increase denoting a block
641  *      BLOCK-MAPPING-START             # sequence or a block mapping.
642  *      BLOCK-END                       # Indentation decrease.
643  *      FLOW-SEQUENCE-START             # '['
644  *      FLOW-SEQUENCE-END               # ']'
645  *      FLOW-MAPPING-START              # '{'
646  *      FLOW-MAPPING-END                # '}'
647  *      BLOCK-ENTRY                     # '-'
648  *      FLOW-ENTRY                      # ','
649  *      KEY                             # '?' or nothing (simple keys).
650  *      VALUE                           # ':'
651  *      ALIAS(anchor)                   # '*anchor'
652  *      ANCHOR(anchor)                  # '&anchor'
653  *      TAG(handle,suffix)              # '!handle!suffix'
654  *      SCALAR(value,style)             # A scalar.
655  *
656  * For our read_handler / write_handler STREAM-START / STREAM-END,
657  * VERSION-DIRECTIVE, and TAG-DIRECTIVE are hanndler by the libyaml
658  * internal scanner so we don't need to deal with it. Normally for
659  * LNet / Lustre DOCUMENT-START / DOCUMENT-END are not needed but it
660  * could be easily handled. In the case of multiplex streams we could
661  * see these used to differentiate data coming in.
662  *
663  * It is here we handle any simple scalars or values of the key /value
664  * pair. How the YAML document is formated is dependent on the key
665  * table's data.
666  */
667 static void yaml_parse_value_list(struct yaml_netlink_input *data, int *size,
668                                   struct nlattr *attr_array[],
669                                   struct ln_key_props *parent)
670 {
671         struct yaml_nl_node *node = data->cur;
672         struct ln_key_props *keys = node->keys.lkl_list;
673         int mapping = parent->lkp_key_format;
674         int child_idx = 0, len = 0, i;
675         bool first = true;
676
677         for (i = 1; i < node->keys.lkl_maxattr; i++) {
678                 struct nlattr *attr;
679
680                 attr = attr_array[i];
681                 if (!attr && !keys[i].lkp_value)
682                         continue;
683
684                 /* This function is called for each Netlink nested list.
685                  * Each nested list is treated as a YAML block. It is here
686                  * we handle data for the YAML block. How that data is seen
687                  * for YAML is based on the parents mapping and the type of
688                  * data value sent.
689                  *
690                  * The cases are:
691                  *
692                  * the value type is NLA_NUL_STRING which is interepted as
693                  *      key:\n
694                  *
695                  * Also NLA_NUL_STRING is used to update a single key value.
696                  *
697                  * the key has no lkp_value and we do receive a 'value'
698                  * that is not a nested list in the Netlink packet. This is
699                  * treated as a plain scalar.
700                  *
701                  * we have a key lkp_value and the parent mapping is
702                  * LNKF_MAPPING then we have a key : value pair. During
703                  * our loop the key normally doesn't change.
704                  *
705                  * This data belongs to a YAML block which can be of
706                  * different kinds (FLOW, SEQUENCE, MAPPING). We determine
707                  * the type and adjust the first line of output for the
708                  * YAML results if needed. Most of the time the creation
709                  * of the nested header is done in the NLA_NESTED case
710                  * switch below which happens before this function is
711                  * called. Specific handling is done here.
712                  *
713                  * The common case handled here is for building of the
714                  * mapping key : value pair. Another case is that we
715                  * are at the start of a SEQUENCE block. If this is the
716                  * case we add '-' to the output and clear the flag
717                  * LNKF_SEQUENCE to prevent multiple instanstances of
718                  * '-'. Only one '-' per SEQUENCE block. We need to
719                  * manually add '-' also in the case of were our nested
720                  * block first PROCESSED attr instance is another nested
721                  * block. For example:
722                  *      local NI(s):
723                  *      -     interfaces:
724                  *                 0: ib0
725                  */
726                 if ((first && (mapping & LNKF_SEQUENCE) &&
727                      keys[i].lkp_data_type == NLA_NESTED) ||
728                     (keys[i].lkp_data_type != NLA_NUL_STRING &&
729                      keys[i].lkp_data_type != NLA_NESTED)) {
730                         if (!attr && keys[i].lkp_data_type != NLA_FLAG)
731                                 continue;
732
733                         /* Mark this as the start of a SEQUENCE block */
734                         if (!(mapping & LNKF_FLOW)) {
735                                 unsigned int indent = data->indent ?
736                                                       data->indent : 2;
737
738                                 memset(data->buffer, ' ', indent);
739                                 if (mapping & LNKF_SEQUENCE) {
740                                         ((char *)data->buffer)[indent - 2] = '-';
741                                         if (keys[i].lkp_data_type != NLA_NESTED &&
742                                             mapping & LNKF_MAPPING)
743                                                 mapping &= ~LNKF_SEQUENCE;
744                                 }
745                                 data->buffer += indent;
746                                 *size -= indent;
747                         }
748
749                         /* Start of the build of the key : value pair.
750                          * Very common case.
751                          */
752                         if (keys[i].lkp_data_type != NLA_NESTED &&
753                             mapping & LNKF_MAPPING) {
754                                 len = snprintf(data->buffer, *size, "%s: ",
755                                                keys[i].lkp_value);
756                                 if (len < 0)
757                                         goto unwind;
758                                 data->buffer += len;
759                                 *size -= len;
760                         }
761                 }
762
763                 switch (keys[i].lkp_data_type) {
764                 case NLA_NESTED: {
765                         struct yaml_nl_node *next = get_next_child(node,
766                                                                    child_idx++);
767                         int num = next ? next->keys.lkl_maxattr : 0;
768                         struct nla_policy nest_policy[num];
769                         struct yaml_nl_node *old;
770                         struct nlattr *cnt_attr;
771                         unsigned int indent = 0;
772                         bool start = true;
773                         int rem, j;
774
775                         if (!attr || !next)
776                                 continue;
777
778                         memset(nest_policy, 0, sizeof(struct nla_policy) * num);
779                         for (j = 1; j < num; j++)
780                                 nest_policy[j].type = next->keys.lkl_list[j].lkp_data_type;
781
782                         /* We might have a empty list but by YAML standards
783                          * we still need to display the header.
784                          */
785                         if (!nla_len(attr)) {
786                                 len = yaml_nested_header(data, size, &indent,
787                                                          first ? mapping : 0,
788                                                          &keys[i]);
789                                 if (len < 0)
790                                         goto unwind;
791                                 data->buffer += len;
792                                 *size -= len;
793                                 len = 0;
794                         }
795
796                         old = data->cur;
797                         data->cur = next;
798                         nla_for_each_nested(cnt_attr, attr, rem) {
799                                 struct nlattr *nest_info[num];
800
801                                 if (nla_parse_nested(nest_info, num, cnt_attr,
802                                                      nest_policy))
803                                         break;
804
805                                 /* Create the nested header only once at start */
806                                 if (!start)
807                                         goto skip_nested_header;
808                                 start = false;
809
810                                 /* Update the header's first key */
811                                 if (next->keys.lkl_list[1].lkp_data_type == NLA_NUL_STRING &&
812                                     !keys[i].lkp_value)
813                                         keys[i].lkp_value = nla_strdup(nest_info[1]);
814
815                                 len = yaml_nested_header(data, size, &indent,
816                                                          first ? mapping : 0,
817                                                          &keys[i]);
818                                 if (len < 0)
819                                         goto unwind;
820                                 data->buffer += len;
821                                 *size -= len;
822                                 len = 0;
823 skip_nested_header:
824                                 data->indent += indent;
825                                 yaml_parse_value_list(data, size, nest_info,
826                                                       &keys[i]);
827                                 data->indent -= indent;
828                         }
829
830                         /* nested bookend header */
831                         if (keys[i].lkp_key_format & LNKF_FLOW) {
832                                 char *tmp = (char *)data->buffer - 2;
833                                 char *brace = " }\n";
834
835                                 if (keys[i].lkp_key_format &
836                                     LNKF_SEQUENCE)
837                                         brace = " ]\n";
838
839                                 memcpy(tmp, brace, strlen(brace));
840                                 data->buffer++;
841                                 *size -= 1;
842                         }
843                         data->cur = old;
844
845                         /* This is for the special case of the first attr of
846                          * a nested list is another nested list. We had to
847                          * insert a '-' but that is only done once so clear
848                          * the mapping of LNKF_SEQUENCE.
849                          */
850                         if (first && attr) {
851                                 if (mapping & LNKF_MAPPING)
852                                         mapping &= ~LNKF_SEQUENCE;
853                                 first = false;
854                         }
855                         break;
856                 }
857
858                 /* Handle the key:\n YAML case or updating an individual key */
859                 case NLA_NUL_STRING:
860                         if (i == 1) {
861                                 if (data->cur != data->root)
862                                         goto not_first;
863
864                                 /* The top level is special so only print
865                                  * once
866                                  */
867                                 if (strlen(keys[i].lkp_value)) {
868                                         len = snprintf(data->buffer,
869                                                        *size, "%s:\n",
870                                                        keys[i].lkp_value);
871                                         if (len < 0)
872                                                 goto unwind;
873                                         data->buffer += len;
874                                         *size -= len;
875                                         len = 0;
876                                 }
877                                 data->indent = 0;
878                                 if (!(mapping & LNKF_FLOW)) {
879                                         if (mapping & LNKF_SEQUENCE)
880                                                 data->indent += 2;
881                                         else if (mapping & LNKF_MAPPING)
882                                                 data->indent += 2;
883                                 }
884 not_first:
885                                 if (attr && parent->lkp_value) {
886                                         free(parent->lkp_value);
887                                         parent->lkp_value = nla_strdup(attr);
888                                 }
889                         }
890                         break;
891
892                 /* The below is used for a plain scalar or to complete the
893                 *  key : value pair.
894                 */
895                 case NLA_STRING:
896                         len = snprintf(data->buffer, *size, "%s",
897                                        nla_get_string(attr));
898                         break;
899
900                 case NLA_FLAG:
901                         len = snprintf(data->buffer, *size, "%s",
902                                        attr ? "true" : "false");
903                         break;
904
905                 case NLA_U16:
906                         len = snprintf(data->buffer, *size, "%hu",
907                                        nla_get_u16(attr));
908                         break;
909
910                 case NLA_U32:
911                         len = snprintf(data->buffer, *size, "%u",
912                                        nla_get_u32(attr));
913                         break;
914
915                 case NLA_U64:
916                         len = snprintf(data->buffer, *size, "%ju",
917                                        nla_get_u64(attr));
918                         break;
919
920                 case NLA_S16:
921                         len = snprintf(data->buffer, *size, "%hd",
922                                        nla_get_u16(attr));
923                         break;
924
925                 case NLA_S32:
926                         len = snprintf(data->buffer, *size, "%d",
927                                        nla_get_s32(attr));
928                         break;
929
930                 case NLA_S64:
931                         len = snprintf(data->buffer, *size, "%jd",
932                                        nla_get_s64(attr));
933                         fallthrough;
934                 default:
935                         break;
936                 }
937
938                 if (len) {
939                         if (mapping & LNKF_FLOW) {
940                                 strcat((char *)data->buffer, ", ");
941                                 len += 2;
942                         } else {
943                                 if ((mapping == LNKF_SEQUENCE) &&
944                                     !keys[i].lkp_value)
945                                         ((char *)data->buffer)[len++] = ':';
946
947                                 ((char *)data->buffer)[len++] = '\n';
948                         }
949                         data->buffer += len;
950                         *size += len;
951                 } else if (len < 0) {
952 unwind:
953                         data->buffer -= data->indent + 2;
954                         *size -= data->indent + 2;
955                 }
956         }
957 }
958
959 static bool cleanup_children(struct yaml_nl_node *parent)
960 {
961         struct yaml_nl_node *child;
962
963         if (nl_list_empty(&parent->children)) {
964                 struct ln_key_props *keys = parent->keys.lkl_list;
965                 int i;
966
967                 for (i = 1; i < parent->keys.lkl_maxattr; i++)
968                         if (keys[i].lkp_value)
969                                 free(keys[i].lkp_value);
970                 nl_list_del(&parent->list);
971                 return true;
972         }
973
974         while ((child = get_next_child(parent, 0)) != NULL) {
975                 if (cleanup_children(child))
976                         free(child);
977         }
978
979         return false;
980 }
981
982 /* This is the CB_VALID callback for the Netlink library that we
983  * have hooked into. Any successful Netlink message is passed to
984  * this function which handles both the incoming key tables and
985  * the values of the key/value pairs being received. We use
986  * the NLM_F_CREATE flag to determine if the incoming Netlink
987  * message is a key table or a packet containing value pairs.
988  */
989 static int yaml_netlink_msg_parse(struct nl_msg *msg, void *arg)
990 {
991         struct yaml_netlink_input *data = arg;
992         struct nlmsghdr *nlh = nlmsg_hdr(msg);
993
994         if (nlh->nlmsg_flags & NLM_F_CREATE) {
995                 struct genlmsghdr *ghdr = genlmsg_hdr(nlh);
996                 struct nlattr *attrs[LN_SCALAR_MAX + 1];
997
998                 if (lnet_genlmsg_parse(nlh, 0, attrs, LN_SCALAR_MAX,
999                                        scalar_attr_policy))
1000                         return NL_SKIP;
1001
1002                 /* If root already exists this means we are updating the
1003                  * key table. Free old key table.
1004                  */
1005                 if (data->root && (nlh->nlmsg_flags & NLM_F_REPLACE)) {
1006                         cleanup_children(data->root);
1007                         free(data->root);
1008                         data->root = NULL;
1009                 }
1010
1011                 if (attrs[LN_SCALAR_ATTR_LIST]) {
1012                         int rc = yaml_parse_key_list(data, NULL,
1013                                                      attrs[LN_SCALAR_ATTR_LIST]);
1014                         if (rc != NL_OK)
1015                                 return rc;
1016
1017                         /* reset to root node */
1018                         data->cur = data->root;
1019                 }
1020
1021                 /* For streaming insert '---' to define start of
1022                  * YAML document. This allows use to extract
1023                  * documents out of a multiplexed stream.
1024                  */
1025                 if (data->async) {
1026                         char *start_doc = "---\n";
1027                         size_t len = strlen(start_doc) + 1;
1028
1029                         strncpy(data->buffer, start_doc, len);
1030                         data->buffer += len - 1;
1031                 }
1032                 data->version = ghdr->version;
1033         } else {
1034                 uint16_t maxtype = data->cur->keys.lkl_maxattr;
1035                 struct nla_policy policy[maxtype];
1036                 struct nlattr *attrs[maxtype];
1037                 int size, i;
1038
1039                 memset(policy, 0, sizeof(struct nla_policy) * maxtype);
1040                 for (i = 1; i < maxtype; i++)
1041                         policy[i].type = data->cur->keys.lkl_list[i].lkp_data_type;
1042
1043                 if (lnet_genlmsg_parse(nlh, 0, attrs, maxtype, policy))
1044                         return NL_SKIP;
1045
1046                 size = data->parser->raw_buffer.end -
1047                        (unsigned char *)data->buffer;
1048                 yaml_parse_value_list(data, &size, attrs,
1049                                       &data->cur->keys.lkl_list[1]);
1050         }
1051
1052         /* Let yaml_netlink_msg_complete end collecting data */
1053         return NL_OK;
1054 }
1055
1056 /* This is the libnl callback for when an error has happened
1057  * kernel side. An error message is sent back to the user.
1058  */
1059 static int yaml_netlink_msg_error(struct sockaddr_nl *who,
1060                                   struct nlmsgerr *errmsg, void *arg)
1061 {
1062         struct nlmsghdr *nlh = (void *)errmsg - NLMSG_HDRLEN;
1063         struct yaml_netlink_input *data = arg;
1064
1065         if ((nlh->nlmsg_type == NLMSG_ERROR ||
1066              nlh->nlmsg_flags & NLM_F_ACK_TLVS) && errmsg->error) {
1067                 /* libyaml stomps on the reader error so we need to
1068                  * cache the source of the error.
1069                  */
1070                 const char *errstr = nl_geterror(nl_syserr2nlerr(errmsg->error));
1071
1072 #ifdef HAVE_USRSPC_NLMSGERR
1073                 /* Newer kernels support NLM_F_ACK_TLVS in nlmsg_flags
1074                  * which gives greater detail why we failed.
1075                  */
1076                 if ((nlh->nlmsg_flags & NLM_F_ACK_TLVS) &&
1077                     !(nlh->nlmsg_flags & NLM_F_CAPPED)) {
1078                         struct nlattr *head = ((void *)&errmsg->msg);
1079                         struct nlattr *tb[NLMSGERR_ATTR_MAX];
1080
1081                         if (nla_parse(tb, NLMSGERR_ATTR_MAX, head,
1082                                       nlmsg_attrlen(nlh, 0), NULL) == 0) {
1083                                 if (tb[NLMSGERR_ATTR_MSG])
1084                                         errstr = nla_strdup(tb[NLMSGERR_ATTR_MSG]);
1085                         }
1086                 }
1087 #endif /* HAVE_USRSPC_NLMSGERR */
1088                 data->errmsg = errstr;
1089                 data->error = errmsg->error;
1090                 data->parser->error = YAML_READER_ERROR;
1091                 data->complete = true;
1092         }
1093         return NL_STOP;
1094 }
1095
1096 /* This is the libnl callback for when the last Netlink packet
1097  * is finished being parsed or its called right away in case
1098  * the Linux kernel reports back an error from the Netlink layer.
1099  */
1100 static int yaml_netlink_msg_complete(struct nl_msg *msg, void *arg)
1101 {
1102         struct yaml_netlink_input *data = arg;
1103         struct nlmsghdr *nlh = nlmsg_hdr(msg);
1104
1105         /* For the case of NLM_F_DUMP the kernel will send error msgs
1106          * yet not be labled NLMSG_ERROR which results in this code
1107          * path being executed.
1108          */
1109         yaml_netlink_msg_error(NULL, nlmsg_data(nlh), arg);
1110         if (data->parser->error == YAML_READER_ERROR)
1111                 return NL_STOP;
1112
1113         /* Free internal data. */
1114         if (data->root) {
1115                 cleanup_children(data->root);
1116                 free(data->root);
1117                 data->root = NULL;
1118         }
1119
1120         /* For streaming insert '...' to define end of
1121          * YAML document
1122          */
1123         if (data->async) {
1124                 char *end_doc = "...\n";
1125                 size_t len = strlen(end_doc) + 1;
1126
1127                 strncpy(data->buffer, end_doc, len);
1128                 data->buffer += len - 1;
1129         } else {
1130                 data->complete = true;
1131         }
1132
1133         return data->async ? NL_OK : NL_STOP;
1134 }
1135
1136 /**
1137  * In order for yaml_parser_set_input_netlink() to work we have to
1138  * register a yaml_read_handler_t callback. This is that call back
1139  * which listens for Netlink packets. Internally nl_recvmsg_report()
1140  * calls the various callbacks discussed above.
1141  */
1142 static int yaml_netlink_read_handler(void *arg, unsigned char *buffer,
1143                                      size_t size, size_t *size_read)
1144 {
1145         struct yaml_netlink_input *data = arg;
1146         struct nl_sock *nl = data->nl;
1147         struct nl_cb *cb;
1148         int rc = 0;
1149
1150         if (data->complete) {
1151                 *size_read = 0;
1152                 return 1;
1153         }
1154
1155         data->buffer = buffer;
1156
1157         cb = nl_socket_get_cb(nl);
1158         rc = nl_recvmsgs_report(nl, cb);
1159         if (rc == -NLE_INTR) {
1160                 *size_read = 0;
1161                 return 1;
1162         } else if (!data->errmsg && rc < 0) {
1163                 data->errmsg = nl_geterror(rc);
1164                 return 0;
1165         } else if (data->parser->error) {
1166                 /* data->errmsg is set in NL_CB_FINISH */
1167                 return 0;
1168         }
1169
1170         rc = (unsigned char *)data->buffer - buffer;
1171         if ((int)size > rc)
1172                 size = rc;
1173
1174         *size_read = size;
1175         return 1;
1176 }
1177
1178 /* libyaml by default just reports "input error" for parser read_handler_t
1179  * issues which is not useful. This provides away to get better debugging
1180  * info.
1181  */
1182 YAML_DECLARE(const char *)
1183 yaml_parser_get_reader_error(yaml_parser_t *parser)
1184 {
1185         struct yaml_netlink_input *buf = parser->read_handler_data;
1186
1187         if (!buf)
1188                 return NULL;
1189
1190         errno = buf->error;
1191         return buf->errmsg;
1192 }
1193
1194 YAML_DECLARE(int)
1195 yaml_parser_get_reader_proto_version(yaml_parser_t *parser)
1196 {
1197         struct yaml_netlink_input *buf = parser->read_handler_data;
1198
1199         if (!buf)
1200                 return 0;
1201
1202         return buf->version;
1203 }
1204
1205 /* yaml_parser_set_input_netlink() mirrors the libyaml function
1206  * yaml_parser_set_input_file(). Internally it does setup of the
1207  * libnl socket callbacks to parse the Netlink messages received
1208  * as well as register the special yaml_read_handler_t for libyaml.
1209  * This is exposed for public use.
1210  */
1211 YAML_DECLARE(int)
1212 yaml_parser_set_input_netlink(yaml_parser_t *reply, struct nl_sock *nl,
1213                               bool stream)
1214 {
1215         struct yaml_netlink_input *buf;
1216         int rc;
1217
1218         buf = calloc(1, sizeof(*buf));
1219         if (!buf) {
1220                 reply->error = YAML_MEMORY_ERROR;
1221                 return false;
1222         }
1223
1224         rc = lustre_netlink_register(nl, stream);
1225         if (rc < 0) {
1226                 yaml_parser_set_reader_error(reply,
1227                                              "netlink setup failed", 0,
1228                                              -rc);
1229                 goto failed;
1230         }
1231
1232         buf->nl = nl;
1233         buf->async = stream;
1234         buf->parser = reply;
1235         yaml_parser_set_input(buf->parser, yaml_netlink_read_handler, buf);
1236
1237         rc = nl_socket_modify_cb(buf->nl, NL_CB_VALID, NL_CB_CUSTOM,
1238                                  yaml_netlink_msg_parse, buf);
1239         if (rc < 0) {
1240                 yaml_parser_set_reader_error(reply,
1241                                              "netlink msg recv setup failed",
1242                                              0, -rc);
1243                 goto failed;
1244         }
1245
1246         rc = nl_socket_modify_cb(buf->nl, NL_CB_FINISH, NL_CB_CUSTOM,
1247                                  yaml_netlink_msg_complete, buf);
1248         if (rc < 0) {
1249                 yaml_parser_set_reader_error(reply,
1250                                              "netlink msg cleanup setup failed",
1251                                              0, -rc);
1252                 goto failed;
1253         }
1254
1255         rc = nl_socket_modify_err_cb(nl, NL_CB_CUSTOM, yaml_netlink_msg_error,
1256                                      buf);
1257         if (rc < 0) {
1258                 yaml_parser_set_reader_error(reply,
1259                                              "failed to register error handling",
1260                                              0, -rc);
1261 failed:
1262                 free(buf);
1263         }
1264
1265         return rc < 0 ? false : true;
1266 }
1267
1268 /* The role of the YAML emitter for us is to take a YAML document and
1269  * change into a Netlink stream to send to the kernel to be processed.
1270  * This provides the infrastructure to do this.
1271  */
1272 struct yaml_netlink_output {
1273         yaml_emitter_t          *emitter;
1274         struct nl_sock          *nl;
1275         char                    *family;
1276         int                     family_id;
1277         int                     version;
1278         int                     cmd;
1279         int                     pid;
1280         int                     flags;
1281 };
1282
1283 /* Internal use for this file only. We fill in details of why creating
1284  * a Netlink packet to send failed. The end user will be able to debug
1285  * what went wrong.
1286  */
1287 static int
1288 yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
1289 {
1290         emitter->error = YAML_WRITER_ERROR;
1291         emitter->problem = problem;
1292
1293         return 0;
1294 }
1295
1296 static unsigned int indent_level(const char *str)
1297 {
1298         char *tmp = (char *)str;
1299
1300         while (isspace(*tmp))
1301                 ++tmp;
1302         return tmp - str;
1303 }
1304
1305 #define LNKF_BLOCK 8
1306
1307 static enum lnet_nl_key_format yaml_format_type(yaml_emitter_t *emitter,
1308                                                 char *line,
1309                                                 unsigned int *offset)
1310 {
1311         unsigned int indent = *offset, new_indent = 0;
1312         enum lnet_nl_key_format fmt = 0;
1313         char *tmp, *flow;
1314
1315         new_indent = indent_level(line);
1316         if (new_indent < indent) {
1317                 *offset = indent - emitter->best_indent;
1318                 return LNKF_BLOCK;
1319         }
1320
1321         if (strncmp(line + new_indent, "- ", 2) == 0) {
1322                 memset(line + new_indent, ' ', 2);
1323                 /* Eat white spaces physical YAML config files have */
1324                 new_indent += strspn(line + new_indent, " ");
1325                 fmt |= LNKF_SEQUENCE;
1326         }
1327
1328         /* hdr: [ a : 1, b : 2, c : 3 ] */
1329         tmp = strstr(line + new_indent, ": ");
1330         if (!tmp)
1331                 tmp = line + new_indent;
1332         else
1333                 fmt |= LNKF_MAPPING;
1334
1335         flow = strchr(line + new_indent, '{');
1336         if (!flow)
1337                 flow = strchr(line + new_indent, '[');
1338         if (flow) {
1339                 if (flow < tmp)
1340                         fmt &= ~LNKF_MAPPING;
1341                 fmt |= LNKF_FLOW;
1342         } else if (strchr(tmp, '}') || strchr(tmp, ']')) {
1343                 if (strchr(tmp, ']'))
1344                         fmt &= ~LNKF_MAPPING;
1345                 fmt |= LNKF_FLOW;
1346         }
1347
1348         if (indent != new_indent) {
1349                 *offset = new_indent;
1350                 fmt |= LNKF_BLOCK;
1351         }
1352
1353         return fmt;
1354 }
1355
1356 static int yaml_fill_scalar_data(struct nl_msg *msg,
1357                                  enum lnet_nl_key_format fmt,
1358                                  char *line)
1359 {
1360         char *sep = strstr(line, ": "); /* handle mappings */
1361         int rc = 0;
1362         long num;
1363
1364         if (!sep) {
1365                 char *tmp = strchr(line, ':');
1366
1367                 if (tmp && strlen(tmp) == 1) /* handle simple scalar */
1368                         sep = tmp;
1369         }
1370         if (sep)
1371                 *sep = '\0';
1372
1373         if (strspn(line, "-0123456789") == strlen(line)) {
1374                 num = strtoll(line, NULL, 0);
1375
1376                 NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1377         } else {
1378                 NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, line);
1379         }
1380
1381         if (fmt & LNKF_FLOW) {
1382                 memset(line, ' ', strlen(line) + 1);
1383                 goto nla_put_failure;
1384         }
1385
1386         if (fmt & LNKF_MAPPING && sep) {
1387                 char *end = strchr(sep, '\n');
1388                 int len;
1389
1390                 /* restore ':' */
1391                 *sep = ':';
1392                 sep++;
1393                 while (isspace(*sep))
1394                         ++sep;
1395
1396                 len = end ? end - sep : strlen(sep);
1397                 if (len <= 0)
1398                         goto nla_put_failure;
1399                 sep[len] = '\0';
1400
1401                 if (strcasecmp(sep, "yes") == 0 ||
1402                     strcasecmp(sep, "true") == 0 ||
1403                     strcasecmp(sep, "on") == 0 ||
1404                     strcasecmp(sep, "y") == 0) {
1405                         NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, 1);
1406                 } else if (strcasecmp(sep, "no") == 0 ||
1407                            strcasecmp(sep, "false") == 0 ||
1408                            strcasecmp(sep, "off") == 0 ||
1409                            strcasecmp(sep, "n") == 0) {
1410                         NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, 0);
1411                 } else if (strspn(sep, "-0123456789") == strlen(sep)) {
1412                         num = strtoll(sep, NULL, 0);
1413                         NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
1414                 } else {
1415                         NLA_PUT_STRING(msg, LN_SCALAR_ATTR_VALUE, sep);
1416                 }
1417                 sep[len] = '\n';
1418         }
1419 nla_put_failure:
1420         return rc;
1421 }
1422
1423 static int yaml_create_nested_list(struct yaml_netlink_output *out,
1424                                    struct nl_msg *msg, char **hdr,
1425                                    char **entry, unsigned int *indent,
1426                                    enum lnet_nl_key_format fmt)
1427 {
1428         struct nlattr *mapping = NULL, *seq = NULL;
1429         char *line, *tmp;
1430         int rc = 0;
1431
1432         /* Not needed for FLOW only case */
1433         if (fmt & LNKF_SEQUENCE) {
1434                 seq = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1435                 if (!seq) {
1436                         yaml_emitter_set_writer_error(out->emitter,
1437                                                       "Emmitter netlink list creation failed");
1438                         rc = -EINVAL;
1439                         goto nla_put_failure;
1440                 }
1441         }
1442
1443         if (fmt & LNKF_FLOW) {
1444                 struct nlattr *list = NULL;
1445                 bool format = false;
1446                 char *split = NULL;
1447
1448                 if (fmt != LNKF_FLOW) {
1449                         rc = yaml_fill_scalar_data(msg, fmt, *hdr + *indent);
1450                         if (rc < 0)
1451                                 goto nla_put_failure;
1452                 }
1453
1454                 tmp = strchr(*hdr, '{');
1455                 if (!tmp) {
1456                         tmp = strchr(*hdr, '[');
1457                         if (!tmp) {
1458                                 yaml_emitter_set_writer_error(out->emitter,
1459                                                               "Emmitter flow format invalid");
1460                                 rc = -EINVAL;
1461                                 goto nla_put_failure;
1462                         }
1463                         fmt |= LNKF_SEQUENCE;
1464                 } else
1465                         fmt |= LNKF_MAPPING;
1466                 *tmp = ' ';
1467
1468                 list = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1469                 if (!list) {
1470                         yaml_emitter_set_writer_error(out->emitter,
1471                                                       "Emmitter netlink list creation failed");
1472                         rc = -EINVAL;
1473                         goto nla_put_failure;
1474                 }
1475
1476                 fmt &= ~LNKF_FLOW;
1477                 while ((line = strsep(hdr, ",")) != NULL) {
1478                         while (!isalnum(line[0]))
1479                                 line++;
1480
1481                         /* Flow can be splt across lines by libyaml library. */
1482                         if (strchr(line, ',')) {
1483                                 split = line;
1484                                 *hdr = line;
1485                                 continue;
1486                         }
1487
1488                         tmp = strchr(line, '}');
1489                         if (!tmp)
1490                                 tmp = strchr(line, ']');
1491                         if (tmp) {
1492                                 format = true;
1493                                 *tmp = '\0';
1494                         }
1495
1496                         rc = yaml_fill_scalar_data(msg, fmt, line);
1497                         if (rc < 0)
1498                                 goto nla_put_failure;
1499
1500                         /* Move to next YAML line */
1501                         if (format) {
1502                                 if (!split)
1503                                         line = *entry;
1504                                 else
1505                                         *entry = NULL;
1506                                 break;
1507                         }
1508                 }
1509
1510                 if (!format) {
1511                         yaml_emitter_set_writer_error(out->emitter,
1512                                                       "Emmitter flow format invalid");
1513                         rc = -EINVAL;
1514                         goto nla_put_failure;
1515                 }
1516
1517                 if (line && line[0] == '-')
1518                         *indent = 0;
1519
1520                 nla_nest_end(msg, list);
1521         } else {
1522 next_mapping:
1523                 if (fmt & LNKF_BLOCK && strchr(*hdr, ':')) {
1524                         mapping = nla_nest_start(msg, LN_SCALAR_ATTR_LIST);
1525                         if (!mapping) {
1526                                 yaml_emitter_set_writer_error(out->emitter,
1527                                                               "Emmitter netlink list creation failed");
1528                                 rc = -EINVAL;
1529                                 goto nla_put_failure;
1530                         }
1531                 }
1532
1533                 rc = yaml_fill_scalar_data(msg, fmt, *hdr + *indent);
1534                 if (rc < 0)
1535                         goto nla_put_failure;
1536
1537                 do {
1538                         line = strsep(entry, "\n");
1539 have_next_line:
1540                         if (!line || !strlen(line) || strcmp(line, "...") == 0)
1541                                 break;
1542
1543                         fmt = yaml_format_type(out->emitter, line, indent);
1544                         if (fmt == LNKF_BLOCK)
1545                                 break;
1546
1547                         /* sequences of simple scalars, general mappings, and
1548                          * plain scalars are not nested structures in a
1549                          * netlink packet.
1550                          */
1551                         if (fmt == LNKF_SEQUENCE || fmt == LNKF_MAPPING || fmt == 0) {
1552                                 rc = yaml_fill_scalar_data(msg, fmt,
1553                                                            line + *indent);
1554                                 if (rc < 0)
1555                                         goto nla_put_failure;
1556                         } else {
1557                                 rc = yaml_create_nested_list(out, msg, &line,
1558                                                              entry, indent,
1559                                                              fmt);
1560                                 if (rc < 0)
1561                                         goto nla_put_failure;
1562
1563                                 /* if the original line that called
1564                                  * yaml_create_nested_list above was an
1565                                  * sequence and the next line is also
1566                                  * then break to treat it as a mapping / scalar
1567                                  * instead to avoid over nesting.
1568                                  */
1569                                 if (line && seq) {
1570                                         fmt = yaml_format_type(out->emitter, line, indent);
1571                                         if ((fmt & LNKF_SEQUENCE) || (fmt & LNKF_BLOCK))
1572                                                 break;
1573                                 }
1574
1575                                 if (line)
1576                                         goto have_next_line;
1577                         }
1578                 } while (strcmp(*entry, ""));
1579
1580                 if (mapping) {
1581                         nla_nest_end(msg, mapping);
1582                         mapping = NULL;
1583                 }
1584         }
1585
1586         /* test if next line is sequence at the same level. */
1587         if (line && (line[0] != '\0') && (fmt & LNKF_BLOCK)) {
1588                 int old_indent = indent_level(*hdr);
1589
1590                 fmt = yaml_format_type(out->emitter, line, indent);
1591                 if (fmt != LNKF_BLOCK && old_indent == *indent) {
1592                         /* If we have a normal mapping set then treate
1593                          * it as a collection of scalars i.e don't create
1594                          * another nested level. For scalar:\n and plain
1595                          * scalar case we send it to next_mapping to
1596                          * create another nested level.
1597                          */
1598                         tmp = strchr(line, ':');
1599                         if (tmp) {
1600                                 fmt = LNKF_BLOCK;
1601                                 if (strstr(line, ": "))
1602                                         fmt |= LNKF_MAPPING;
1603                                 if (strstr(line, "- "))
1604                                         fmt |= LNKF_SEQUENCE;
1605                                 *hdr = line;
1606                                 goto next_mapping;
1607                         }
1608
1609                         goto have_next_line;
1610                 }
1611         }
1612
1613         if (seq) {
1614                 if (*indent >= 2)
1615                         *indent -= 2;
1616                 nla_nest_end(msg, seq);
1617                 seq = NULL;
1618                 if (*entry && !strlen(*entry) && fmt != LNKF_BLOCK)
1619                         line = NULL;
1620         }
1621
1622         /* strsep in the above loop moves entry to a value pass the end of the
1623          * nested list. So to avoid losing this value we replace hdr with line.
1624          */
1625         *hdr = line;
1626 nla_put_failure:
1627         return rc;
1628 }
1629
1630 /* YAML allows ' and " in its documents but those characters really
1631  * confuse libc string handling. The workaround is to replace
1632  * ' and " with another reserved character for YAML '%' which is
1633  * for tags which shouldn't matter if we send in a Netlink packet.
1634  * The kernel side will need to handle % in a special way.
1635  */
1636 static void yaml_quotation_handling(char *buf)
1637 {
1638         char *tmp = buf, *line;
1639
1640         line = strstr(tmp, "! \'");
1641         if (line)
1642                 line[0] = ' ';
1643
1644         while ((line = strchr(tmp, '\"')) != NULL) {
1645                 line[0] = ' ';
1646                 tmp = strchr(line, '\"');
1647                 tmp[0] = ' ';
1648         }
1649
1650         while ((line = strchr(tmp, '\'')) != NULL) {
1651                 line[0] = ' ';
1652                 tmp = strchr(line, '\'');
1653                 tmp[0] = ' ';
1654         }
1655 }
1656
1657 /* libyaml takes the YAML documents and places the data into an
1658  * internal buffer to the library. We take each line and turn it
1659  * into a Netlink message using the same format as the key table.
1660  * The reason for this approach is that we can do filters at the
1661  * key level or the key + value level.
1662  */
1663 static int yaml_netlink_write_handler(void *data, unsigned char *buffer,
1664                                       size_t size)
1665 {
1666         struct yaml_netlink_output *out = data;
1667         char *buf = strndup((char *)buffer, size);
1668         char *entry = buf, *tmp = buf, *line;
1669         enum lnet_nl_key_format fmt = 0;
1670         struct nl_msg *msg = NULL;
1671         unsigned int indent = 0;
1672         bool nogroups = true;
1673         int rc = 0;
1674
1675         yaml_quotation_handling(entry);
1676
1677         while (entry && strcmp(line = strsep(&entry, "\n"), "")) {
1678 already_have_line:
1679                 if (strcmp(line, "---") == 0 || strcmp(line, "...") == 0)
1680                         continue;
1681
1682                 /* In theory we could have a sequence of groups but a bug in
1683                  * libyaml prevents this from happing
1684                  */
1685                 if (line[0] != ' ' && line[0] != '-') {
1686                         bool extra = false;
1687
1688                         if (strchr(line, '{') || strchr(line, '['))
1689                                 extra = true;
1690
1691                         tmp = strchr(line, ':');
1692                         if (!tmp)
1693                                 continue;
1694                         *tmp = '\0';
1695
1696                         rc = lustre_netlink_add_group(out->nl, out->family,
1697                                                       line);
1698                         if (rc < 0) {
1699                                 yaml_emitter_set_writer_error(out->emitter,
1700                                                               "Netlink group does not exist");
1701                                 goto nla_put_failure;
1702                         }
1703                         nogroups = false;
1704                         /* Handle case first line contains more than a
1705                          * simple key
1706                          */
1707                         if (extra) {
1708                                 *tmp = ' ';
1709                                 line = tmp;
1710                                 goto already_have_line;
1711                         }
1712                 } else {
1713                         if (!msg) {
1714                                 void *usr_hdr;
1715
1716                                 msg = nlmsg_alloc();
1717                                 if (!msg) {
1718                                         out->emitter->error = YAML_MEMORY_ERROR;
1719                                         goto nla_put_failure;
1720                                 }
1721
1722                                 usr_hdr = genlmsg_put(msg, out->pid,
1723                                                       NL_AUTO_SEQ,
1724                                                       out->family_id, 0,
1725                                                       out->flags, out->cmd,
1726                                                       out->version);
1727                                 if (!usr_hdr) {
1728                                         out->emitter->error = YAML_MEMORY_ERROR;
1729                                         nlmsg_free(msg);
1730                                         goto nla_put_failure;
1731                                 }
1732
1733                                 if (line[0] != '-')
1734                                         indent = 2;
1735                         }
1736
1737                         fmt = yaml_format_type(out->emitter, line, &indent);
1738                         if (fmt) {
1739                                 rc = yaml_create_nested_list(out, msg, &line,
1740                                                              &entry, &indent,
1741                                                              fmt);
1742                                 if (rc < 0) {
1743                                         yaml_emitter_set_writer_error(out->emitter,
1744                                                                       nl_geterror(rc));
1745                                         nlmsg_free(msg);
1746                                         goto nla_put_failure;
1747                                 }
1748                                 /* yaml_create_nested_list set line to the next
1749                                  * entry. We can just add it to the msg directly.
1750                                  */
1751                                 if (line)
1752                                         goto already_have_line;
1753                         } else {
1754                                 rc = yaml_fill_scalar_data(msg, fmt,
1755                                                            line + indent);
1756                                 if (rc < 0) {
1757                                         yaml_emitter_set_writer_error(out->emitter,
1758                                                                       nl_geterror(rc));
1759                                         nlmsg_free(msg);
1760                                         goto nla_put_failure;
1761                                 }
1762                         }
1763                 }
1764         }
1765
1766         /* Don't success if no valid groups found */
1767         if (nogroups) {
1768                 yaml_emitter_set_writer_error(out->emitter,
1769                                               "Emitter contains no valid Netlink groups");
1770                 goto nla_put_failure;
1771         }
1772
1773         if (msg) {
1774                 rc = nl_send_auto(out->nl, msg);
1775                 nlmsg_free(msg);
1776         } else {
1777                 rc = genl_send_simple(out->nl, out->family_id, out->cmd,
1778                                       out->version, out->flags);
1779         }
1780         if (rc < 0)
1781                 yaml_emitter_set_writer_error(out->emitter,
1782                                               nl_geterror(rc));
1783 nla_put_failure:
1784         free(buf);
1785         return out->emitter->error == YAML_NO_ERROR ? 1 : 0;
1786 }
1787
1788 /* This function is used by external utilities to use Netlink with
1789  * libyaml so we can turn YAML documentations into Netlink message
1790  * to send. This behavior mirrors yaml_emitter_set_output_file()
1791  * which is used to write out a YAML document to a file.
1792  */
1793 YAML_DECLARE(int)
1794 yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
1795                                 char *family, int version, int cmd, int flags)
1796 {
1797         struct yaml_netlink_output *out;
1798
1799         out = calloc(1, sizeof(*out));
1800         if (!out) {
1801                 sender->error = YAML_MEMORY_ERROR;
1802                 return false;
1803         }
1804
1805         /* Get family ID */
1806         out->family_id = genl_ctrl_resolve(nl, family);
1807         if (out->family_id < 0) {
1808                 yaml_emitter_set_writer_error(sender,
1809                                               "failed to resolve Netlink family id");
1810                 free(out);
1811                 return false;
1812         }
1813
1814         out->emitter = sender;
1815         out->nl = nl;
1816         out->family = family;
1817         out->version = version;
1818         out->cmd = cmd;
1819         out->flags = flags;
1820         out->pid = nl_socket_get_local_port(nl);
1821         yaml_emitter_set_output(sender, yaml_netlink_write_handler, out);
1822         return true;
1823 }
1824
1825 /* Error handling helpers */
1826 void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log)
1827 {
1828         /* YAML_WRITER_ERROR means no Netlink support so use old API */
1829         switch (emitter->error) {
1830         case YAML_MEMORY_ERROR:
1831                 fprintf(log, "Memory error: Not enough memory for emitting\n");
1832                         break;
1833         case YAML_WRITER_ERROR:
1834                 fprintf(log, "Writer error: %s\n", emitter->problem);
1835                 break;
1836         case YAML_EMITTER_ERROR:
1837                 fprintf(log, "Emitter error: %s\n", emitter->problem);
1838         default:
1839                 break;
1840         }
1841 }
1842
1843 void yaml_parser_log_error(yaml_parser_t *parser, FILE *log, const char *errmsg)
1844 {
1845         const char *extra;
1846
1847         switch (parser->error) {
1848         case YAML_MEMORY_ERROR:
1849                 fprintf(log, "Memory error: Not enough memory for parser\n");
1850                 break;
1851
1852         case YAML_SCANNER_ERROR:
1853         case YAML_PARSER_ERROR:
1854                 if (parser->context) {
1855                         fprintf(log,
1856                                 "%s error: %s at line %d, column %d\n%s at line %d, column %d\n",
1857                                 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1858                                 parser->context,
1859                                 (int)parser->context_mark.line + 1,
1860                                 (int)parser->context_mark.column + 1,
1861                                 parser->problem,
1862                                 (int)parser->problem_mark.line + 1,
1863                                 (int)parser->problem_mark.column + 1);
1864                 } else {
1865                         fprintf(log, "%s error: %s at line %d, column %d\n",
1866                                 parser->error == YAML_SCANNER_ERROR ? "Scanner" : "Parser",
1867                                 parser->problem,
1868                                 (int)parser->problem_mark.line + 1,
1869                                 (int)parser->problem_mark.column + 1);
1870                 }
1871                 break;
1872
1873         case YAML_READER_ERROR:
1874                 extra = yaml_parser_get_reader_error(parser);
1875                 if (!extra)
1876                         extra = parser->problem;
1877
1878                 if (parser->problem_value != -1) {
1879                         fprintf(log, "Reader error: '%s':#%X at %ld'\n",
1880                                 extra, parser->problem_value,
1881                                 (long)parser->problem_offset);
1882                 } else {
1883                         fprintf(log, "Reader error: '%s' at %ld\n",
1884                                 extra, (long)parser->problem_offset);
1885                 }
1886                 fallthrough;
1887         default:
1888                 break;
1889         }
1890 }