1 /* Stroke for charon is the counterpart to whack from pluto
2 * Copyright (C) 2006 Martin Willi - Hochschule fuer Technik Rapperswil
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include <sys/types.h>
18 #include <sys/socket.h>
20 #include <sys/fcntl.h>
28 #include "stroke_keywords.h"
35 static char* push_string(stroke_msg_t
*msg
, char *string
)
37 unsigned long string_start
= msg
->length
;
39 if (string
== NULL
|| msg
->length
+ strlen(string
) >= sizeof(stroke_msg_t
))
45 msg
->length
+= strlen(string
) + 1;
46 strcpy((char*)msg
+ string_start
, string
);
47 return (char*)string_start
;
51 static int send_stroke_msg (stroke_msg_t
*msg
)
53 struct sockaddr_un ctl_addr
= { AF_UNIX
, STROKE_SOCKET
};
58 msg
->output_verbosity
= 1; /* CONTROL */
60 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
63 fprintf(stderr
, "Opening unix socket %s: %s\n", STROKE_SOCKET
, strerror(errno
));
66 if (connect(sock
, (struct sockaddr
*)&ctl_addr
,
67 offsetof(struct sockaddr_un
, sun_path
) + strlen(ctl_addr
.sun_path
)) < 0)
69 fprintf(stderr
, "Connect to socket failed: %s\n", strerror(errno
));
75 if (write(sock
, msg
, msg
->length
) != msg
->length
)
77 fprintf(stderr
, "writing to socket failed: %s\n", strerror(errno
));
82 while ((byte_count
= read(sock
, buffer
, sizeof(buffer
)-1)) > 0)
84 buffer
[byte_count
] = '\0';
89 fprintf(stderr
, "reading from socket failed: %s\n", strerror(errno
));
96 static int add_connection(char *name
,
97 char *my_id
, char *other_id
,
98 char *my_addr
, char *other_addr
,
99 char *my_net
, char *other_net
,
100 u_int my_netmask
, u_int other_netmask
)
104 msg
.length
= offsetof(stroke_msg_t
, buffer
);
105 msg
.type
= STR_ADD_CONN
;
107 msg
.add_conn
.name
= push_string(&msg
, name
);
108 msg
.add_conn
.ikev2
= 1;
109 msg
.add_conn
.auth_method
= 2;
110 msg
.add_conn
.eap_type
= 0;
111 msg
.add_conn
.mode
= 1;
113 msg
.add_conn
.rekey
.reauth
= 0;
114 msg
.add_conn
.rekey
.ipsec_lifetime
= 0;
115 msg
.add_conn
.rekey
.ike_lifetime
= 0;
116 msg
.add_conn
.rekey
.margin
= 0;
117 msg
.add_conn
.rekey
.tries
= 0;
118 msg
.add_conn
.rekey
.fuzz
= 0;
120 msg
.add_conn
.algorithms
.ike
= NULL
;
121 msg
.add_conn
.algorithms
.esp
= NULL
;
123 msg
.add_conn
.dpd
.delay
= 0;
124 msg
.add_conn
.dpd
.action
= 1;
126 msg
.add_conn
.me
.id
= push_string(&msg
, my_id
);
127 msg
.add_conn
.me
.address
= push_string(&msg
, my_addr
);
128 msg
.add_conn
.me
.subnet
= push_string(&msg
, my_net
);
129 msg
.add_conn
.me
.subnet_mask
= my_netmask
;
130 msg
.add_conn
.me
.sourceip
= NULL
;
131 msg
.add_conn
.me
.virtual_ip
= 0;
132 msg
.add_conn
.me
.cert
= NULL
;
133 msg
.add_conn
.me
.ca
= NULL
;
134 msg
.add_conn
.me
.sendcert
= 1;
135 msg
.add_conn
.me
.hostaccess
= 0;
136 msg
.add_conn
.me
.tohost
= 0;
137 msg
.add_conn
.me
.protocol
= 0;
138 msg
.add_conn
.me
.port
= 0;
140 msg
.add_conn
.other
.id
= push_string(&msg
, other_id
);
141 msg
.add_conn
.other
.address
= push_string(&msg
, other_addr
);
142 msg
.add_conn
.other
.subnet
= push_string(&msg
, other_net
);
143 msg
.add_conn
.other
.subnet_mask
= other_netmask
;
144 msg
.add_conn
.other
.sourceip
= NULL
;
145 msg
.add_conn
.other
.virtual_ip
= 0;
146 msg
.add_conn
.other
.cert
= NULL
;
147 msg
.add_conn
.other
.ca
= NULL
;
148 msg
.add_conn
.other
.sendcert
= 1;
149 msg
.add_conn
.other
.hostaccess
= 0;
150 msg
.add_conn
.other
.tohost
= 0;
151 msg
.add_conn
.other
.protocol
= 0;
152 msg
.add_conn
.other
.port
= 0;
154 return send_stroke_msg(&msg
);
157 static int del_connection(char *name
)
161 msg
.length
= offsetof(stroke_msg_t
, buffer
);
162 msg
.type
= STR_DEL_CONN
;
163 msg
.initiate
.name
= push_string(&msg
, name
);
164 return send_stroke_msg(&msg
);
167 static int initiate_connection(char *name
)
171 msg
.length
= offsetof(stroke_msg_t
, buffer
);
172 msg
.type
= STR_INITIATE
;
173 msg
.initiate
.name
= push_string(&msg
, name
);
174 return send_stroke_msg(&msg
);
177 static int terminate_connection(char *name
)
181 msg
.type
= STR_TERMINATE
;
182 msg
.length
= offsetof(stroke_msg_t
, buffer
);
183 msg
.initiate
.name
= push_string(&msg
, name
);
184 return send_stroke_msg(&msg
);
187 static int route_connection(char *name
)
191 msg
.type
= STR_ROUTE
;
192 msg
.length
= offsetof(stroke_msg_t
, buffer
);
193 msg
.route
.name
= push_string(&msg
, name
);
194 return send_stroke_msg(&msg
);
197 static int unroute_connection(char *name
)
201 msg
.type
= STR_UNROUTE
;
202 msg
.length
= offsetof(stroke_msg_t
, buffer
);
203 msg
.unroute
.name
= push_string(&msg
, name
);
204 return send_stroke_msg(&msg
);
207 static int show_status(stroke_keyword_t kw
, char *connection
)
211 msg
.type
= (kw
== STROKE_STATUS
)? STR_STATUS
:STR_STATUS_ALL
;
212 msg
.length
= offsetof(stroke_msg_t
, buffer
);
213 msg
.status
.name
= push_string(&msg
, connection
);
214 return send_stroke_msg(&msg
);
217 static int list_flags
[] = {
227 static int list(stroke_keyword_t kw
, int utc
)
232 msg
.length
= offsetof(stroke_msg_t
, buffer
);
234 msg
.list
.flags
= list_flags
[kw
- STROKE_LIST_FIRST
];
235 return send_stroke_msg(&msg
);
238 static int reread_flags
[] = {
245 static int reread(stroke_keyword_t kw
)
249 msg
.type
= STR_REREAD
;
250 msg
.length
= offsetof(stroke_msg_t
, buffer
);
251 msg
.reread
.flags
= reread_flags
[kw
- STROKE_REREAD_FIRST
];
252 return send_stroke_msg(&msg
);
255 static int purge_flags
[] = {
259 static int purge(stroke_keyword_t kw
)
263 msg
.type
= STR_PURGE
;
264 msg
.length
= offsetof(stroke_msg_t
, buffer
);
265 msg
.purge
.flags
= purge_flags
[kw
- STROKE_PURGE_FIRST
];
266 return send_stroke_msg(&msg
);
269 static int set_loglevel(char *type
, u_int level
)
273 msg
.type
= STR_LOGLEVEL
;
274 msg
.length
= offsetof(stroke_msg_t
, buffer
);
275 msg
.loglevel
.type
= push_string(&msg
, type
);
276 msg
.loglevel
.level
= level
;
277 return send_stroke_msg(&msg
);
280 static void exit_error(char *error
)
284 fprintf(stderr
, "%s\n", error
);
289 static void exit_usage(char *error
)
292 printf(" Add a connection:\n");
293 printf(" stroke add NAME MY_ID OTHER_ID MY_ADDR OTHER_ADDR\\\n");
294 printf(" MY_NET OTHER_NET MY_NETBITS OTHER_NETBITS\n");
295 printf(" where: ID is any IKEv2 ID \n");
296 printf(" ADDR is a IPv4 address\n");
297 printf(" NET is a IPv4 address of the subnet to tunnel\n");
298 printf(" NETBITS is the size of the subnet, as the \"24\" in 192.168.0.0/24\n");
299 printf(" Delete a connection:\n");
300 printf(" stroke delete NAME\n");
301 printf(" where: NAME is a connection name added with \"stroke add\"\n");
302 printf(" Initiate a connection:\n");
303 printf(" stroke up NAME\n");
304 printf(" where: NAME is a connection name added with \"stroke add\"\n");
305 printf(" Terminate a connection:\n");
306 printf(" stroke down NAME\n");
307 printf(" where: NAME is a connection name added with \"stroke add\"\n");
308 printf(" Set loglevel for a logging type:\n");
309 printf(" stroke loglevel TYPE LEVEL\n");
310 printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|enc|lib\n");
311 printf(" LEVEL is -1|0|1|2|3|4\n");
312 printf(" Show connection status:\n");
313 printf(" stroke status\n");
314 printf(" Show list of locally loaded certificates and crls:\n");
315 printf(" stroke listcerts|listcacerts|listocspcerts|listcainfos|listcrls|listocsp|listall\n");
316 printf(" Reload ca certificates and crls:\n");
317 printf(" stroke rereadcacerts|rereadcrls|rereadall\n");
318 printf(" Purge ocsp cache entries:\n");
319 printf(" stroke purgeocsp\n");
323 int main(int argc
, char *argv
[])
325 const stroke_token_t
*token
;
333 token
= in_word_set(argv
[1], strlen(argv
[1]));
337 exit_usage("unknown keyword");
345 exit_usage("\"add\" needs more parameters...");
347 res
= add_connection(argv
[2],
351 atoi(argv
[9]), atoi(argv
[10]));
357 exit_usage("\"delete\" needs a connection name");
359 res
= del_connection(argv
[2]);
364 exit_usage("\"up\" needs a connection name");
366 res
= initiate_connection(argv
[2]);
371 exit_usage("\"down\" needs a connection name");
373 res
= terminate_connection(argv
[2]);
378 exit_usage("\"route\" needs a connection name");
380 res
= route_connection(argv
[2]);
385 exit_usage("\"unroute\" needs a connection name");
387 res
= unroute_connection(argv
[2]);
389 case STROKE_LOGLEVEL
:
392 exit_usage("\"logtype\" needs more parameters...");
394 res
= set_loglevel(argv
[2], atoi(argv
[3]));
397 case STROKE_STATUSALL
:
398 res
= show_status(token
->kw
, argc
> 2 ? argv
[2] : NULL
);
400 case STROKE_LIST_CERTS
:
401 case STROKE_LIST_CACERTS
:
402 case STROKE_LIST_OCSPCERTS
:
403 case STROKE_LIST_CAINFOS
:
404 case STROKE_LIST_CRLS
:
405 case STROKE_LIST_OCSP
:
406 case STROKE_LIST_ALL
:
407 res
= list(token
->kw
, argc
> 2 && strcmp(argv
[2], "--utc") == 0);
409 case STROKE_REREAD_CACERTS
:
410 case STROKE_REREAD_CRLS
:
411 case STROKE_REREAD_ALL
:
412 res
= reread(token
->kw
);
414 case STROKE_PURGE_OCSP
:
415 res
= purge(token
->kw
);