466a68ad9ba48dc5a3316a08cf99a95ae83a9e58
[strongswan.git] / src / dumm / mconsole.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2001-2004 Jeff Dike
5 *
6 * Based on the "uml_mconsole" utilty from Jeff Dike.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24
25 #include <debug.h>
26
27 #include "mconsole.h"
28
29 #define MCONSOLE_MAGIC 0xcafebabe
30 #define MCONSOLE_VERSION 2
31 #define MCONSOLE_MAX_DATA 512
32
33 typedef struct private_mconsole_t private_mconsole_t;
34
35 struct private_mconsole_t {
36 /** public interface */
37 mconsole_t public;
38 /** mconsole socket */
39 int socket;
40 /** address of uml socket */
41 struct sockaddr_un uml;
42 };
43
44 /**
45 * send a request to UML using mconsole
46 */
47 static bool request(private_mconsole_t *this, char *command)
48 {
49 struct {
50 u_int32_t magic;
51 u_int32_t version;
52 u_int32_t len;
53 char data[MCONSOLE_MAX_DATA];
54 } request;
55 struct {
56 u_int32_t err;
57 u_int32_t more;
58 u_int32_t len;
59 char data[MCONSOLE_MAX_DATA];
60 } reply;
61 bool first = TRUE, good = TRUE;
62 int len;
63
64 memset(&request, 0, sizeof(request));
65 request.magic = MCONSOLE_MAGIC;
66 request.version = MCONSOLE_VERSION;
67 request.len = min(strlen(command), sizeof(reply.data) - 1);
68 strncpy(request.data, command, request.len);
69
70 if (sendto(this->socket, &request, sizeof(request), 0,
71 (struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
72 {
73 DBG1("sending mconsole command to UML failed: %m");
74 return FALSE;
75 }
76 do
77 {
78 len = recvfrom(this->socket, &reply, sizeof(reply), 0, NULL, 0);
79 if (len < 0)
80 {
81 DBG1("receiving from mconsole failed: %m");
82 return FALSE;
83 }
84 if (first && reply.err)
85 {
86 good = FALSE;
87 DBG1("received error from UML mconsole: %s", reply.data);
88 }
89 first = FALSE;
90 }
91 while (reply.more);
92 return good;
93 }
94
95 /**
96 * Implementation of mconsole_t.add_iface.
97 */
98 static bool add_iface(private_mconsole_t *this, char *guest, char *host)
99 {
100 char buf[128];
101 int len;
102
103 len = snprintf(buf, sizeof(buf), "config %s=tuntap,%s", guest, host);
104 if (len < 0 || len >= sizeof(buf))
105 {
106 return FALSE;
107 }
108 return request(this, buf);
109 }
110
111 /**
112 * Implementation of mconsole_t.del_iface.
113 */
114 static bool del_iface(private_mconsole_t *this, char *guest)
115 {
116 char buf[128];
117 int len;
118
119 len = snprintf(buf, sizeof(buf), "remove %s", guest);
120 if (len < 0 || len >= sizeof(buf))
121 {
122 return FALSE;
123 }
124 return request(this, buf);
125 }
126
127 /**
128 * Implementation of mconsole_t.destroy.
129 */
130 static void destroy(private_mconsole_t *this)
131 {
132 close(this->socket);
133 free(this);
134 }
135
136 /**
137 * create the mconsole instance
138 */
139 mconsole_t *mconsole_create(char *sock)
140 {
141 struct sockaddr_un addr;
142 private_mconsole_t *this = malloc_thing(private_mconsole_t);
143
144 this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
145 this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
146 this->public.destroy = (void*)destroy;
147
148 this->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
149 if (this->socket < 0)
150 {
151 DBG1("opening mconsole socket failed: %m");
152 free(this);
153 return NULL;
154 }
155 memset(&addr, 0, sizeof(addr));
156 addr.sun_family = AF_UNIX;
157 snprintf(&addr.sun_path[1], sizeof(addr.sun_path), "%5d-%s", getpid(), sock);
158 if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
159 {
160 DBG1("binding mconsole socket failed: %m");
161 destroy(this);
162 return NULL;
163 }
164 memset(&this->uml, 0, sizeof(this->uml));
165 this->uml.sun_family = AF_UNIX;
166 strncpy(this->uml.sun_path, sock, sizeof(this->uml.sun_path));
167
168 return &this->public;
169 }
170