blob: 9723b0c5e1a65a7154bc042b40becb0eee3f28d0 [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,
61 MSG_CONNECT,
62 MSG_DISCONNECT,
63 MSG_GET,
64 MSG_GETCONFIG,
65 MSG_EDITCONFIG,
66 MSG_COPYCONFIG,
67 MSG_DELETECONFIG,
68 MSG_LOCK,
69 MSG_UNLOCK,
70 MSG_KILL
71} MSG_TYPE;
72
73void print_help(char* progname)
74{
75 printf("Usage: %s <command>\n", progname);
76 printf("Available commands:\n");
77 printf("\tconnect\n");
78 printf("\tdisconnect\n");
79 printf("\tcopy-config\n");
80 printf("\tdelete-config\n");
81 printf("\tedit-config\n");
82 printf("\tget\n");
83 printf("\tget-config\n");
84 printf("\tkill-session\n");
85 printf("\tlock\n");
86 printf("\tunlock\n");
87}
88
89int main (int argc, char* argv[])
90{
Radek Krejci035bf4e2012-07-25 10:59:09 +020091 json_object* msg = NULL, *reply = NULL;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020092 const char* msg_text;
93 int sock;
94 struct sockaddr_un addr;
95 size_t len;
96 char buffer[BUFFER_SIZE];
97 char* line = NULL;
98
99 if (argc != 2) {
100 print_help(argv[0]);
101 return (2);
102 }
103
104 /* connect to the daemon */
105 sock = socket(PF_UNIX, SOCK_STREAM, 0);
106 if (sock == -1) {
107 fprintf(stderr, "Creating socket failed (%s)", strerror(errno));
108 return (EXIT_FAILURE);
109 }
110 addr.sun_family = AF_UNIX;
111 strncpy(addr.sun_path, SOCKET_FILENAME, sizeof(addr.sun_path));
112 len = strlen(addr.sun_path) + sizeof(addr.sun_family);
113 if (connect(sock, (struct sockaddr *) &addr, len) == -1) {
114 fprintf(stderr, "Connecting to mod_netconf (%s) failed (%s)", SOCKET_FILENAME, strerror(errno));
115 close(sock);
116 return (EXIT_FAILURE);
117 }
118
119 line = malloc(sizeof(char) * BUFFER_SIZE);
120
121 if (strcmp(argv[1], "connect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200122 /*
123 * create NETCONF session
124 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200125 msg = json_object_new_object();
126 json_object_object_add(msg, "type", json_object_new_int(MSG_CONNECT));
127 printf("Hostname: ");
128 getline (&line, &len, stdin);
129 line[(strlen(line)-1)] = 0;
130 json_object_object_add(msg, "host", json_object_new_string(line));
131 printf("Port: ");
132 getline (&line, &len, stdin);
133 line[(strlen(line)-1)] = 0;
134 json_object_object_add(msg, "port", json_object_new_string(line));
135 printf("Username: ");
136 getline (&line, &len, stdin);
137 line[(strlen(line)-1)] = 0;
138 json_object_object_add(msg, "user", json_object_new_string(line));
139 printf("Password: ");
140 system("stty -echo");
141 getline (&line, &len, stdin);
142 system("stty echo");
143 printf("\n");
144 line[(strlen(line)-1)] = 0;
145 json_object_object_add(msg, "pass", json_object_new_string(line));
146 } else if (strcmp(argv[1], "disconnect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200147 /*
148 * Close NETCONF session
149 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200150 msg = json_object_new_object();
151 json_object_object_add(msg, "type", json_object_new_int(MSG_DISCONNECT));
152 printf("Session: ");
153 getline (&line, &len, stdin);
154 line[(strlen(line)-1)] = 0;
155 json_object_object_add(msg, "session", json_object_new_string(line));
156 } else if (strcmp(argv[1], "copy-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200157 /*
158 * NETCONF <copy-config>
159 */
Radek Krejci035bf4e2012-07-25 10:59:09 +0200160 msg = json_object_new_object();
161 json_object_object_add(msg, "type", json_object_new_int(MSG_COPYCONFIG));
162 printf("Session: ");
163 getline (&line, &len, stdin);
164 line[(strlen(line)-1)] = 0;
165 json_object_object_add(msg, "session", json_object_new_string(line));
166 printf("Source (running|startup|candidate): ");
167 getline (&line, &len, stdin);
168 line[(strlen(line)-1)] = 0;
Radek Krejciae021c12012-07-25 18:03:52 +0200169 if (strlen(line) > 0) {
170 json_object_object_add(msg, "source", json_object_new_string(line));
171 } else {
172 printf("Configuration data: ");
173 getline (&line, &len, stdin);
174 line[(strlen(line)-1)] = 0;
175 json_object_object_add(msg, "config", json_object_new_string(line));
176 }
Radek Krejci035bf4e2012-07-25 10:59:09 +0200177 printf("Target (running|startup|candidate): ");
178 getline (&line, &len, stdin);
179 line[(strlen(line)-1)] = 0;
180 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200181 } else if (strcmp(argv[1], "delete-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200182 /*
183 * NETCONF <delete-config>
184 */
185 msg = json_object_new_object();
186 json_object_object_add(msg, "type", json_object_new_int(MSG_DELETECONFIG));
187 printf("Session: ");
188 getline (&line, &len, stdin);
189 line[(strlen(line)-1)] = 0;
190 json_object_object_add(msg, "session", json_object_new_string(line));
191 printf("Target (running|startup|candidate): ");
192 getline (&line, &len, stdin);
193 line[(strlen(line)-1)] = 0;
194 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200195 } else if (strcmp(argv[1], "edit-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200196 /*
197 * NETCONF <edit-config>
198 */
199 msg = json_object_new_object();
200 json_object_object_add(msg, "type", json_object_new_int(MSG_EDITCONFIG));
201 printf("Session: ");
202 getline (&line, &len, stdin);
203 line[(strlen(line)-1)] = 0;
204 json_object_object_add(msg, "session", json_object_new_string(line));
205 printf("Target (running|startup|candidate): ");
206 getline(&line, &len, stdin);
207 line[(strlen(line) - 1)] = 0;
208 json_object_object_add(msg, "target", json_object_new_string(line));
209 printf("Default operation (merge|replace|none): ");
210 getline(&line, &len, stdin);
211 line[(strlen(line) - 1)] = 0;
212 if (strlen(line) > 0) {
213 json_object_object_add(msg, "default-operation", json_object_new_string(line));
214 }
215 printf("Error option (stop-on-error|continue-on-error|rollback-on-error): ");
216 getline(&line, &len, stdin);
217 line[(strlen(line) - 1)] = 0;
218 if (strlen(line) > 0) {
219 json_object_object_add(msg, "error-option", json_object_new_string(line));
220 }
221 printf("Configuration data: ");
222 getline(&line, &len, stdin);
223 line[(strlen(line) - 1)] = 0;
Radek Krejcib1e08f42012-07-26 10:54:28 +0200224 json_object_object_add(msg, "config", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200225 } else if (strcmp(argv[1], "get") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200226 /*
227 * NETCONF <get>
228 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200229 msg = json_object_new_object();
230 json_object_object_add(msg, "type", json_object_new_int(MSG_GET));
231 printf("Session: ");
232 getline (&line, &len, stdin);
233 line[(strlen(line)-1)] = 0;
234 json_object_object_add(msg, "session", json_object_new_string(line));
235 printf("Filter: ");
236 getline(&line, &len, stdin);
237 line[(strlen(line)-1)] = 0;
238 if (strlen(line) > 0) {
239 json_object_object_add(msg, "filter", json_object_new_string(line));
240 }
241 } else if (strcmp(argv[1], "get-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200242 /*
243 * NETCONF <get-config>
244 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200245 msg = json_object_new_object();
246 json_object_object_add(msg, "type", json_object_new_int(MSG_GETCONFIG));
247 printf("Session: ");
248 getline (&line, &len, stdin);
249 line[(strlen(line)-1)] = 0;
250 json_object_object_add(msg, "session", json_object_new_string(line));
251 printf("Source (running|startup|candidate): ");
252 getline (&line, &len, stdin);
253 line[(strlen(line)-1)] = 0;
254 json_object_object_add(msg, "source", json_object_new_string(line));
255 printf("Filter: ");
256 getline(&line, &len, stdin);
257 line[(strlen(line)-1)] = 0;
258 if (strlen(line) > 0) {
259 json_object_object_add(msg, "filter", json_object_new_string(line));
260 }
261 } else if (strcmp(argv[1], "kill-session") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200262 /*
263 * NETCONF <kill-session>
264 */
265 msg = json_object_new_object();
266 json_object_object_add(msg, "type", json_object_new_int(MSG_KILL));
267 printf("Session: ");
268 getline (&line, &len, stdin);
269 line[(strlen(line)-1)] = 0;
270 json_object_object_add(msg, "session", json_object_new_string(line));
271 printf("Kill session with ID: ");
272 getline (&line, &len, stdin);
273 line[(strlen(line)-1)] = 0;
274 json_object_object_add(msg, "session-id", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200275 } else if (strcmp(argv[1], "lock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200276 /*
277 * NETCONF <lock>
278 */
279 msg = json_object_new_object();
280 json_object_object_add(msg, "type", json_object_new_int(MSG_LOCK));
281 printf("Session: ");
282 getline (&line, &len, stdin);
283 line[(strlen(line)-1)] = 0;
284 json_object_object_add(msg, "session", json_object_new_string(line));
285 printf("Target (running|startup|candidate): ");
286 getline (&line, &len, stdin);
287 line[(strlen(line)-1)] = 0;
288 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200289 } else if (strcmp(argv[1], "unlock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200290 /*
291 * NETCONF <unlock>
292 */
293 msg = json_object_new_object();
294 json_object_object_add(msg, "type", json_object_new_int(MSG_UNLOCK));
295 printf("Session: ");
296 getline (&line, &len, stdin);
297 line[(strlen(line)-1)] = 0;
298 json_object_object_add(msg, "session", json_object_new_string(line));
299 printf("Target (running|startup|candidate): ");
300 getline (&line, &len, stdin);
301 line[(strlen(line)-1)] = 0;
302 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200303 } else {
Radek Krejciaa422df2012-07-25 18:04:59 +0200304 /*
305 * Unknown request
306 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200307 fprintf(stderr, "Unknown command %s\n", argv[1]);
308 close(sock);
309 return (EXIT_FAILURE);
310 }
311
312 /* send the message */
313 if (msg != NULL) {
314 msg_text = json_object_to_json_string(msg);
315
Radek Krejci035bf4e2012-07-25 10:59:09 +0200316 if (json_object_object_get(msg, "pass") == NULL) {
317 /* print message only if it does not contain password */
318 printf("Sending: %s\n", msg_text);
319 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200320 send(sock, msg_text, strlen(msg_text) + 1, 0);
321
322 json_object_put(msg);
323 } else {
324 close(sock);
325 return (EXIT_FAILURE);
326 }
327
328 len = recv(sock, buffer, BUFFER_SIZE, 0);
Radek Krejci035bf4e2012-07-25 10:59:09 +0200329 if (len > 0) {
330 reply = json_tokener_parse(buffer);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200331 }
Radek Krejci035bf4e2012-07-25 10:59:09 +0200332 printf("Received:\n");
333 if (reply == NULL) {
334 printf("(null)\n");
335 } else {
336 json_object_object_foreach(reply, key, value) {
337 printf("Key: %s, Value: ", key);
338 switch (json_object_get_type(value)) {
339 case json_type_string:
340 printf("%s\n", json_object_get_string(value));
341 break;
342 case json_type_int:
343 printf("%d\n", json_object_get_int(value));
344 break;
345 default:
346 printf("\n");
347 break;
348 }
349 }
350 json_object_put(reply);
351 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200352 close(sock);
353 free(line);
354
355 return (EXIT_SUCCESS);
356}