blob: 2ff337ec94fa6b19358126675c7f29ef5d794ea2 [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,
Radek Krejci80c10d92012-07-30 08:38:50 +020072 MSG_INFO,
73 MSG_GENERIC
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020074} MSG_TYPE;
75
76void print_help(char* progname)
77{
78 printf("Usage: %s <command>\n", progname);
79 printf("Available commands:\n");
80 printf("\tconnect\n");
81 printf("\tdisconnect\n");
82 printf("\tcopy-config\n");
83 printf("\tdelete-config\n");
84 printf("\tedit-config\n");
85 printf("\tget\n");
86 printf("\tget-config\n");
87 printf("\tkill-session\n");
88 printf("\tlock\n");
89 printf("\tunlock\n");
Radek Krejci9e04c7b2012-07-26 15:54:25 +020090 printf("\tinfo\n");
Radek Krejci80c10d92012-07-30 08:38:50 +020091 printf("\tgeneric\n");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020092}
93
94int main (int argc, char* argv[])
95{
Radek Krejci035bf4e2012-07-25 10:59:09 +020096 json_object* msg = NULL, *reply = NULL;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020097 const char* msg_text;
98 int sock;
99 struct sockaddr_un addr;
100 size_t len;
101 char buffer[BUFFER_SIZE];
102 char* line = NULL;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200103 int i, alen;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200104
105 if (argc != 2) {
106 print_help(argv[0]);
107 return (2);
108 }
109
110 /* connect to the daemon */
111 sock = socket(PF_UNIX, SOCK_STREAM, 0);
112 if (sock == -1) {
113 fprintf(stderr, "Creating socket failed (%s)", strerror(errno));
114 return (EXIT_FAILURE);
115 }
116 addr.sun_family = AF_UNIX;
117 strncpy(addr.sun_path, SOCKET_FILENAME, sizeof(addr.sun_path));
118 len = strlen(addr.sun_path) + sizeof(addr.sun_family);
119 if (connect(sock, (struct sockaddr *) &addr, len) == -1) {
120 fprintf(stderr, "Connecting to mod_netconf (%s) failed (%s)", SOCKET_FILENAME, strerror(errno));
121 close(sock);
122 return (EXIT_FAILURE);
123 }
124
125 line = malloc(sizeof(char) * BUFFER_SIZE);
126
127 if (strcmp(argv[1], "connect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200128 /*
129 * create NETCONF session
130 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200131 msg = json_object_new_object();
132 json_object_object_add(msg, "type", json_object_new_int(MSG_CONNECT));
133 printf("Hostname: ");
134 getline (&line, &len, stdin);
135 line[(strlen(line)-1)] = 0;
136 json_object_object_add(msg, "host", json_object_new_string(line));
137 printf("Port: ");
138 getline (&line, &len, stdin);
139 line[(strlen(line)-1)] = 0;
140 json_object_object_add(msg, "port", json_object_new_string(line));
141 printf("Username: ");
142 getline (&line, &len, stdin);
143 line[(strlen(line)-1)] = 0;
144 json_object_object_add(msg, "user", json_object_new_string(line));
145 printf("Password: ");
146 system("stty -echo");
147 getline (&line, &len, stdin);
148 system("stty echo");
149 printf("\n");
150 line[(strlen(line)-1)] = 0;
151 json_object_object_add(msg, "pass", json_object_new_string(line));
152 } else if (strcmp(argv[1], "disconnect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200153 /*
154 * Close NETCONF session
155 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200156 msg = json_object_new_object();
157 json_object_object_add(msg, "type", json_object_new_int(MSG_DISCONNECT));
158 printf("Session: ");
159 getline (&line, &len, stdin);
160 line[(strlen(line)-1)] = 0;
161 json_object_object_add(msg, "session", json_object_new_string(line));
162 } else if (strcmp(argv[1], "copy-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200163 /*
164 * NETCONF <copy-config>
165 */
Radek Krejci035bf4e2012-07-25 10:59:09 +0200166 msg = json_object_new_object();
167 json_object_object_add(msg, "type", json_object_new_int(MSG_COPYCONFIG));
168 printf("Session: ");
169 getline (&line, &len, stdin);
170 line[(strlen(line)-1)] = 0;
171 json_object_object_add(msg, "session", json_object_new_string(line));
172 printf("Source (running|startup|candidate): ");
173 getline (&line, &len, stdin);
174 line[(strlen(line)-1)] = 0;
Radek Krejciae021c12012-07-25 18:03:52 +0200175 if (strlen(line) > 0) {
176 json_object_object_add(msg, "source", json_object_new_string(line));
177 } else {
178 printf("Configuration data: ");
179 getline (&line, &len, stdin);
180 line[(strlen(line)-1)] = 0;
181 json_object_object_add(msg, "config", json_object_new_string(line));
182 }
Radek Krejci035bf4e2012-07-25 10:59:09 +0200183 printf("Target (running|startup|candidate): ");
184 getline (&line, &len, stdin);
185 line[(strlen(line)-1)] = 0;
186 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200187 } else if (strcmp(argv[1], "delete-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200188 /*
189 * NETCONF <delete-config>
190 */
191 msg = json_object_new_object();
192 json_object_object_add(msg, "type", json_object_new_int(MSG_DELETECONFIG));
193 printf("Session: ");
194 getline (&line, &len, stdin);
195 line[(strlen(line)-1)] = 0;
196 json_object_object_add(msg, "session", json_object_new_string(line));
197 printf("Target (running|startup|candidate): ");
198 getline (&line, &len, stdin);
199 line[(strlen(line)-1)] = 0;
200 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200201 } else if (strcmp(argv[1], "edit-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200202 /*
203 * NETCONF <edit-config>
204 */
205 msg = json_object_new_object();
206 json_object_object_add(msg, "type", json_object_new_int(MSG_EDITCONFIG));
207 printf("Session: ");
208 getline (&line, &len, stdin);
209 line[(strlen(line)-1)] = 0;
210 json_object_object_add(msg, "session", json_object_new_string(line));
211 printf("Target (running|startup|candidate): ");
212 getline(&line, &len, stdin);
213 line[(strlen(line) - 1)] = 0;
214 json_object_object_add(msg, "target", json_object_new_string(line));
215 printf("Default operation (merge|replace|none): ");
216 getline(&line, &len, stdin);
217 line[(strlen(line) - 1)] = 0;
218 if (strlen(line) > 0) {
219 json_object_object_add(msg, "default-operation", json_object_new_string(line));
220 }
221 printf("Error option (stop-on-error|continue-on-error|rollback-on-error): ");
222 getline(&line, &len, stdin);
223 line[(strlen(line) - 1)] = 0;
224 if (strlen(line) > 0) {
225 json_object_object_add(msg, "error-option", json_object_new_string(line));
226 }
227 printf("Configuration data: ");
228 getline(&line, &len, stdin);
229 line[(strlen(line) - 1)] = 0;
Radek Krejcib1e08f42012-07-26 10:54:28 +0200230 json_object_object_add(msg, "config", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200231 } else if (strcmp(argv[1], "get") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200232 /*
233 * NETCONF <get>
234 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200235 msg = json_object_new_object();
236 json_object_object_add(msg, "type", json_object_new_int(MSG_GET));
237 printf("Session: ");
238 getline (&line, &len, stdin);
239 line[(strlen(line)-1)] = 0;
240 json_object_object_add(msg, "session", json_object_new_string(line));
241 printf("Filter: ");
242 getline(&line, &len, stdin);
243 line[(strlen(line)-1)] = 0;
244 if (strlen(line) > 0) {
245 json_object_object_add(msg, "filter", json_object_new_string(line));
246 }
247 } else if (strcmp(argv[1], "get-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200248 /*
249 * NETCONF <get-config>
250 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200251 msg = json_object_new_object();
252 json_object_object_add(msg, "type", json_object_new_int(MSG_GETCONFIG));
253 printf("Session: ");
254 getline (&line, &len, stdin);
255 line[(strlen(line)-1)] = 0;
256 json_object_object_add(msg, "session", json_object_new_string(line));
257 printf("Source (running|startup|candidate): ");
258 getline (&line, &len, stdin);
259 line[(strlen(line)-1)] = 0;
260 json_object_object_add(msg, "source", json_object_new_string(line));
261 printf("Filter: ");
262 getline(&line, &len, stdin);
263 line[(strlen(line)-1)] = 0;
264 if (strlen(line) > 0) {
265 json_object_object_add(msg, "filter", json_object_new_string(line));
266 }
267 } else if (strcmp(argv[1], "kill-session") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200268 /*
269 * NETCONF <kill-session>
270 */
271 msg = json_object_new_object();
272 json_object_object_add(msg, "type", json_object_new_int(MSG_KILL));
273 printf("Session: ");
274 getline (&line, &len, stdin);
275 line[(strlen(line)-1)] = 0;
276 json_object_object_add(msg, "session", json_object_new_string(line));
277 printf("Kill session with ID: ");
278 getline (&line, &len, stdin);
279 line[(strlen(line)-1)] = 0;
280 json_object_object_add(msg, "session-id", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200281 } else if (strcmp(argv[1], "lock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200282 /*
283 * NETCONF <lock>
284 */
285 msg = json_object_new_object();
286 json_object_object_add(msg, "type", json_object_new_int(MSG_LOCK));
287 printf("Session: ");
288 getline (&line, &len, stdin);
289 line[(strlen(line)-1)] = 0;
290 json_object_object_add(msg, "session", json_object_new_string(line));
291 printf("Target (running|startup|candidate): ");
292 getline (&line, &len, stdin);
293 line[(strlen(line)-1)] = 0;
294 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200295 } else if (strcmp(argv[1], "unlock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200296 /*
297 * NETCONF <unlock>
298 */
299 msg = json_object_new_object();
300 json_object_object_add(msg, "type", json_object_new_int(MSG_UNLOCK));
301 printf("Session: ");
302 getline (&line, &len, stdin);
303 line[(strlen(line)-1)] = 0;
304 json_object_object_add(msg, "session", json_object_new_string(line));
305 printf("Target (running|startup|candidate): ");
306 getline (&line, &len, stdin);
307 line[(strlen(line)-1)] = 0;
308 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200309 } else if (strcmp(argv[1], "info") == 0) {
310 /*
311 * Get information about NETCONF session
312 */
313 msg = json_object_new_object();
314 json_object_object_add(msg, "type", json_object_new_int(MSG_INFO));
315 printf("Session: ");
316 getline (&line, &len, stdin);
317 line[(strlen(line)-1)] = 0;
318 json_object_object_add(msg, "session", json_object_new_string(line));
Radek Krejci80c10d92012-07-30 08:38:50 +0200319 } else if (strcmp(argv[1], "generic") == 0) {
320 /*
321 * Generic NETCONF request
322 */
323 msg = json_object_new_object();
324 json_object_object_add(msg, "type", json_object_new_int(MSG_GENERIC));
325 printf("Session: ");
326 getline (&line, &len, stdin);
327 line[(strlen(line)-1)] = 0;
328 json_object_object_add(msg, "session", json_object_new_string(line));
329 printf("NETCONF <rpc> content: ");
330 getline(&line, &len, stdin);
331 line[(strlen(line) - 1)] = 0;
332 json_object_object_add(msg, "content", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200333 } else {
Radek Krejciaa422df2012-07-25 18:04:59 +0200334 /*
335 * Unknown request
336 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200337 fprintf(stderr, "Unknown command %s\n", argv[1]);
338 close(sock);
339 return (EXIT_FAILURE);
340 }
341
342 /* send the message */
343 if (msg != NULL) {
344 msg_text = json_object_to_json_string(msg);
345
Radek Krejci035bf4e2012-07-25 10:59:09 +0200346 if (json_object_object_get(msg, "pass") == NULL) {
347 /* print message only if it does not contain password */
348 printf("Sending: %s\n", msg_text);
349 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200350 send(sock, msg_text, strlen(msg_text) + 1, 0);
351
352 json_object_put(msg);
353 } else {
354 close(sock);
355 return (EXIT_FAILURE);
356 }
357
358 len = recv(sock, buffer, BUFFER_SIZE, 0);
Radek Krejci035bf4e2012-07-25 10:59:09 +0200359 if (len > 0) {
360 reply = json_tokener_parse(buffer);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200361 }
Radek Krejci035bf4e2012-07-25 10:59:09 +0200362 printf("Received:\n");
363 if (reply == NULL) {
364 printf("(null)\n");
365 } else {
366 json_object_object_foreach(reply, key, value) {
367 printf("Key: %s, Value: ", key);
368 switch (json_object_get_type(value)) {
369 case json_type_string:
370 printf("%s\n", json_object_get_string(value));
371 break;
372 case json_type_int:
373 printf("%d\n", json_object_get_int(value));
374 break;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200375 case json_type_array:
376 printf("\n");
377 alen = json_object_array_length(value);
378 for (i = 0; i < alen; i++) {
379 printf("\t(%d) %s\n", i, json_object_get_string(json_object_array_get_idx(value, i)));
380 }
381 break;
Radek Krejci035bf4e2012-07-25 10:59:09 +0200382 default:
383 printf("\n");
384 break;
385 }
386 }
387 json_object_put(reply);
388 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200389 close(sock);
390 free(line);
391
392 return (EXIT_SUCCESS);
393}