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