blob: 7dc121fa092306701486d54add0f49e70ab22890 [file] [log] [blame]
Radek Krejci8fd1f5e2012-07-24 17:33:36 +02001/*!
2 * \file test-client.c
3 * \brief Testing client sending JSON requsts to the mod_netconf socket
4 * \author Radek Krejci <rkrejci@cesnet.cz>
5 * \date 2012
6 */
7/*
8 * Copyright (C) 2012 CESNET
9 *
10 * LICENSE TERMS
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 * 3. Neither the name of the Company nor the names of its contributors
22 * may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 *
25 * ALTERNATIVELY, provided that this notice is retained in full, this
26 * product may be distributed under the terms of the GNU General Public
27 * License (GPL) version 2 or later, in which case the provisions
28 * of the GPL apply INSTEAD OF those given above.
29 *
30 * This software is provided ``as is'', and any express or implied
31 * warranties, including, but not limited to, the implied warranties of
32 * merchantability and fitness for a particular purpose are disclaimed.
33 * In no event shall the company or contributors be liable for any
34 * direct, indirect, incidental, special, exemplary, or consequential
35 * damages (including, but not limited to, procurement of substitute
36 * goods or services; loss of use, data, or profits; or business
37 * interruption) however caused and on any theory of liability, whether
38 * in contract, strict liability, or tort (including negligence or
39 * otherwise) arising in any way out of the use of this software, even
40 * if advised of the possibility of such damage.
41 *
42 */
43
44#include <unistd.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <errno.h>
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <sys/un.h>
52#include <json/json.h>
53
Radek Krejci6cb08982012-07-25 18:01:06 +020054#define SOCKET_FILENAME "/tmp/mod_netconf.sock"
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020055#define BUFFER_SIZE 4096
56
57typedef enum MSG_TYPE {
58 REPLY_OK,
59 REPLY_DATA,
60 REPLY_ERROR,
Radek Krejci9e04c7b2012-07-26 15:54:25 +020061 REPLY_INFO,
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020062 MSG_CONNECT,
63 MSG_DISCONNECT,
64 MSG_GET,
65 MSG_GETCONFIG,
66 MSG_EDITCONFIG,
67 MSG_COPYCONFIG,
68 MSG_DELETECONFIG,
69 MSG_LOCK,
70 MSG_UNLOCK,
Radek Krejci9e04c7b2012-07-26 15:54:25 +020071 MSG_KILL,
72 MSG_INFO
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020073} MSG_TYPE;
74
75void print_help(char* progname)
76{
77 printf("Usage: %s <command>\n", progname);
78 printf("Available commands:\n");
79 printf("\tconnect\n");
80 printf("\tdisconnect\n");
81 printf("\tcopy-config\n");
82 printf("\tdelete-config\n");
83 printf("\tedit-config\n");
84 printf("\tget\n");
85 printf("\tget-config\n");
86 printf("\tkill-session\n");
87 printf("\tlock\n");
88 printf("\tunlock\n");
Radek Krejci9e04c7b2012-07-26 15:54:25 +020089 printf("\tinfo\n");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020090}
91
92int main (int argc, char* argv[])
93{
Radek Krejci035bf4e2012-07-25 10:59:09 +020094 json_object* msg = NULL, *reply = NULL;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020095 const char* msg_text;
96 int sock;
97 struct sockaddr_un addr;
98 size_t len;
99 char buffer[BUFFER_SIZE];
100 char* line = NULL;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200101 int i, alen;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200102
103 if (argc != 2) {
104 print_help(argv[0]);
105 return (2);
106 }
107
108 /* connect to the daemon */
109 sock = socket(PF_UNIX, SOCK_STREAM, 0);
110 if (sock == -1) {
111 fprintf(stderr, "Creating socket failed (%s)", strerror(errno));
112 return (EXIT_FAILURE);
113 }
114 addr.sun_family = AF_UNIX;
115 strncpy(addr.sun_path, SOCKET_FILENAME, sizeof(addr.sun_path));
116 len = strlen(addr.sun_path) + sizeof(addr.sun_family);
117 if (connect(sock, (struct sockaddr *) &addr, len) == -1) {
118 fprintf(stderr, "Connecting to mod_netconf (%s) failed (%s)", SOCKET_FILENAME, strerror(errno));
119 close(sock);
120 return (EXIT_FAILURE);
121 }
122
123 line = malloc(sizeof(char) * BUFFER_SIZE);
124
125 if (strcmp(argv[1], "connect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200126 /*
127 * create NETCONF session
128 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200129 msg = json_object_new_object();
130 json_object_object_add(msg, "type", json_object_new_int(MSG_CONNECT));
131 printf("Hostname: ");
132 getline (&line, &len, stdin);
133 line[(strlen(line)-1)] = 0;
134 json_object_object_add(msg, "host", json_object_new_string(line));
135 printf("Port: ");
136 getline (&line, &len, stdin);
137 line[(strlen(line)-1)] = 0;
138 json_object_object_add(msg, "port", json_object_new_string(line));
139 printf("Username: ");
140 getline (&line, &len, stdin);
141 line[(strlen(line)-1)] = 0;
142 json_object_object_add(msg, "user", json_object_new_string(line));
143 printf("Password: ");
144 system("stty -echo");
145 getline (&line, &len, stdin);
146 system("stty echo");
147 printf("\n");
148 line[(strlen(line)-1)] = 0;
149 json_object_object_add(msg, "pass", json_object_new_string(line));
150 } else if (strcmp(argv[1], "disconnect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200151 /*
152 * Close NETCONF session
153 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200154 msg = json_object_new_object();
155 json_object_object_add(msg, "type", json_object_new_int(MSG_DISCONNECT));
156 printf("Session: ");
157 getline (&line, &len, stdin);
158 line[(strlen(line)-1)] = 0;
159 json_object_object_add(msg, "session", json_object_new_string(line));
160 } else if (strcmp(argv[1], "copy-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200161 /*
162 * NETCONF <copy-config>
163 */
Radek Krejci035bf4e2012-07-25 10:59:09 +0200164 msg = json_object_new_object();
165 json_object_object_add(msg, "type", json_object_new_int(MSG_COPYCONFIG));
166 printf("Session: ");
167 getline (&line, &len, stdin);
168 line[(strlen(line)-1)] = 0;
169 json_object_object_add(msg, "session", json_object_new_string(line));
170 printf("Source (running|startup|candidate): ");
171 getline (&line, &len, stdin);
172 line[(strlen(line)-1)] = 0;
Radek Krejciae021c12012-07-25 18:03:52 +0200173 if (strlen(line) > 0) {
174 json_object_object_add(msg, "source", json_object_new_string(line));
175 } else {
176 printf("Configuration data: ");
177 getline (&line, &len, stdin);
178 line[(strlen(line)-1)] = 0;
179 json_object_object_add(msg, "config", json_object_new_string(line));
180 }
Radek Krejci035bf4e2012-07-25 10:59:09 +0200181 printf("Target (running|startup|candidate): ");
182 getline (&line, &len, stdin);
183 line[(strlen(line)-1)] = 0;
184 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200185 } else if (strcmp(argv[1], "delete-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200186 /*
187 * NETCONF <delete-config>
188 */
189 msg = json_object_new_object();
190 json_object_object_add(msg, "type", json_object_new_int(MSG_DELETECONFIG));
191 printf("Session: ");
192 getline (&line, &len, stdin);
193 line[(strlen(line)-1)] = 0;
194 json_object_object_add(msg, "session", json_object_new_string(line));
195 printf("Target (running|startup|candidate): ");
196 getline (&line, &len, stdin);
197 line[(strlen(line)-1)] = 0;
198 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200199 } else if (strcmp(argv[1], "edit-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200200 /*
201 * NETCONF <edit-config>
202 */
203 msg = json_object_new_object();
204 json_object_object_add(msg, "type", json_object_new_int(MSG_EDITCONFIG));
205 printf("Session: ");
206 getline (&line, &len, stdin);
207 line[(strlen(line)-1)] = 0;
208 json_object_object_add(msg, "session", json_object_new_string(line));
209 printf("Target (running|startup|candidate): ");
210 getline(&line, &len, stdin);
211 line[(strlen(line) - 1)] = 0;
212 json_object_object_add(msg, "target", json_object_new_string(line));
213 printf("Default operation (merge|replace|none): ");
214 getline(&line, &len, stdin);
215 line[(strlen(line) - 1)] = 0;
216 if (strlen(line) > 0) {
217 json_object_object_add(msg, "default-operation", json_object_new_string(line));
218 }
219 printf("Error option (stop-on-error|continue-on-error|rollback-on-error): ");
220 getline(&line, &len, stdin);
221 line[(strlen(line) - 1)] = 0;
222 if (strlen(line) > 0) {
223 json_object_object_add(msg, "error-option", json_object_new_string(line));
224 }
225 printf("Configuration data: ");
226 getline(&line, &len, stdin);
227 line[(strlen(line) - 1)] = 0;
Radek Krejcib1e08f42012-07-26 10:54:28 +0200228 json_object_object_add(msg, "config", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200229 } else if (strcmp(argv[1], "get") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200230 /*
231 * NETCONF <get>
232 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200233 msg = json_object_new_object();
234 json_object_object_add(msg, "type", json_object_new_int(MSG_GET));
235 printf("Session: ");
236 getline (&line, &len, stdin);
237 line[(strlen(line)-1)] = 0;
238 json_object_object_add(msg, "session", json_object_new_string(line));
239 printf("Filter: ");
240 getline(&line, &len, stdin);
241 line[(strlen(line)-1)] = 0;
242 if (strlen(line) > 0) {
243 json_object_object_add(msg, "filter", json_object_new_string(line));
244 }
245 } else if (strcmp(argv[1], "get-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200246 /*
247 * NETCONF <get-config>
248 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200249 msg = json_object_new_object();
250 json_object_object_add(msg, "type", json_object_new_int(MSG_GETCONFIG));
251 printf("Session: ");
252 getline (&line, &len, stdin);
253 line[(strlen(line)-1)] = 0;
254 json_object_object_add(msg, "session", json_object_new_string(line));
255 printf("Source (running|startup|candidate): ");
256 getline (&line, &len, stdin);
257 line[(strlen(line)-1)] = 0;
258 json_object_object_add(msg, "source", json_object_new_string(line));
259 printf("Filter: ");
260 getline(&line, &len, stdin);
261 line[(strlen(line)-1)] = 0;
262 if (strlen(line) > 0) {
263 json_object_object_add(msg, "filter", json_object_new_string(line));
264 }
265 } else if (strcmp(argv[1], "kill-session") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200266 /*
267 * NETCONF <kill-session>
268 */
269 msg = json_object_new_object();
270 json_object_object_add(msg, "type", json_object_new_int(MSG_KILL));
271 printf("Session: ");
272 getline (&line, &len, stdin);
273 line[(strlen(line)-1)] = 0;
274 json_object_object_add(msg, "session", json_object_new_string(line));
275 printf("Kill session with ID: ");
276 getline (&line, &len, stdin);
277 line[(strlen(line)-1)] = 0;
278 json_object_object_add(msg, "session-id", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200279 } else if (strcmp(argv[1], "lock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200280 /*
281 * NETCONF <lock>
282 */
283 msg = json_object_new_object();
284 json_object_object_add(msg, "type", json_object_new_int(MSG_LOCK));
285 printf("Session: ");
286 getline (&line, &len, stdin);
287 line[(strlen(line)-1)] = 0;
288 json_object_object_add(msg, "session", json_object_new_string(line));
289 printf("Target (running|startup|candidate): ");
290 getline (&line, &len, stdin);
291 line[(strlen(line)-1)] = 0;
292 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200293 } else if (strcmp(argv[1], "unlock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200294 /*
295 * NETCONF <unlock>
296 */
297 msg = json_object_new_object();
298 json_object_object_add(msg, "type", json_object_new_int(MSG_UNLOCK));
299 printf("Session: ");
300 getline (&line, &len, stdin);
301 line[(strlen(line)-1)] = 0;
302 json_object_object_add(msg, "session", json_object_new_string(line));
303 printf("Target (running|startup|candidate): ");
304 getline (&line, &len, stdin);
305 line[(strlen(line)-1)] = 0;
306 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200307 } else if (strcmp(argv[1], "info") == 0) {
308 /*
309 * Get information about NETCONF session
310 */
311 msg = json_object_new_object();
312 json_object_object_add(msg, "type", json_object_new_int(MSG_INFO));
313 printf("Session: ");
314 getline (&line, &len, stdin);
315 line[(strlen(line)-1)] = 0;
316 json_object_object_add(msg, "session", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200317 } else {
Radek Krejciaa422df2012-07-25 18:04:59 +0200318 /*
319 * Unknown request
320 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200321 fprintf(stderr, "Unknown command %s\n", argv[1]);
322 close(sock);
323 return (EXIT_FAILURE);
324 }
325
326 /* send the message */
327 if (msg != NULL) {
328 msg_text = json_object_to_json_string(msg);
329
Radek Krejci035bf4e2012-07-25 10:59:09 +0200330 if (json_object_object_get(msg, "pass") == NULL) {
331 /* print message only if it does not contain password */
332 printf("Sending: %s\n", msg_text);
333 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200334 send(sock, msg_text, strlen(msg_text) + 1, 0);
335
336 json_object_put(msg);
337 } else {
338 close(sock);
339 return (EXIT_FAILURE);
340 }
341
342 len = recv(sock, buffer, BUFFER_SIZE, 0);
Radek Krejci035bf4e2012-07-25 10:59:09 +0200343 if (len > 0) {
344 reply = json_tokener_parse(buffer);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200345 }
Radek Krejci035bf4e2012-07-25 10:59:09 +0200346 printf("Received:\n");
347 if (reply == NULL) {
348 printf("(null)\n");
349 } else {
350 json_object_object_foreach(reply, key, value) {
351 printf("Key: %s, Value: ", key);
352 switch (json_object_get_type(value)) {
353 case json_type_string:
354 printf("%s\n", json_object_get_string(value));
355 break;
356 case json_type_int:
357 printf("%d\n", json_object_get_int(value));
358 break;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200359 case json_type_array:
360 printf("\n");
361 alen = json_object_array_length(value);
362 for (i = 0; i < alen; i++) {
363 printf("\t(%d) %s\n", i, json_object_get_string(json_object_array_get_idx(value, i)));
364 }
365 break;
Radek Krejci035bf4e2012-07-25 10:59:09 +0200366 default:
367 printf("\n");
368 break;
369 }
370 }
371 json_object_put(reply);
372 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200373 close(sock);
374 free(line);
375
376 return (EXIT_SUCCESS);
377}