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