1 /*
2  * media.c	TIPC link functionality.
3  *
4  *		This program is free software; you can redistribute it and/or
5  *		modify it under the terms of the GNU General Public License
6  *		as published by the Free Software Foundation; either version
7  *		2 of the License, or (at your option) any later version.
8  *
9  * Authors:	Richard Alpe <richard.alpe@ericsson.com>
10  */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 
17 #include <linux/tipc_netlink.h>
18 #include <linux/tipc.h>
19 #include <linux/genetlink.h>
20 #include <libmnl/libmnl.h>
21 
22 #include "cmdl.h"
23 #include "msg.h"
24 #include "media.h"
25 
media_list_cb(const struct nlmsghdr * nlh,void * data)26 static int media_list_cb(const struct nlmsghdr *nlh, void *data)
27 {
28 	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
29 	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
30 	struct nlattr *attrs[TIPC_NLA_MEDIA_MAX + 1] = {};
31 
32 	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
33 	if (!info[TIPC_NLA_MEDIA])
34 		return MNL_CB_ERROR;
35 
36 	mnl_attr_parse_nested(info[TIPC_NLA_MEDIA], parse_attrs, attrs);
37 	if (!attrs[TIPC_NLA_MEDIA_NAME])
38 		return MNL_CB_ERROR;
39 
40 	printf("%s\n", mnl_attr_get_str(attrs[TIPC_NLA_MEDIA_NAME]));
41 
42 	return MNL_CB_OK;
43 }
44 
cmd_media_list(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)45 static int cmd_media_list(struct nlmsghdr *nlh, const struct cmd *cmd,
46 			 struct cmdl *cmdl, void *data)
47 {
48 	char buf[MNL_SOCKET_BUFFER_SIZE];
49 
50 	if (help_flag) {
51 		fprintf(stderr, "Usage: %s media list\n", cmdl->argv[0]);
52 		return -EINVAL;
53 	}
54 
55 	if (!(nlh = msg_init(buf, TIPC_NL_MEDIA_GET))) {
56 		fprintf(stderr, "error, message initialisation failed\n");
57 		return -1;
58 	}
59 
60 	return msg_dumpit(nlh, media_list_cb, NULL);
61 }
62 
media_get_cb(const struct nlmsghdr * nlh,void * data)63 static int media_get_cb(const struct nlmsghdr *nlh, void *data)
64 {
65 	int *prop = data;
66 	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
67 	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
68 	struct nlattr *attrs[TIPC_NLA_MEDIA_MAX + 1] = {};
69 	struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
70 
71 	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
72 	if (!info[TIPC_NLA_MEDIA])
73 		return MNL_CB_ERROR;
74 
75 	mnl_attr_parse_nested(info[TIPC_NLA_MEDIA], parse_attrs, attrs);
76 	if (!attrs[TIPC_NLA_MEDIA_PROP])
77 		return MNL_CB_ERROR;
78 
79 	mnl_attr_parse_nested(attrs[TIPC_NLA_MEDIA_PROP], parse_attrs, props);
80 	if (!props[*prop])
81 		return MNL_CB_ERROR;
82 
83 	printf("%u\n", mnl_attr_get_u32(props[*prop]));
84 
85 	return MNL_CB_OK;
86 }
87 
cmd_media_get_prop(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)88 static int cmd_media_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
89 			      struct cmdl *cmdl, void *data)
90 {
91 	int prop;
92 	char buf[MNL_SOCKET_BUFFER_SIZE];
93 	struct nlattr *nest;
94 	struct opt *opt;
95 	struct opt opts[] = {
96 		{ "media",		OPT_KEYVAL,	NULL },
97 		{ NULL }
98 	};
99 
100 	if (strcmp(cmd->cmd, "priority") == 0)
101 		prop = TIPC_NLA_PROP_PRIO;
102 	else if ((strcmp(cmd->cmd, "tolerance") == 0))
103 		prop = TIPC_NLA_PROP_TOL;
104 	else if ((strcmp(cmd->cmd, "window") == 0))
105 		prop = TIPC_NLA_PROP_WIN;
106 	else
107 		return -EINVAL;
108 
109 	if (help_flag) {
110 		(cmd->help)(cmdl);
111 		return -EINVAL;
112 	}
113 
114 	if (parse_opts(opts, cmdl) < 0)
115 		return -EINVAL;
116 
117 	if (!(nlh = msg_init(buf, TIPC_NL_MEDIA_GET))) {
118 		fprintf(stderr, "error, message initialisation failed\n");
119 		return -1;
120 	}
121 
122 	if (!(opt = get_opt(opts, "media"))) {
123 		fprintf(stderr, "error, missing media\n");
124 		return -EINVAL;
125 	}
126 	nest = mnl_attr_nest_start(nlh, TIPC_NLA_MEDIA);
127 	mnl_attr_put_strz(nlh, TIPC_NLA_MEDIA_NAME, opt->val);
128 	mnl_attr_nest_end(nlh, nest);
129 
130 	return msg_doit(nlh, media_get_cb, &prop);
131 }
132 
cmd_media_get_help(struct cmdl * cmdl)133 static void cmd_media_get_help(struct cmdl *cmdl)
134 {
135 	fprintf(stderr, "Usage: %s media get PPROPERTY media MEDIA\n\n"
136 		"PROPERTIES\n"
137 		" tolerance             - Get media tolerance\n"
138 		" priority              - Get media priority\n"
139 		" window                - Get media window\n",
140 		cmdl->argv[0]);
141 }
142 
cmd_media_get(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)143 static int cmd_media_get(struct nlmsghdr *nlh, const struct cmd *cmd,
144 			struct cmdl *cmdl, void *data)
145 {
146 	const struct cmd cmds[] = {
147 		{ "priority",	cmd_media_get_prop,	cmd_media_get_help },
148 		{ "tolerance",	cmd_media_get_prop,	cmd_media_get_help },
149 		{ "window",	cmd_media_get_prop,	cmd_media_get_help },
150 		{ NULL }
151 	};
152 
153 	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
154 }
155 
cmd_media_set_help(struct cmdl * cmdl)156 static void cmd_media_set_help(struct cmdl *cmdl)
157 {
158 	fprintf(stderr, "Usage: %s media set PPROPERTY media MEDIA\n\n"
159 		"PROPERTIES\n"
160 		" tolerance TOLERANCE   - Set media tolerance\n"
161 		" priority PRIORITY     - Set media priority\n"
162 		" window WINDOW         - Set media window\n",
163 		cmdl->argv[0]);
164 }
165 
cmd_media_set_prop(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)166 static int cmd_media_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
167 			 struct cmdl *cmdl, void *data)
168 {
169 	int val;
170 	int prop;
171 	char buf[MNL_SOCKET_BUFFER_SIZE];
172 	struct nlattr *props;
173 	struct nlattr *attrs;
174 	struct opt *opt;
175 	struct opt opts[] = {
176 		{ "media",		OPT_KEYVAL,	NULL },
177 		{ NULL }
178 	};
179 
180 	if (strcmp(cmd->cmd, "priority") == 0)
181 		prop = TIPC_NLA_PROP_PRIO;
182 	else if ((strcmp(cmd->cmd, "tolerance") == 0))
183 		prop = TIPC_NLA_PROP_TOL;
184 	else if ((strcmp(cmd->cmd, "window") == 0))
185 		prop = TIPC_NLA_PROP_WIN;
186 	else
187 		return -EINVAL;
188 
189 	if (help_flag) {
190 		(cmd->help)(cmdl);
191 		return -EINVAL;
192 	}
193 
194 	if (cmdl->optind >= cmdl->argc) {
195 		fprintf(stderr, "error, missing value\n");
196 		return -EINVAL;
197 	}
198 	val = atoi(shift_cmdl(cmdl));
199 
200 	if (parse_opts(opts, cmdl) < 0)
201 		return -EINVAL;
202 
203 	if (!(nlh = msg_init(buf, TIPC_NL_MEDIA_SET))) {
204 		fprintf(stderr, "error, message initialisation failed\n");
205 		return -1;
206 	}
207 	attrs = mnl_attr_nest_start(nlh, TIPC_NLA_MEDIA);
208 
209 	if (!(opt = get_opt(opts, "media"))) {
210 		fprintf(stderr, "error, missing media\n");
211 		return -EINVAL;
212 	}
213 	mnl_attr_put_strz(nlh, TIPC_NLA_MEDIA_NAME, opt->val);
214 
215 	props = mnl_attr_nest_start(nlh, TIPC_NLA_MEDIA_PROP);
216 	mnl_attr_put_u32(nlh, prop, val);
217 	mnl_attr_nest_end(nlh, props);
218 
219 	mnl_attr_nest_end(nlh, attrs);
220 
221 	return msg_doit(nlh, NULL, NULL);
222 }
223 
cmd_media_set(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)224 static int cmd_media_set(struct nlmsghdr *nlh, const struct cmd *cmd,
225 			 struct cmdl *cmdl, void *data)
226 {
227 	const struct cmd cmds[] = {
228 		{ "priority",	cmd_media_set_prop,	cmd_media_set_help },
229 		{ "tolerance",	cmd_media_set_prop,	cmd_media_set_help },
230 		{ "window",	cmd_media_set_prop,	cmd_media_set_help },
231 		{ NULL }
232 	};
233 
234 	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
235 }
236 
cmd_media_help(struct cmdl * cmdl)237 void cmd_media_help(struct cmdl *cmdl)
238 {
239 	fprintf(stderr,
240 		"Usage: %s media COMMAND [ARGS] ...\n"
241 		"\n"
242 		"Commands:\n"
243 		" list                  - List active media types\n"
244 		" get                   - Get various media properties\n"
245 		" set                   - Set various media properties\n",
246 		cmdl->argv[0]);
247 }
248 
cmd_media(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)249 int cmd_media(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
250 	     void *data)
251 {
252 	const struct cmd cmds[] = {
253 		{ "get",	cmd_media_get,	cmd_media_get_help },
254 		{ "list",	cmd_media_list,	NULL },
255 		{ "set",	cmd_media_set,	cmd_media_set_help },
256 		{ NULL }
257 	};
258 
259 	return run_cmd(nlh, cmd, cmds, cmdl, NULL);
260 }
261