~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/net/ynl/lib/ynl.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/net/ynl/lib/ynl.c (Architecture ppc) and /tools/net/ynl/lib/ynl.c (Architecture m68k)


  1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-C      1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2 #include <errno.h>                                  2 #include <errno.h>
  3 #include <poll.h>                                   3 #include <poll.h>
  4 #include <string.h>                                 4 #include <string.h>
  5 #include <stdlib.h>                                 5 #include <stdlib.h>
  6 #include <stdio.h>                                  6 #include <stdio.h>
  7 #include <unistd.h>                                 7 #include <unistd.h>
  8 #include <linux/types.h>                            8 #include <linux/types.h>
  9 #include <linux/genetlink.h>                        9 #include <linux/genetlink.h>
 10 #include <sys/socket.h>                            10 #include <sys/socket.h>
 11                                                    11 
 12 #include "ynl.h"                                   12 #include "ynl.h"
 13                                                    13 
 14 #define ARRAY_SIZE(arr)         (sizeof(arr) /     14 #define ARRAY_SIZE(arr)         (sizeof(arr) / sizeof(*arr))
 15                                                    15 
 16 #define __yerr_msg(yse, _msg...)                   16 #define __yerr_msg(yse, _msg...)                                        \
 17         ({                                         17         ({                                                              \
 18                 struct ynl_error *_yse = (yse)     18                 struct ynl_error *_yse = (yse);                         \
 19                                                    19                                                                         \
 20                 if (_yse) {                        20                 if (_yse) {                                             \
 21                         snprintf(_yse->msg, si     21                         snprintf(_yse->msg, sizeof(_yse->msg) - 1,  _msg); \
 22                         _yse->msg[sizeof(_yse-     22                         _yse->msg[sizeof(_yse->msg) - 1] = 0;           \
 23                 }                                  23                 }                                                       \
 24         })                                         24         })
 25                                                    25 
 26 #define __yerr_code(yse, _code...)                 26 #define __yerr_code(yse, _code...)              \
 27         ({                                         27         ({                                      \
 28                 struct ynl_error *_yse = (yse)     28                 struct ynl_error *_yse = (yse); \
 29                                                    29                                                 \
 30                 if (_yse) {                        30                 if (_yse) {                     \
 31                         _yse->code = _code;        31                         _yse->code = _code;     \
 32                 }                                  32                 }                               \
 33         })                                         33         })
 34                                                    34 
 35 #define __yerr(yse, _code, _msg...)                35 #define __yerr(yse, _code, _msg...)             \
 36         ({                                         36         ({                                      \
 37                 __yerr_msg(yse, _msg);             37                 __yerr_msg(yse, _msg);          \
 38                 __yerr_code(yse, _code);           38                 __yerr_code(yse, _code);        \
 39         })                                         39         })
 40                                                    40 
 41 #define __perr(yse, _msg)               __yerr     41 #define __perr(yse, _msg)               __yerr(yse, errno, _msg)
 42                                                    42 
 43 #define yerr_msg(_ys, _msg...)          __yerr     43 #define yerr_msg(_ys, _msg...)          __yerr_msg(&(_ys)->err, _msg)
 44 #define yerr(_ys, _code, _msg...)       __yerr     44 #define yerr(_ys, _code, _msg...)       __yerr(&(_ys)->err, _code, _msg)
 45 #define perr(_ys, _msg)                 __yerr     45 #define perr(_ys, _msg)                 __yerr(&(_ys)->err, errno, _msg)
 46                                                    46 
 47 /* -- Netlink boiler plate */                      47 /* -- Netlink boiler plate */
 48 static int                                         48 static int
 49 ynl_err_walk_report_one(const struct ynl_polic     49 ynl_err_walk_report_one(const struct ynl_policy_nest *policy, unsigned int type,
 50                         char *str, int str_sz,     50                         char *str, int str_sz, int *n)
 51 {                                                  51 {
 52         if (!policy) {                             52         if (!policy) {
 53                 if (*n < str_sz)                   53                 if (*n < str_sz)
 54                         *n += snprintf(str, st     54                         *n += snprintf(str, str_sz, "!policy");
 55                 return 1;                          55                 return 1;
 56         }                                          56         }
 57                                                    57 
 58         if (type > policy->max_attr) {             58         if (type > policy->max_attr) {
 59                 if (*n < str_sz)                   59                 if (*n < str_sz)
 60                         *n += snprintf(str, st     60                         *n += snprintf(str, str_sz, "!oob");
 61                 return 1;                          61                 return 1;
 62         }                                          62         }
 63                                                    63 
 64         if (!policy->table[type].name) {           64         if (!policy->table[type].name) {
 65                 if (*n < str_sz)                   65                 if (*n < str_sz)
 66                         *n += snprintf(str, st     66                         *n += snprintf(str, str_sz, "!name");
 67                 return 1;                          67                 return 1;
 68         }                                          68         }
 69                                                    69 
 70         if (*n < str_sz)                           70         if (*n < str_sz)
 71                 *n += snprintf(str, str_sz - *     71                 *n += snprintf(str, str_sz - *n,
 72                                ".%s", policy->     72                                ".%s", policy->table[type].name);
 73         return 0;                                  73         return 0;
 74 }                                                  74 }
 75                                                    75 
 76 static int                                         76 static int
 77 ynl_err_walk(struct ynl_sock *ys, void *start,     77 ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
 78              const struct ynl_policy_nest *pol     78              const struct ynl_policy_nest *policy, char *str, int str_sz,
 79              const struct ynl_policy_nest **ne     79              const struct ynl_policy_nest **nest_pol)
 80 {                                                  80 {
 81         unsigned int astart_off, aend_off;         81         unsigned int astart_off, aend_off;
 82         const struct nlattr *attr;                 82         const struct nlattr *attr;
 83         unsigned int data_len;                     83         unsigned int data_len;
 84         unsigned int type;                         84         unsigned int type;
 85         bool found = false;                        85         bool found = false;
 86         int n = 0;                                 86         int n = 0;
 87                                                    87 
 88         if (!policy) {                             88         if (!policy) {
 89                 if (n < str_sz)                    89                 if (n < str_sz)
 90                         n += snprintf(str, str     90                         n += snprintf(str, str_sz, "!policy");
 91                 return n;                          91                 return n;
 92         }                                          92         }
 93                                                    93 
 94         data_len = end - start;                    94         data_len = end - start;
 95                                                    95 
 96         ynl_attr_for_each_payload(start, data_     96         ynl_attr_for_each_payload(start, data_len, attr) {
 97                 astart_off = (char *)attr - (c     97                 astart_off = (char *)attr - (char *)start;
 98                 aend_off = astart_off + ynl_at     98                 aend_off = astart_off + ynl_attr_data_len(attr);
 99                 if (aend_off <= off)               99                 if (aend_off <= off)
100                         continue;                 100                         continue;
101                                                   101 
102                 found = true;                     102                 found = true;
103                 break;                            103                 break;
104         }                                         104         }
105         if (!found)                               105         if (!found)
106                 return 0;                         106                 return 0;
107                                                   107 
108         off -= astart_off;                        108         off -= astart_off;
109                                                   109 
110         type = ynl_attr_type(attr);               110         type = ynl_attr_type(attr);
111                                                   111 
112         if (ynl_err_walk_report_one(policy, ty    112         if (ynl_err_walk_report_one(policy, type, str, str_sz, &n))
113                 return n;                         113                 return n;
114                                                   114 
115         if (!off) {                               115         if (!off) {
116                 if (nest_pol)                     116                 if (nest_pol)
117                         *nest_pol = policy->ta    117                         *nest_pol = policy->table[type].nest;
118                 return n;                         118                 return n;
119         }                                         119         }
120                                                   120 
121         if (!policy->table[type].nest) {          121         if (!policy->table[type].nest) {
122                 if (n < str_sz)                   122                 if (n < str_sz)
123                         n += snprintf(str, str    123                         n += snprintf(str, str_sz, "!nest");
124                 return n;                         124                 return n;
125         }                                         125         }
126                                                   126 
127         off -= sizeof(struct nlattr);             127         off -= sizeof(struct nlattr);
128         start =  ynl_attr_data(attr);             128         start =  ynl_attr_data(attr);
129         end = start + ynl_attr_data_len(attr);    129         end = start + ynl_attr_data_len(attr);
130                                                   130 
131         return n + ynl_err_walk(ys, start, end    131         return n + ynl_err_walk(ys, start, end, off, policy->table[type].nest,
132                                 &str[n], str_s    132                                 &str[n], str_sz - n, nest_pol);
133 }                                                 133 }
134                                                   134 
135 #define NLMSGERR_ATTR_MISS_TYPE (NLMSGERR_ATTR    135 #define NLMSGERR_ATTR_MISS_TYPE (NLMSGERR_ATTR_POLICY + 1)
136 #define NLMSGERR_ATTR_MISS_NEST (NLMSGERR_ATTR    136 #define NLMSGERR_ATTR_MISS_NEST (NLMSGERR_ATTR_POLICY + 2)
137 #define NLMSGERR_ATTR_MAX (NLMSGERR_ATTR_MAX +    137 #define NLMSGERR_ATTR_MAX (NLMSGERR_ATTR_MAX + 2)
138                                                   138 
139 static int                                        139 static int
140 ynl_ext_ack_check(struct ynl_sock *ys, const s    140 ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
141                   unsigned int hlen)              141                   unsigned int hlen)
142 {                                                 142 {
143         const struct nlattr *tb[NLMSGERR_ATTR_    143         const struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
144         char miss_attr[sizeof(ys->err.msg)];      144         char miss_attr[sizeof(ys->err.msg)];
145         char bad_attr[sizeof(ys->err.msg)];       145         char bad_attr[sizeof(ys->err.msg)];
146         const struct nlattr *attr;                146         const struct nlattr *attr;
147         const char *str = NULL;                   147         const char *str = NULL;
148                                                   148 
149         if (!(nlh->nlmsg_flags & NLM_F_ACK_TLV    149         if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) {
150                 yerr_msg(ys, "%s", strerror(ys    150                 yerr_msg(ys, "%s", strerror(ys->err.code));
151                 return YNL_PARSE_CB_OK;           151                 return YNL_PARSE_CB_OK;
152         }                                         152         }
153                                                   153 
154         ynl_attr_for_each(attr, nlh, hlen) {      154         ynl_attr_for_each(attr, nlh, hlen) {
155                 unsigned int len, type;           155                 unsigned int len, type;
156                                                   156 
157                 len = ynl_attr_data_len(attr);    157                 len = ynl_attr_data_len(attr);
158                 type = ynl_attr_type(attr);       158                 type = ynl_attr_type(attr);
159                                                   159 
160                 if (type > NLMSGERR_ATTR_MAX)     160                 if (type > NLMSGERR_ATTR_MAX)
161                         continue;                 161                         continue;
162                                                   162 
163                 tb[type] = attr;                  163                 tb[type] = attr;
164                                                   164 
165                 switch (type) {                   165                 switch (type) {
166                 case NLMSGERR_ATTR_OFFS:          166                 case NLMSGERR_ATTR_OFFS:
167                 case NLMSGERR_ATTR_MISS_TYPE:     167                 case NLMSGERR_ATTR_MISS_TYPE:
168                 case NLMSGERR_ATTR_MISS_NEST:     168                 case NLMSGERR_ATTR_MISS_NEST:
169                         if (len != sizeof(__u3    169                         if (len != sizeof(__u32))
170                                 return YNL_PAR    170                                 return YNL_PARSE_CB_ERROR;
171                         break;                    171                         break;
172                 case NLMSGERR_ATTR_MSG:           172                 case NLMSGERR_ATTR_MSG:
173                         str = ynl_attr_get_str    173                         str = ynl_attr_get_str(attr);
174                         if (str[len - 1])         174                         if (str[len - 1])
175                                 return YNL_PAR    175                                 return YNL_PARSE_CB_ERROR;
176                         break;                    176                         break;
177                 default:                          177                 default:
178                         break;                    178                         break;
179                 }                                 179                 }
180         }                                         180         }
181                                                   181 
182         bad_attr[0] = '\0';                       182         bad_attr[0] = '\0';
183         miss_attr[0] = '\0';                      183         miss_attr[0] = '\0';
184                                                   184 
185         if (tb[NLMSGERR_ATTR_OFFS]) {             185         if (tb[NLMSGERR_ATTR_OFFS]) {
186                 unsigned int n, off;              186                 unsigned int n, off;
187                 void *start, *end;                187                 void *start, *end;
188                                                   188 
189                 ys->err.attr_offs = ynl_attr_g    189                 ys->err.attr_offs = ynl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
190                                                   190 
191                 n = snprintf(bad_attr, sizeof(    191                 n = snprintf(bad_attr, sizeof(bad_attr), "%sbad attribute: ",
192                              str ? " (" : "");    192                              str ? " (" : "");
193                                                   193 
194                 start = ynl_nlmsg_data_offset(    194                 start = ynl_nlmsg_data_offset(ys->nlh, ys->family->hdr_len);
195                 end = ynl_nlmsg_end_addr(ys->n    195                 end = ynl_nlmsg_end_addr(ys->nlh);
196                                                   196 
197                 off = ys->err.attr_offs;          197                 off = ys->err.attr_offs;
198                 off -= sizeof(struct nlmsghdr)    198                 off -= sizeof(struct nlmsghdr);
199                 off -= ys->family->hdr_len;       199                 off -= ys->family->hdr_len;
200                                                   200 
201                 n += ynl_err_walk(ys, start, e    201                 n += ynl_err_walk(ys, start, end, off, ys->req_policy,
202                                   &bad_attr[n]    202                                   &bad_attr[n], sizeof(bad_attr) - n, NULL);
203                                                   203 
204                 if (n >= sizeof(bad_attr))        204                 if (n >= sizeof(bad_attr))
205                         n = sizeof(bad_attr) -    205                         n = sizeof(bad_attr) - 1;
206                 bad_attr[n] = '\0';               206                 bad_attr[n] = '\0';
207         }                                         207         }
208         if (tb[NLMSGERR_ATTR_MISS_TYPE]) {        208         if (tb[NLMSGERR_ATTR_MISS_TYPE]) {
209                 const struct ynl_policy_nest *    209                 const struct ynl_policy_nest *nest_pol = NULL;
210                 unsigned int n, off, type;        210                 unsigned int n, off, type;
211                 void *start, *end;                211                 void *start, *end;
212                 int n2;                           212                 int n2;
213                                                   213 
214                 type = ynl_attr_get_u32(tb[NLM    214                 type = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_TYPE]);
215                                                   215 
216                 n = snprintf(miss_attr, sizeof    216                 n = snprintf(miss_attr, sizeof(miss_attr), "%smissing attribute: ",
217                              bad_attr[0] ? ",     217                              bad_attr[0] ? ", " : (str ? " (" : ""));
218                                                   218 
219                 start = ynl_nlmsg_data_offset(    219                 start = ynl_nlmsg_data_offset(ys->nlh, ys->family->hdr_len);
220                 end = ynl_nlmsg_end_addr(ys->n    220                 end = ynl_nlmsg_end_addr(ys->nlh);
221                                                   221 
222                 nest_pol = ys->req_policy;        222                 nest_pol = ys->req_policy;
223                 if (tb[NLMSGERR_ATTR_MISS_NEST    223                 if (tb[NLMSGERR_ATTR_MISS_NEST]) {
224                         off = ynl_attr_get_u32    224                         off = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
225                         off -= sizeof(struct n    225                         off -= sizeof(struct nlmsghdr);
226                         off -= ys->family->hdr    226                         off -= ys->family->hdr_len;
227                                                   227 
228                         n += ynl_err_walk(ys,     228                         n += ynl_err_walk(ys, start, end, off, ys->req_policy,
229                                           &mis    229                                           &miss_attr[n], sizeof(miss_attr) - n,
230                                           &nes    230                                           &nest_pol);
231                 }                                 231                 }
232                                                   232 
233                 n2 = 0;                           233                 n2 = 0;
234                 ynl_err_walk_report_one(nest_p    234                 ynl_err_walk_report_one(nest_pol, type, &miss_attr[n],
235                                         sizeof    235                                         sizeof(miss_attr) - n, &n2);
236                 n += n2;                          236                 n += n2;
237                                                   237 
238                 if (n >= sizeof(miss_attr))       238                 if (n >= sizeof(miss_attr))
239                         n = sizeof(miss_attr)     239                         n = sizeof(miss_attr) - 1;
240                 miss_attr[n] = '\0';              240                 miss_attr[n] = '\0';
241         }                                         241         }
242                                                   242 
243         /* Implicitly depend on ys->err.code a    243         /* Implicitly depend on ys->err.code already set */
244         if (str)                                  244         if (str)
245                 yerr_msg(ys, "Kernel %s: '%s'%    245                 yerr_msg(ys, "Kernel %s: '%s'%s%s%s",
246                          ys->err.code ? "error    246                          ys->err.code ? "error" : "warning",
247                          str, bad_attr, miss_a    247                          str, bad_attr, miss_attr,
248                          bad_attr[0] || miss_a    248                          bad_attr[0] || miss_attr[0] ? ")" : "");
249         else if (bad_attr[0] || miss_attr[0])     249         else if (bad_attr[0] || miss_attr[0])
250                 yerr_msg(ys, "Kernel %s: %s%s"    250                 yerr_msg(ys, "Kernel %s: %s%s",
251                          ys->err.code ? "error    251                          ys->err.code ? "error" : "warning",
252                          bad_attr, miss_attr);    252                          bad_attr, miss_attr);
253         else                                      253         else
254                 yerr_msg(ys, "%s", strerror(ys    254                 yerr_msg(ys, "%s", strerror(ys->err.code));
255                                                   255 
256         return YNL_PARSE_CB_OK;                   256         return YNL_PARSE_CB_OK;
257 }                                                 257 }
258                                                   258 
259 static int                                        259 static int
260 ynl_cb_error(const struct nlmsghdr *nlh, struc    260 ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
261 {                                                 261 {
262         const struct nlmsgerr *err = ynl_nlmsg    262         const struct nlmsgerr *err = ynl_nlmsg_data(nlh);
263         unsigned int hlen;                        263         unsigned int hlen;
264         int code;                                 264         int code;
265                                                   265 
266         code = err->error >= 0 ? err->error :     266         code = err->error >= 0 ? err->error : -err->error;
267         yarg->ys->err.code = code;                267         yarg->ys->err.code = code;
268         errno = code;                             268         errno = code;
269                                                   269 
270         hlen = sizeof(*err);                      270         hlen = sizeof(*err);
271         if (!(nlh->nlmsg_flags & NLM_F_CAPPED)    271         if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
272                 hlen += ynl_nlmsg_data_len(&er    272                 hlen += ynl_nlmsg_data_len(&err->msg);
273                                                   273 
274         ynl_ext_ack_check(yarg->ys, nlh, hlen)    274         ynl_ext_ack_check(yarg->ys, nlh, hlen);
275                                                   275 
276         return code ? YNL_PARSE_CB_ERROR : YNL    276         return code ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_STOP;
277 }                                                 277 }
278                                                   278 
279 static int ynl_cb_done(const struct nlmsghdr *    279 static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
280 {                                                 280 {
281         int err;                                  281         int err;
282                                                   282 
283         err = *(int *)NLMSG_DATA(nlh);            283         err = *(int *)NLMSG_DATA(nlh);
284         if (err < 0) {                            284         if (err < 0) {
285                 yarg->ys->err.code = -err;        285                 yarg->ys->err.code = -err;
286                 errno = -err;                     286                 errno = -err;
287                                                   287 
288                 ynl_ext_ack_check(yarg->ys, nl    288                 ynl_ext_ack_check(yarg->ys, nlh, sizeof(int));
289                                                   289 
290                 return YNL_PARSE_CB_ERROR;        290                 return YNL_PARSE_CB_ERROR;
291         }                                         291         }
292         return YNL_PARSE_CB_STOP;                 292         return YNL_PARSE_CB_STOP;
293 }                                                 293 }
294                                                   294 
295 /* Attribute validation */                        295 /* Attribute validation */
296                                                   296 
297 int ynl_attr_validate(struct ynl_parse_arg *ya    297 int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
298 {                                                 298 {
299         const struct ynl_policy_attr *policy;     299         const struct ynl_policy_attr *policy;
300         unsigned int type, len;                   300         unsigned int type, len;
301         unsigned char *data;                      301         unsigned char *data;
302                                                   302 
303         data = ynl_attr_data(attr);               303         data = ynl_attr_data(attr);
304         len = ynl_attr_data_len(attr);            304         len = ynl_attr_data_len(attr);
305         type = ynl_attr_type(attr);               305         type = ynl_attr_type(attr);
306         if (type > yarg->rsp_policy->max_attr)    306         if (type > yarg->rsp_policy->max_attr) {
307                 yerr(yarg->ys, YNL_ERROR_INTER    307                 yerr(yarg->ys, YNL_ERROR_INTERNAL,
308                      "Internal error, validati    308                      "Internal error, validating unknown attribute");
309                 return -1;                        309                 return -1;
310         }                                         310         }
311                                                   311 
312         policy = &yarg->rsp_policy->table[type    312         policy = &yarg->rsp_policy->table[type];
313                                                   313 
314         switch (policy->type) {                   314         switch (policy->type) {
315         case YNL_PT_REJECT:                       315         case YNL_PT_REJECT:
316                 yerr(yarg->ys, YNL_ERROR_ATTR_    316                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
317                      "Rejected attribute (%s)"    317                      "Rejected attribute (%s)", policy->name);
318                 return -1;                        318                 return -1;
319         case YNL_PT_IGNORE:                       319         case YNL_PT_IGNORE:
320                 break;                            320                 break;
321         case YNL_PT_U8:                           321         case YNL_PT_U8:
322                 if (len == sizeof(__u8))          322                 if (len == sizeof(__u8))
323                         break;                    323                         break;
324                 yerr(yarg->ys, YNL_ERROR_ATTR_    324                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
325                      "Invalid attribute (u8 %s    325                      "Invalid attribute (u8 %s)", policy->name);
326                 return -1;                        326                 return -1;
327         case YNL_PT_U16:                          327         case YNL_PT_U16:
328                 if (len == sizeof(__u16))         328                 if (len == sizeof(__u16))
329                         break;                    329                         break;
330                 yerr(yarg->ys, YNL_ERROR_ATTR_    330                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
331                      "Invalid attribute (u16 %    331                      "Invalid attribute (u16 %s)", policy->name);
332                 return -1;                        332                 return -1;
333         case YNL_PT_U32:                          333         case YNL_PT_U32:
334                 if (len == sizeof(__u32))         334                 if (len == sizeof(__u32))
335                         break;                    335                         break;
336                 yerr(yarg->ys, YNL_ERROR_ATTR_    336                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
337                      "Invalid attribute (u32 %    337                      "Invalid attribute (u32 %s)", policy->name);
338                 return -1;                        338                 return -1;
339         case YNL_PT_U64:                          339         case YNL_PT_U64:
340                 if (len == sizeof(__u64))         340                 if (len == sizeof(__u64))
341                         break;                    341                         break;
342                 yerr(yarg->ys, YNL_ERROR_ATTR_    342                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
343                      "Invalid attribute (u64 %    343                      "Invalid attribute (u64 %s)", policy->name);
344                 return -1;                        344                 return -1;
345         case YNL_PT_UINT:                         345         case YNL_PT_UINT:
346                 if (len == sizeof(__u32) || le    346                 if (len == sizeof(__u32) || len == sizeof(__u64))
347                         break;                    347                         break;
348                 yerr(yarg->ys, YNL_ERROR_ATTR_    348                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
349                      "Invalid attribute (uint     349                      "Invalid attribute (uint %s)", policy->name);
350                 return -1;                        350                 return -1;
351         case YNL_PT_FLAG:                         351         case YNL_PT_FLAG:
352                 /* Let flags grow into real at    352                 /* Let flags grow into real attrs, why not.. */
353                 break;                            353                 break;
354         case YNL_PT_NEST:                         354         case YNL_PT_NEST:
355                 if (!len || len >= sizeof(*att    355                 if (!len || len >= sizeof(*attr))
356                         break;                    356                         break;
357                 yerr(yarg->ys, YNL_ERROR_ATTR_    357                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
358                      "Invalid attribute (nest     358                      "Invalid attribute (nest %s)", policy->name);
359                 return -1;                        359                 return -1;
360         case YNL_PT_BINARY:                       360         case YNL_PT_BINARY:
361                 if (!policy->len || len == pol    361                 if (!policy->len || len == policy->len)
362                         break;                    362                         break;
363                 yerr(yarg->ys, YNL_ERROR_ATTR_    363                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
364                      "Invalid attribute (binar    364                      "Invalid attribute (binary %s)", policy->name);
365                 return -1;                        365                 return -1;
366         case YNL_PT_NUL_STR:                      366         case YNL_PT_NUL_STR:
367                 if ((!policy->len || len <= po    367                 if ((!policy->len || len <= policy->len) && !data[len - 1])
368                         break;                    368                         break;
369                 yerr(yarg->ys, YNL_ERROR_ATTR_    369                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
370                      "Invalid attribute (strin    370                      "Invalid attribute (string %s)", policy->name);
371                 return -1;                        371                 return -1;
372         case YNL_PT_BITFIELD32:                   372         case YNL_PT_BITFIELD32:
373                 if (len == sizeof(struct nla_b    373                 if (len == sizeof(struct nla_bitfield32))
374                         break;                    374                         break;
375                 yerr(yarg->ys, YNL_ERROR_ATTR_    375                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
376                      "Invalid attribute (bitfi    376                      "Invalid attribute (bitfield32 %s)", policy->name);
377                 return -1;                        377                 return -1;
378         default:                                  378         default:
379                 yerr(yarg->ys, YNL_ERROR_ATTR_    379                 yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
380                      "Invalid attribute (unkno    380                      "Invalid attribute (unknown %s)", policy->name);
381                 return -1;                        381                 return -1;
382         }                                         382         }
383                                                   383 
384         return 0;                                 384         return 0;
385 }                                                 385 }
386                                                   386 
387 /* Generic code */                                387 /* Generic code */
388                                                   388 
389 static void ynl_err_reset(struct ynl_sock *ys)    389 static void ynl_err_reset(struct ynl_sock *ys)
390 {                                                 390 {
391         ys->err.code = 0;                         391         ys->err.code = 0;
392         ys->err.attr_offs = 0;                    392         ys->err.attr_offs = 0;
393         ys->err.msg[0] = 0;                       393         ys->err.msg[0] = 0;
394 }                                                 394 }
395                                                   395 
396 struct nlmsghdr *ynl_msg_start(struct ynl_sock    396 struct nlmsghdr *ynl_msg_start(struct ynl_sock *ys, __u32 id, __u16 flags)
397 {                                                 397 {
398         struct nlmsghdr *nlh;                     398         struct nlmsghdr *nlh;
399                                                   399 
400         ynl_err_reset(ys);                        400         ynl_err_reset(ys);
401                                                   401 
402         nlh = ys->nlh = ynl_nlmsg_put_header(y    402         nlh = ys->nlh = ynl_nlmsg_put_header(ys->tx_buf);
403         nlh->nlmsg_type = id;                     403         nlh->nlmsg_type = id;
404         nlh->nlmsg_flags = flags;                 404         nlh->nlmsg_flags = flags;
405         nlh->nlmsg_seq = ++ys->seq;               405         nlh->nlmsg_seq = ++ys->seq;
406                                                   406 
407         /* This is a local YNL hack for length    407         /* This is a local YNL hack for length checking, we put the buffer
408          * length in nlmsg_pid, since messages    408          * length in nlmsg_pid, since messages sent to the kernel always use
409          * PID 0. Message needs to be terminat    409          * PID 0. Message needs to be terminated with ynl_msg_end().
410          */                                       410          */
411         nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZ    411         nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZE;
412                                                   412 
413         return nlh;                               413         return nlh;
414 }                                                 414 }
415                                                   415 
416 static int ynl_msg_end(struct ynl_sock *ys, st    416 static int ynl_msg_end(struct ynl_sock *ys, struct nlmsghdr *nlh)
417 {                                                 417 {
418         /* We stash buffer length in nlmsg_pid    418         /* We stash buffer length in nlmsg_pid. */
419         if (nlh->nlmsg_pid == 0) {                419         if (nlh->nlmsg_pid == 0) {
420                 yerr(ys, YNL_ERROR_INPUT_INVAL    420                 yerr(ys, YNL_ERROR_INPUT_INVALID,
421                      "Unknown input buffer len    421                      "Unknown input buffer length");
422                 return -EINVAL;                   422                 return -EINVAL;
423         }                                         423         }
424         if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW    424         if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW) {
425                 yerr(ys, YNL_ERROR_INPUT_TOO_B    425                 yerr(ys, YNL_ERROR_INPUT_TOO_BIG,
426                      "Constructed message long    426                      "Constructed message longer than internal buffer");
427                 return -EMSGSIZE;                 427                 return -EMSGSIZE;
428         }                                         428         }
429                                                   429 
430         nlh->nlmsg_pid = 0;                       430         nlh->nlmsg_pid = 0;
431         return 0;                                 431         return 0;
432 }                                                 432 }
433                                                   433 
434 struct nlmsghdr *                                 434 struct nlmsghdr *
435 ynl_gemsg_start(struct ynl_sock *ys, __u32 id,    435 ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags,
436                 __u8 cmd, __u8 version)           436                 __u8 cmd, __u8 version)
437 {                                                 437 {
438         struct genlmsghdr gehdr;                  438         struct genlmsghdr gehdr;
439         struct nlmsghdr *nlh;                     439         struct nlmsghdr *nlh;
440         void *data;                               440         void *data;
441                                                   441 
442         nlh = ynl_msg_start(ys, id, flags);       442         nlh = ynl_msg_start(ys, id, flags);
443                                                   443 
444         memset(&gehdr, 0, sizeof(gehdr));         444         memset(&gehdr, 0, sizeof(gehdr));
445         gehdr.cmd = cmd;                          445         gehdr.cmd = cmd;
446         gehdr.version = version;                  446         gehdr.version = version;
447                                                   447 
448         data = ynl_nlmsg_put_extra_header(nlh,    448         data = ynl_nlmsg_put_extra_header(nlh, sizeof(gehdr));
449         memcpy(data, &gehdr, sizeof(gehdr));      449         memcpy(data, &gehdr, sizeof(gehdr));
450                                                   450 
451         return nlh;                               451         return nlh;
452 }                                                 452 }
453                                                   453 
454 void ynl_msg_start_req(struct ynl_sock *ys, __    454 void ynl_msg_start_req(struct ynl_sock *ys, __u32 id)
455 {                                                 455 {
456         ynl_msg_start(ys, id, NLM_F_REQUEST |     456         ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK);
457 }                                                 457 }
458                                                   458 
459 void ynl_msg_start_dump(struct ynl_sock *ys, _    459 void ynl_msg_start_dump(struct ynl_sock *ys, __u32 id)
460 {                                                 460 {
461         ynl_msg_start(ys, id, NLM_F_REQUEST |     461         ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
462 }                                                 462 }
463                                                   463 
464 struct nlmsghdr *                                 464 struct nlmsghdr *
465 ynl_gemsg_start_req(struct ynl_sock *ys, __u32    465 ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
466 {                                                 466 {
467         return ynl_gemsg_start(ys, id, NLM_F_R    467         return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK, cmd, version);
468 }                                                 468 }
469                                                   469 
470 struct nlmsghdr *                                 470 struct nlmsghdr *
471 ynl_gemsg_start_dump(struct ynl_sock *ys, __u3    471 ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
472 {                                                 472 {
473         return ynl_gemsg_start(ys, id, NLM_F_R    473         return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,
474                                cmd, version);     474                                cmd, version);
475 }                                                 475 }
476                                                   476 
477 static int ynl_cb_null(const struct nlmsghdr *    477 static int ynl_cb_null(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
478 {                                                 478 {
479         yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG,    479         yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG,
480              "Received a message when none wer    480              "Received a message when none were expected");
481                                                   481 
482         return YNL_PARSE_CB_ERROR;                482         return YNL_PARSE_CB_ERROR;
483 }                                                 483 }
484                                                   484 
485 static int                                        485 static int
486 __ynl_sock_read_msgs(struct ynl_parse_arg *yar    486 __ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb, int flags)
487 {                                                 487 {
488         struct ynl_sock *ys = yarg->ys;           488         struct ynl_sock *ys = yarg->ys;
489         const struct nlmsghdr *nlh;               489         const struct nlmsghdr *nlh;
490         ssize_t len, rem;                         490         ssize_t len, rem;
491         int ret;                                  491         int ret;
492                                                   492 
493         len = recv(ys->socket, ys->rx_buf, YNL    493         len = recv(ys->socket, ys->rx_buf, YNL_SOCKET_BUFFER_SIZE, flags);
494         if (len < 0) {                            494         if (len < 0) {
495                 if (flags & MSG_DONTWAIT && er    495                 if (flags & MSG_DONTWAIT && errno == EAGAIN)
496                         return YNL_PARSE_CB_ST    496                         return YNL_PARSE_CB_STOP;
497                 return len;                       497                 return len;
498         }                                         498         }
499                                                   499 
500         ret = YNL_PARSE_CB_STOP;                  500         ret = YNL_PARSE_CB_STOP;
501         for (rem = len; rem > 0; NLMSG_NEXT(nl    501         for (rem = len; rem > 0; NLMSG_NEXT(nlh, rem)) {
502                 nlh = (struct nlmsghdr *)&ys->    502                 nlh = (struct nlmsghdr *)&ys->rx_buf[len - rem];
503                 if (!NLMSG_OK(nlh, rem)) {        503                 if (!NLMSG_OK(nlh, rem)) {
504                         yerr(yarg->ys, YNL_ERR    504                         yerr(yarg->ys, YNL_ERROR_INV_RESP,
505                              "Invalid message     505                              "Invalid message or trailing data in the response.");
506                         return YNL_PARSE_CB_ER    506                         return YNL_PARSE_CB_ERROR;
507                 }                                 507                 }
508                                                   508 
509                 if (nlh->nlmsg_flags & NLM_F_D    509                 if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
510                         /* TODO: handle this b    510                         /* TODO: handle this better */
511                         yerr(yarg->ys, YNL_ERR    511                         yerr(yarg->ys, YNL_ERROR_DUMP_INTER,
512                              "Dump interrupted    512                              "Dump interrupted / inconsistent, please retry.");
513                         return YNL_PARSE_CB_ER    513                         return YNL_PARSE_CB_ERROR;
514                 }                                 514                 }
515                                                   515 
516                 switch (nlh->nlmsg_type) {        516                 switch (nlh->nlmsg_type) {
517                 case 0:                           517                 case 0:
518                         yerr(yarg->ys, YNL_ERR    518                         yerr(yarg->ys, YNL_ERROR_INV_RESP,
519                              "Invalid message     519                              "Invalid message type in the response.");
520                         return YNL_PARSE_CB_ER    520                         return YNL_PARSE_CB_ERROR;
521                 case NLMSG_NOOP:                  521                 case NLMSG_NOOP:
522                 case NLMSG_OVERRUN ... NLMSG_M    522                 case NLMSG_OVERRUN ... NLMSG_MIN_TYPE - 1:
523                         ret = YNL_PARSE_CB_OK;    523                         ret = YNL_PARSE_CB_OK;
524                         break;                    524                         break;
525                 case NLMSG_ERROR:                 525                 case NLMSG_ERROR:
526                         ret = ynl_cb_error(nlh    526                         ret = ynl_cb_error(nlh, yarg);
527                         break;                    527                         break;
528                 case NLMSG_DONE:                  528                 case NLMSG_DONE:
529                         ret = ynl_cb_done(nlh,    529                         ret = ynl_cb_done(nlh, yarg);
530                         break;                    530                         break;
531                 default:                          531                 default:
532                         ret = cb(nlh, yarg);      532                         ret = cb(nlh, yarg);
533                         break;                    533                         break;
534                 }                                 534                 }
535         }                                         535         }
536                                                   536 
537         return ret;                               537         return ret;
538 }                                                 538 }
539                                                   539 
540 static int ynl_sock_read_msgs(struct ynl_parse    540 static int ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb)
541 {                                                 541 {
542         return __ynl_sock_read_msgs(yarg, cb,     542         return __ynl_sock_read_msgs(yarg, cb, 0);
543 }                                                 543 }
544                                                   544 
545 static int ynl_recv_ack(struct ynl_sock *ys, i    545 static int ynl_recv_ack(struct ynl_sock *ys, int ret)
546 {                                                 546 {
547         struct ynl_parse_arg yarg = { .ys = ys    547         struct ynl_parse_arg yarg = { .ys = ys, };
548                                                   548 
549         if (!ret) {                               549         if (!ret) {
550                 yerr(ys, YNL_ERROR_EXPECT_ACK,    550                 yerr(ys, YNL_ERROR_EXPECT_ACK,
551                      "Expecting an ACK but not    551                      "Expecting an ACK but nothing received");
552                 return -1;                        552                 return -1;
553         }                                         553         }
554                                                   554 
555         return ynl_sock_read_msgs(&yarg, ynl_c    555         return ynl_sock_read_msgs(&yarg, ynl_cb_null);
556 }                                                 556 }
557                                                   557 
558 /* Init/fini and genetlink boiler plate */        558 /* Init/fini and genetlink boiler plate */
559 static int                                        559 static int
560 ynl_get_family_info_mcast(struct ynl_sock *ys,    560 ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts)
561 {                                                 561 {
562         const struct nlattr *entry, *attr;        562         const struct nlattr *entry, *attr;
563         unsigned int i;                           563         unsigned int i;
564                                                   564 
565         ynl_attr_for_each_nested(attr, mcasts)    565         ynl_attr_for_each_nested(attr, mcasts)
566                 ys->n_mcast_groups++;             566                 ys->n_mcast_groups++;
567                                                   567 
568         if (!ys->n_mcast_groups)                  568         if (!ys->n_mcast_groups)
569                 return 0;                         569                 return 0;
570                                                   570 
571         ys->mcast_groups = calloc(ys->n_mcast_    571         ys->mcast_groups = calloc(ys->n_mcast_groups,
572                                   sizeof(*ys->    572                                   sizeof(*ys->mcast_groups));
573         if (!ys->mcast_groups)                    573         if (!ys->mcast_groups)
574                 return YNL_PARSE_CB_ERROR;        574                 return YNL_PARSE_CB_ERROR;
575                                                   575 
576         i = 0;                                    576         i = 0;
577         ynl_attr_for_each_nested(entry, mcasts    577         ynl_attr_for_each_nested(entry, mcasts) {
578                 ynl_attr_for_each_nested(attr,    578                 ynl_attr_for_each_nested(attr, entry) {
579                         if (ynl_attr_type(attr    579                         if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_ID)
580                                 ys->mcast_grou    580                                 ys->mcast_groups[i].id = ynl_attr_get_u32(attr);
581                         if (ynl_attr_type(attr    581                         if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_NAME) {
582                                 strncpy(ys->mc    582                                 strncpy(ys->mcast_groups[i].name,
583                                         ynl_at    583                                         ynl_attr_get_str(attr),
584                                         GENL_N    584                                         GENL_NAMSIZ - 1);
585                                 ys->mcast_grou    585                                 ys->mcast_groups[i].name[GENL_NAMSIZ - 1] = 0;
586                         }                         586                         }
587                 }                                 587                 }
588                 i++;                              588                 i++;
589         }                                         589         }
590                                                   590 
591         return 0;                                 591         return 0;
592 }                                                 592 }
593                                                   593 
594 static int                                        594 static int
595 ynl_get_family_info_cb(const struct nlmsghdr *    595 ynl_get_family_info_cb(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
596 {                                                 596 {
597         struct ynl_sock *ys = yarg->ys;           597         struct ynl_sock *ys = yarg->ys;
598         const struct nlattr *attr;                598         const struct nlattr *attr;
599         bool found_id = true;                     599         bool found_id = true;
600                                                   600 
601         ynl_attr_for_each(attr, nlh, sizeof(st    601         ynl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
602                 if (ynl_attr_type(attr) == CTR    602                 if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GROUPS)
603                         if (ynl_get_family_inf    603                         if (ynl_get_family_info_mcast(ys, attr))
604                                 return YNL_PAR    604                                 return YNL_PARSE_CB_ERROR;
605                                                   605 
606                 if (ynl_attr_type(attr) != CTR    606                 if (ynl_attr_type(attr) != CTRL_ATTR_FAMILY_ID)
607                         continue;                 607                         continue;
608                                                   608 
609                 if (ynl_attr_data_len(attr) !=    609                 if (ynl_attr_data_len(attr) != sizeof(__u16)) {
610                         yerr(ys, YNL_ERROR_ATT    610                         yerr(ys, YNL_ERROR_ATTR_INVALID, "Invalid family ID");
611                         return YNL_PARSE_CB_ER    611                         return YNL_PARSE_CB_ERROR;
612                 }                                 612                 }
613                                                   613 
614                 ys->family_id = ynl_attr_get_u    614                 ys->family_id = ynl_attr_get_u16(attr);
615                 found_id = true;                  615                 found_id = true;
616         }                                         616         }
617                                                   617 
618         if (!found_id) {                          618         if (!found_id) {
619                 yerr(ys, YNL_ERROR_ATTR_MISSIN    619                 yerr(ys, YNL_ERROR_ATTR_MISSING, "Family ID missing");
620                 return YNL_PARSE_CB_ERROR;        620                 return YNL_PARSE_CB_ERROR;
621         }                                         621         }
622         return YNL_PARSE_CB_OK;                   622         return YNL_PARSE_CB_OK;
623 }                                                 623 }
624                                                   624 
625 static int ynl_sock_read_family(struct ynl_soc    625 static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name)
626 {                                                 626 {
627         struct ynl_parse_arg yarg = { .ys = ys    627         struct ynl_parse_arg yarg = { .ys = ys, };
628         struct nlmsghdr *nlh;                     628         struct nlmsghdr *nlh;
629         int err;                                  629         int err;
630                                                   630 
631         nlh = ynl_gemsg_start_req(ys, GENL_ID_    631         nlh = ynl_gemsg_start_req(ys, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1);
632         ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY    632         ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
633                                                   633 
634         err = ynl_msg_end(ys, nlh);               634         err = ynl_msg_end(ys, nlh);
635         if (err < 0)                              635         if (err < 0)
636                 return err;                       636                 return err;
637                                                   637 
638         err = send(ys->socket, nlh, nlh->nlmsg    638         err = send(ys->socket, nlh, nlh->nlmsg_len, 0);
639         if (err < 0) {                            639         if (err < 0) {
640                 perr(ys, "failed to request so    640                 perr(ys, "failed to request socket family info");
641                 return err;                       641                 return err;
642         }                                         642         }
643                                                   643 
644         err = ynl_sock_read_msgs(&yarg, ynl_ge    644         err = ynl_sock_read_msgs(&yarg, ynl_get_family_info_cb);
645         if (err < 0) {                            645         if (err < 0) {
646                 free(ys->mcast_groups);           646                 free(ys->mcast_groups);
647                 perr(ys, "failed to receive th    647                 perr(ys, "failed to receive the socket family info - no such family?");
648                 return err;                       648                 return err;
649         }                                         649         }
650                                                   650 
651         err = ynl_recv_ack(ys, err);              651         err = ynl_recv_ack(ys, err);
652         if (err < 0) {                            652         if (err < 0) {
653                 free(ys->mcast_groups);           653                 free(ys->mcast_groups);
654                 return err;                       654                 return err;
655         }                                         655         }
656                                                   656 
657         return 0;                                 657         return 0;
658 }                                                 658 }
659                                                   659 
660 struct ynl_sock *                                 660 struct ynl_sock *
661 ynl_sock_create(const struct ynl_family *yf, s    661 ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse)
662 {                                                 662 {
663         struct sockaddr_nl addr;                  663         struct sockaddr_nl addr;
664         struct ynl_sock *ys;                      664         struct ynl_sock *ys;
665         socklen_t addrlen;                        665         socklen_t addrlen;
666         int one = 1;                              666         int one = 1;
667                                                   667 
668         ys = malloc(sizeof(*ys) + 2 * YNL_SOCK    668         ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE);
669         if (!ys)                                  669         if (!ys)
670                 return NULL;                      670                 return NULL;
671         memset(ys, 0, sizeof(*ys));               671         memset(ys, 0, sizeof(*ys));
672                                                   672 
673         ys->family = yf;                          673         ys->family = yf;
674         ys->tx_buf = &ys->raw_buf[0];             674         ys->tx_buf = &ys->raw_buf[0];
675         ys->rx_buf = &ys->raw_buf[YNL_SOCKET_B    675         ys->rx_buf = &ys->raw_buf[YNL_SOCKET_BUFFER_SIZE];
676         ys->ntf_last_next = &ys->ntf_first;       676         ys->ntf_last_next = &ys->ntf_first;
677                                                   677 
678         ys->socket = socket(AF_NETLINK, SOCK_R    678         ys->socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
679         if (ys->socket < 0) {                     679         if (ys->socket < 0) {
680                 __perr(yse, "failed to create     680                 __perr(yse, "failed to create a netlink socket");
681                 goto err_free_sock;               681                 goto err_free_sock;
682         }                                         682         }
683                                                   683 
684         if (setsockopt(ys->socket, SOL_NETLINK    684         if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_CAP_ACK,
685                        &one, sizeof(one))) {      685                        &one, sizeof(one))) {
686                 __perr(yse, "failed to enable     686                 __perr(yse, "failed to enable netlink ACK");
687                 goto err_close_sock;              687                 goto err_close_sock;
688         }                                         688         }
689         if (setsockopt(ys->socket, SOL_NETLINK    689         if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_EXT_ACK,
690                        &one, sizeof(one))) {      690                        &one, sizeof(one))) {
691                 __perr(yse, "failed to enable     691                 __perr(yse, "failed to enable netlink ext ACK");
692                 goto err_close_sock;              692                 goto err_close_sock;
693         }                                         693         }
694                                                   694 
695         memset(&addr, 0, sizeof(addr));           695         memset(&addr, 0, sizeof(addr));
696         addr.nl_family = AF_NETLINK;              696         addr.nl_family = AF_NETLINK;
697         if (bind(ys->socket, (struct sockaddr     697         if (bind(ys->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
698                 __perr(yse, "unable to bind to    698                 __perr(yse, "unable to bind to a socket address");
699                 goto err_close_sock;              699                 goto err_close_sock;
700         }                                         700         }
701                                                   701 
702         memset(&addr, 0, sizeof(addr));           702         memset(&addr, 0, sizeof(addr));
703         addrlen = sizeof(addr);                   703         addrlen = sizeof(addr);
704         if (getsockname(ys->socket, (struct so    704         if (getsockname(ys->socket, (struct sockaddr *)&addr, &addrlen) < 0) {
705                 __perr(yse, "unable to read so    705                 __perr(yse, "unable to read socket address");
706                 goto err_close_sock;              706                 goto err_close_sock;
707         }                                         707         }
708         ys->portid = addr.nl_pid;                 708         ys->portid = addr.nl_pid;
709         ys->seq = random();                       709         ys->seq = random();
710                                                   710 
711                                                   711 
712         if (ynl_sock_read_family(ys, yf->name)    712         if (ynl_sock_read_family(ys, yf->name)) {
713                 if (yse)                          713                 if (yse)
714                         memcpy(yse, &ys->err,     714                         memcpy(yse, &ys->err, sizeof(*yse));
715                 goto err_close_sock;              715                 goto err_close_sock;
716         }                                         716         }
717                                                   717 
718         return ys;                                718         return ys;
719                                                   719 
720 err_close_sock:                                   720 err_close_sock:
721         close(ys->socket);                        721         close(ys->socket);
722 err_free_sock:                                    722 err_free_sock:
723         free(ys);                                 723         free(ys);
724         return NULL;                              724         return NULL;
725 }                                                 725 }
726                                                   726 
727 void ynl_sock_destroy(struct ynl_sock *ys)        727 void ynl_sock_destroy(struct ynl_sock *ys)
728 {                                                 728 {
729         struct ynl_ntf_base_type *ntf;            729         struct ynl_ntf_base_type *ntf;
730                                                   730 
731         close(ys->socket);                        731         close(ys->socket);
732         while ((ntf = ynl_ntf_dequeue(ys)))       732         while ((ntf = ynl_ntf_dequeue(ys)))
733                 ynl_ntf_free(ntf);                733                 ynl_ntf_free(ntf);
734         free(ys->mcast_groups);                   734         free(ys->mcast_groups);
735         free(ys);                                 735         free(ys);
736 }                                                 736 }
737                                                   737 
738 /* YNL multicast handling */                      738 /* YNL multicast handling */
739                                                   739 
740 void ynl_ntf_free(struct ynl_ntf_base_type *nt    740 void ynl_ntf_free(struct ynl_ntf_base_type *ntf)
741 {                                                 741 {
742         ntf->free(ntf);                           742         ntf->free(ntf);
743 }                                                 743 }
744                                                   744 
745 int ynl_subscribe(struct ynl_sock *ys, const c    745 int ynl_subscribe(struct ynl_sock *ys, const char *grp_name)
746 {                                                 746 {
747         unsigned int i;                           747         unsigned int i;
748         int err;                                  748         int err;
749                                                   749 
750         for (i = 0; i < ys->n_mcast_groups; i+    750         for (i = 0; i < ys->n_mcast_groups; i++)
751                 if (!strcmp(ys->mcast_groups[i    751                 if (!strcmp(ys->mcast_groups[i].name, grp_name))
752                         break;                    752                         break;
753         if (i == ys->n_mcast_groups) {            753         if (i == ys->n_mcast_groups) {
754                 yerr(ys, ENOENT, "Multicast gr    754                 yerr(ys, ENOENT, "Multicast group '%s' not found", grp_name);
755                 return -1;                        755                 return -1;
756         }                                         756         }
757                                                   757 
758         err = setsockopt(ys->socket, SOL_NETLI    758         err = setsockopt(ys->socket, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
759                          &ys->mcast_groups[i].    759                          &ys->mcast_groups[i].id,
760                          sizeof(ys->mcast_grou    760                          sizeof(ys->mcast_groups[i].id));
761         if (err < 0) {                            761         if (err < 0) {
762                 perr(ys, "Subscribing to multi    762                 perr(ys, "Subscribing to multicast group failed");
763                 return -1;                        763                 return -1;
764         }                                         764         }
765                                                   765 
766         return 0;                                 766         return 0;
767 }                                                 767 }
768                                                   768 
769 int ynl_socket_get_fd(struct ynl_sock *ys)        769 int ynl_socket_get_fd(struct ynl_sock *ys)
770 {                                                 770 {
771         return ys->socket;                        771         return ys->socket;
772 }                                                 772 }
773                                                   773 
774 struct ynl_ntf_base_type *ynl_ntf_dequeue(stru    774 struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys)
775 {                                                 775 {
776         struct ynl_ntf_base_type *ntf;            776         struct ynl_ntf_base_type *ntf;
777                                                   777 
778         if (!ynl_has_ntf(ys))                     778         if (!ynl_has_ntf(ys))
779                 return NULL;                      779                 return NULL;
780                                                   780 
781         ntf = ys->ntf_first;                      781         ntf = ys->ntf_first;
782         ys->ntf_first = ntf->next;                782         ys->ntf_first = ntf->next;
783         if (ys->ntf_last_next == &ntf->next)      783         if (ys->ntf_last_next == &ntf->next)
784                 ys->ntf_last_next = &ys->ntf_f    784                 ys->ntf_last_next = &ys->ntf_first;
785                                                   785 
786         return ntf;                               786         return ntf;
787 }                                                 787 }
788                                                   788 
789 static int ynl_ntf_parse(struct ynl_sock *ys,     789 static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
790 {                                                 790 {
791         struct ynl_parse_arg yarg = { .ys = ys    791         struct ynl_parse_arg yarg = { .ys = ys, };
792         const struct ynl_ntf_info *info;          792         const struct ynl_ntf_info *info;
793         struct ynl_ntf_base_type *rsp;            793         struct ynl_ntf_base_type *rsp;
794         struct genlmsghdr *gehdr;                 794         struct genlmsghdr *gehdr;
795         int ret;                                  795         int ret;
796                                                   796 
797         gehdr = ynl_nlmsg_data(nlh);              797         gehdr = ynl_nlmsg_data(nlh);
798         if (gehdr->cmd >= ys->family->ntf_info    798         if (gehdr->cmd >= ys->family->ntf_info_size)
799                 return YNL_PARSE_CB_ERROR;        799                 return YNL_PARSE_CB_ERROR;
800         info = &ys->family->ntf_info[gehdr->cm    800         info = &ys->family->ntf_info[gehdr->cmd];
801         if (!info->cb)                            801         if (!info->cb)
802                 return YNL_PARSE_CB_ERROR;        802                 return YNL_PARSE_CB_ERROR;
803                                                   803 
804         rsp = calloc(1, info->alloc_sz);          804         rsp = calloc(1, info->alloc_sz);
805         rsp->free = info->free;                   805         rsp->free = info->free;
806         yarg.data = rsp->data;                    806         yarg.data = rsp->data;
807         yarg.rsp_policy = info->policy;           807         yarg.rsp_policy = info->policy;
808                                                   808 
809         ret = info->cb(nlh, &yarg);               809         ret = info->cb(nlh, &yarg);
810         if (ret <= YNL_PARSE_CB_STOP)             810         if (ret <= YNL_PARSE_CB_STOP)
811                 goto err_free;                    811                 goto err_free;
812                                                   812 
813         rsp->family = nlh->nlmsg_type;            813         rsp->family = nlh->nlmsg_type;
814         rsp->cmd = gehdr->cmd;                    814         rsp->cmd = gehdr->cmd;
815                                                   815 
816         *ys->ntf_last_next = rsp;                 816         *ys->ntf_last_next = rsp;
817         ys->ntf_last_next = &rsp->next;           817         ys->ntf_last_next = &rsp->next;
818                                                   818 
819         return YNL_PARSE_CB_OK;                   819         return YNL_PARSE_CB_OK;
820                                                   820 
821 err_free:                                         821 err_free:
822         info->free(rsp);                          822         info->free(rsp);
823         return YNL_PARSE_CB_ERROR;                823         return YNL_PARSE_CB_ERROR;
824 }                                                 824 }
825                                                   825 
826 static int                                        826 static int
827 ynl_ntf_trampoline(const struct nlmsghdr *nlh,    827 ynl_ntf_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
828 {                                                 828 {
829         return ynl_ntf_parse(yarg->ys, nlh);      829         return ynl_ntf_parse(yarg->ys, nlh);
830 }                                                 830 }
831                                                   831 
832 int ynl_ntf_check(struct ynl_sock *ys)            832 int ynl_ntf_check(struct ynl_sock *ys)
833 {                                                 833 {
834         struct ynl_parse_arg yarg = { .ys = ys    834         struct ynl_parse_arg yarg = { .ys = ys, };
835         int err;                                  835         int err;
836                                                   836 
837         do {                                      837         do {
838                 err = __ynl_sock_read_msgs(&ya    838                 err = __ynl_sock_read_msgs(&yarg, ynl_ntf_trampoline,
839                                            MSG    839                                            MSG_DONTWAIT);
840                 if (err < 0)                      840                 if (err < 0)
841                         return err;               841                         return err;
842         } while (err > 0);                        842         } while (err > 0);
843                                                   843 
844         return 0;                                 844         return 0;
845 }                                                 845 }
846                                                   846 
847 /* YNL specific helpers used by the auto-gener    847 /* YNL specific helpers used by the auto-generated code */
848                                                   848 
849 struct ynl_dump_list_type *YNL_LIST_END = (voi    849 struct ynl_dump_list_type *YNL_LIST_END = (void *)(0xb4d123);
850                                                   850 
851 void ynl_error_unknown_notification(struct ynl    851 void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd)
852 {                                                 852 {
853         yerr(ys, YNL_ERROR_UNKNOWN_NTF,           853         yerr(ys, YNL_ERROR_UNKNOWN_NTF,
854              "Unknown notification message typ    854              "Unknown notification message type '%d'", cmd);
855 }                                                 855 }
856                                                   856 
857 int ynl_error_parse(struct ynl_parse_arg *yarg    857 int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg)
858 {                                                 858 {
859         yerr(yarg->ys, YNL_ERROR_INV_RESP, "Er    859         yerr(yarg->ys, YNL_ERROR_INV_RESP, "Error parsing response: %s", msg);
860         return YNL_PARSE_CB_ERROR;                860         return YNL_PARSE_CB_ERROR;
861 }                                                 861 }
862                                                   862 
863 static int                                        863 static int
864 ynl_check_alien(struct ynl_sock *ys, const str    864 ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd)
865 {                                                 865 {
866         struct genlmsghdr *gehdr;                 866         struct genlmsghdr *gehdr;
867                                                   867 
868         if (ynl_nlmsg_data_len(nlh) < sizeof(*    868         if (ynl_nlmsg_data_len(nlh) < sizeof(*gehdr)) {
869                 yerr(ys, YNL_ERROR_INV_RESP,      869                 yerr(ys, YNL_ERROR_INV_RESP,
870                      "Kernel responded with tr    870                      "Kernel responded with truncated message");
871                 return -1;                        871                 return -1;
872         }                                         872         }
873                                                   873 
874         gehdr = ynl_nlmsg_data(nlh);              874         gehdr = ynl_nlmsg_data(nlh);
875         if (gehdr->cmd != rsp_cmd)                875         if (gehdr->cmd != rsp_cmd)
876                 return ynl_ntf_parse(ys, nlh);    876                 return ynl_ntf_parse(ys, nlh);
877                                                   877 
878         return 0;                                 878         return 0;
879 }                                                 879 }
880                                                   880 
881 static                                            881 static
882 int ynl_req_trampoline(const struct nlmsghdr *    882 int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
883 {                                                 883 {
884         struct ynl_req_state *yrs = (void *)ya    884         struct ynl_req_state *yrs = (void *)yarg;
885         int ret;                                  885         int ret;
886                                                   886 
887         ret = ynl_check_alien(yrs->yarg.ys, nl    887         ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd);
888         if (ret)                                  888         if (ret)
889                 return ret < 0 ? YNL_PARSE_CB_    889                 return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
890                                                   890 
891         return yrs->cb(nlh, &yrs->yarg);          891         return yrs->cb(nlh, &yrs->yarg);
892 }                                                 892 }
893                                                   893 
894 int ynl_exec(struct ynl_sock *ys, struct nlmsg    894 int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
895              struct ynl_req_state *yrs)           895              struct ynl_req_state *yrs)
896 {                                                 896 {
897         int err;                                  897         int err;
898                                                   898 
899         err = ynl_msg_end(ys, req_nlh);           899         err = ynl_msg_end(ys, req_nlh);
900         if (err < 0)                              900         if (err < 0)
901                 return err;                       901                 return err;
902                                                   902 
903         err = send(ys->socket, req_nlh, req_nl    903         err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
904         if (err < 0)                              904         if (err < 0)
905                 return err;                       905                 return err;
906                                                   906 
907         do {                                      907         do {
908                 err = ynl_sock_read_msgs(&yrs-    908                 err = ynl_sock_read_msgs(&yrs->yarg, ynl_req_trampoline);
909         } while (err > 0);                        909         } while (err > 0);
910                                                   910 
911         return err;                               911         return err;
912 }                                                 912 }
913                                                   913 
914 static int                                        914 static int
915 ynl_dump_trampoline(const struct nlmsghdr *nlh    915 ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data)
916 {                                                 916 {
917         struct ynl_dump_state *ds = (void *)da    917         struct ynl_dump_state *ds = (void *)data;
918         struct ynl_dump_list_type *obj;           918         struct ynl_dump_list_type *obj;
919         struct ynl_parse_arg yarg = {};           919         struct ynl_parse_arg yarg = {};
920         int ret;                                  920         int ret;
921                                                   921 
922         ret = ynl_check_alien(ds->yarg.ys, nlh    922         ret = ynl_check_alien(ds->yarg.ys, nlh, ds->rsp_cmd);
923         if (ret)                                  923         if (ret)
924                 return ret < 0 ? YNL_PARSE_CB_    924                 return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
925                                                   925 
926         obj = calloc(1, ds->alloc_sz);            926         obj = calloc(1, ds->alloc_sz);
927         if (!obj)                                 927         if (!obj)
928                 return YNL_PARSE_CB_ERROR;        928                 return YNL_PARSE_CB_ERROR;
929                                                   929 
930         if (!ds->first)                           930         if (!ds->first)
931                 ds->first = obj;                  931                 ds->first = obj;
932         if (ds->last)                             932         if (ds->last)
933                 ds->last->next = obj;             933                 ds->last->next = obj;
934         ds->last = obj;                           934         ds->last = obj;
935                                                   935 
936         yarg = ds->yarg;                          936         yarg = ds->yarg;
937         yarg.data = &obj->data;                   937         yarg.data = &obj->data;
938                                                   938 
939         return ds->cb(nlh, &yarg);                939         return ds->cb(nlh, &yarg);
940 }                                                 940 }
941                                                   941 
942 static void *ynl_dump_end(struct ynl_dump_stat    942 static void *ynl_dump_end(struct ynl_dump_state *ds)
943 {                                                 943 {
944         if (!ds->first)                           944         if (!ds->first)
945                 return YNL_LIST_END;              945                 return YNL_LIST_END;
946                                                   946 
947         ds->last->next = YNL_LIST_END;            947         ds->last->next = YNL_LIST_END;
948         return ds->first;                         948         return ds->first;
949 }                                                 949 }
950                                                   950 
951 int ynl_exec_dump(struct ynl_sock *ys, struct     951 int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
952                   struct ynl_dump_state *yds)     952                   struct ynl_dump_state *yds)
953 {                                                 953 {
954         int err;                                  954         int err;
955                                                   955 
956         err = ynl_msg_end(ys, req_nlh);           956         err = ynl_msg_end(ys, req_nlh);
957         if (err < 0)                              957         if (err < 0)
958                 return err;                       958                 return err;
959                                                   959 
960         err = send(ys->socket, req_nlh, req_nl    960         err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
961         if (err < 0)                              961         if (err < 0)
962                 return err;                       962                 return err;
963                                                   963 
964         do {                                      964         do {
965                 err = ynl_sock_read_msgs(&yds-    965                 err = ynl_sock_read_msgs(&yds->yarg, ynl_dump_trampoline);
966                 if (err < 0)                      966                 if (err < 0)
967                         goto err_close_list;      967                         goto err_close_list;
968         } while (err > 0);                        968         } while (err > 0);
969                                                   969 
970         yds->first = ynl_dump_end(yds);           970         yds->first = ynl_dump_end(yds);
971         return 0;                                 971         return 0;
972                                                   972 
973 err_close_list:                                   973 err_close_list:
974         yds->first = ynl_dump_end(yds);           974         yds->first = ynl_dump_end(yds);
975         return -1;                                975         return -1;
976 }                                                 976 }
977                                                   977 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php