@@ -41,9 +41,13 @@ int api_bindlisten(const char *api_socket)
41
41
struct api_hostfwd {
42
42
int id ;
43
43
int is_udp ;
44
- struct in_addr host_addr ;
44
+ int is_ipv4 ;
45
+ int is_ipv6 ;
46
+ struct sockaddr_in host ;
47
+ struct sockaddr_in guest ;
48
+ struct sockaddr_in6 host6 ;
49
+ struct sockaddr_in6 guest6 ;
45
50
int host_port ;
46
- struct in_addr guest_addr ;
47
51
int guest_port ;
48
52
};
49
53
@@ -107,9 +111,9 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
107
111
exit (EXIT_FAILURE );
108
112
}
109
113
fwd -> is_udp = -1 ; /* TODO: support SCTP */
110
- if (strcmp (proto_s , "udp" ) == 0 ) {
114
+ if (strncmp (proto_s , "udp" , 3 ) == 0 ) {
111
115
fwd -> is_udp = 1 ;
112
- } else if (strcmp (proto_s , "tcp" ) == 0 ) {
116
+ } else if (strncmp (proto_s , "tcp" , 3 ) == 0 ) {
113
117
fwd -> is_udp = 0 ;
114
118
}
115
119
if (fwd -> is_udp == -1 ) {
@@ -119,16 +123,59 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
119
123
free (fwd );
120
124
goto finish ;
121
125
}
126
+ int flags = (fwd -> is_udp ? SLIRP_HOSTFWD_UDP : 0 );
127
+
122
128
if (host_addr_s == NULL || host_addr_s [0 ] == '\0' ) {
123
129
host_addr_s = "0.0.0.0" ;
124
130
}
125
- if (inet_pton (AF_INET , host_addr_s , & fwd -> host_addr ) != 1 ) {
126
- const char * err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
127
- "bad arguments.host_addr\"}}" ;
128
- wrc = write (fd , err , strlen (err ));
129
- free (fwd );
130
- goto finish ;
131
+ if (strcmp ("0.0.0.0" , host_addr_s ) == 0 ||
132
+ strcmp ("::" , host_addr_s ) == 0 ||
133
+ strcmp ("::0" , host_addr_s ) == 0 ) {
134
+ fwd -> is_ipv4 = 1 ;
135
+ fwd -> is_ipv6 = ctx -> cfg -> enable_ipv6 ;
136
+ host_addr_s = "0.0.0.0" ;
137
+ } else {
138
+ if (strchr (host_addr_s , '.' )) {
139
+ fwd -> is_ipv4 = 1 ;
140
+ }
141
+ else if (strchr (host_addr_s , ':' )) {
142
+ if (!ctx -> cfg -> enable_ipv6 ) {
143
+ const char * err =
144
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
145
+ "bad arguments.host_addr\"}}" ;
146
+ wrc = write (fd , err , strlen (err ));
147
+ free (fwd );
148
+ goto finish ;
149
+ }
150
+ fwd -> is_ipv6 = 1 ;
151
+ }
152
+ }
153
+
154
+ if (strlen (proto_s ) == 4 ) {
155
+ if (proto_s [3 ] == '4' ) {
156
+ fwd -> is_ipv4 = 1 ;
157
+ fwd -> is_ipv6 = 0 ;
158
+ } else if (proto_s [3 ] == '6' ) {
159
+ if (!ctx -> cfg -> enable_ipv6 ) {
160
+ const char * err =
161
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
162
+ "bad arguments.proto\"}}" ;
163
+ wrc = write (fd , err , strlen (err ));
164
+ free (fwd );
165
+ goto finish ;
166
+ }
167
+ fwd -> is_ipv4 = 0 ;
168
+ fwd -> is_ipv6 = 1 ;
169
+ } else {
170
+ const char * err =
171
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
172
+ "bad arguments.proto\"}}" ;
173
+ wrc = write (fd , err , strlen (err ));
174
+ free (fwd );
175
+ goto finish ;
176
+ }
131
177
}
178
+
132
179
fwd -> host_port = (int )json_object_dotget_number (jo , "arguments.host_port" );
133
180
if (fwd -> host_port == 0 ) {
134
181
const char * err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
@@ -137,16 +184,6 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
137
184
free (fwd );
138
185
goto finish ;
139
186
}
140
-
141
- if (guest_addr_s == NULL || guest_addr_s [0 ] == '\0' ) {
142
- fwd -> guest_addr = ctx -> cfg -> recommended_vguest ;
143
- } else if (inet_pton (AF_INET , guest_addr_s , & fwd -> guest_addr ) != 1 ) {
144
- const char * err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
145
- "bad arguments.guest_addr\"}}" ;
146
- wrc = write (fd , err , strlen (err ));
147
- free (fwd );
148
- goto finish ;
149
- }
150
187
fwd -> guest_port =
151
188
(int )json_object_dotget_number (jo , "arguments.guest_port" );
152
189
if (fwd -> guest_port == 0 ) {
@@ -156,13 +193,77 @@ static int api_handle_req_add_hostfwd(Slirp *slirp, int fd, struct api_ctx *ctx,
156
193
free (fwd );
157
194
goto finish ;
158
195
}
159
- if (slirp_add_hostfwd (slirp , fwd -> is_udp , fwd -> host_addr , fwd -> host_port ,
160
- fwd -> guest_addr , fwd -> guest_port ) < 0 ) {
161
- const char * err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
162
- "slirp_add_hostfwd failed\"}}" ;
163
- wrc = write (fd , err , strlen (err ));
164
- free (fwd );
165
- goto finish ;
196
+
197
+ if (fwd -> is_ipv4 ) {
198
+ fwd -> host .sin_family = AF_INET ;
199
+ fwd -> guest .sin_family = AF_INET ;
200
+ fwd -> host .sin_port = htons (fwd -> host_port );
201
+ fwd -> guest .sin_port = htons (fwd -> guest_port );
202
+ if (guest_addr_s == NULL || guest_addr_s [0 ] == '\0' ) {
203
+ fwd -> guest .sin_addr = ctx -> cfg -> recommended_vguest ;
204
+ } else if (inet_pton (AF_INET , guest_addr_s , & fwd -> guest .sin_addr ) != 1 ) {
205
+ const char * err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
206
+ "bad arguments.guest_addr\"}}" ;
207
+ wrc = write (fd , err , strlen (err ));
208
+ free (fwd );
209
+ goto finish ;
210
+ }
211
+ if (inet_pton (AF_INET , host_addr_s , & fwd -> host .sin_addr ) != 1 ) {
212
+ const char * err =
213
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
214
+ "bad arguments.host_addr\"}}" ;
215
+ wrc = write (fd , err , strlen (err ));
216
+ free (fwd );
217
+ goto finish ;
218
+ }
219
+ if (slirp_add_hostxfwd (slirp ,
220
+ (const struct sockaddr * )& fwd -> host , sizeof (fwd -> host ),
221
+ (const struct sockaddr * )& fwd -> guest , sizeof (fwd -> guest ), flags ) < 0 ) {
222
+ const char * err =
223
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
224
+ "slirp_add_hostxfwd failed\"}}" ;
225
+ wrc = write (fd , err , strlen (err ));
226
+ free (fwd );
227
+ goto finish ;
228
+ }
229
+ }
230
+
231
+ if (fwd -> is_ipv6 ) {
232
+ fwd -> host6 .sin6_family = AF_INET6 ;
233
+ fwd -> guest6 .sin6_family = AF_INET6 ;
234
+ fwd -> host6 .sin6_port = htons (fwd -> host_port );
235
+ fwd -> guest6 .sin6_port = htons (fwd -> guest_port );
236
+ if (guest_addr_s == NULL || guest_addr_s [0 ] == '\0' ) {
237
+ fwd -> guest6 .sin6_addr = ctx -> cfg -> recommended_vguest6 ;
238
+ } else if (inet_pton (AF_INET6 , guest_addr_s , & fwd -> guest6 .sin6_addr ) != 1 ) {
239
+ const char * err = "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
240
+ "bad arguments.guest_addr\"}}" ;
241
+ wrc = write (fd , err , strlen (err ));
242
+ free (fwd );
243
+ goto finish ;
244
+ }
245
+ if (strcmp (host_addr_s , "0.0.0.0" ) == 0 ) {
246
+ host_addr_s = "::" ;
247
+ }
248
+ if (inet_pton (AF_INET6 , host_addr_s , & fwd -> host6 .sin6_addr ) != 1 ) {
249
+ const char * err =
250
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
251
+ "bad arguments.host_addr\"}}" ;
252
+ wrc = write (fd , err , strlen (err ));
253
+ free (fwd );
254
+ goto finish ;
255
+ }
256
+ flags |= SLIRP_HOSTFWD_V6ONLY ;
257
+ if (slirp_add_hostxfwd (slirp ,
258
+ (const struct sockaddr * )& fwd -> host6 , sizeof (fwd -> host6 ),
259
+ (const struct sockaddr * )& fwd -> guest6 , sizeof (fwd -> guest6 ), flags ) < 0 ) {
260
+ const char * err =
261
+ "{\"error\":{\"desc\":\"bad request: add_hostfwd: "
262
+ "slirp_add_hostxfwd failed\"}}" ;
263
+ wrc = write (fd , err , strlen (err ));
264
+ free (fwd );
265
+ goto finish ;
266
+ }
166
267
}
167
268
fwd -> id = ctx -> hostfwds_nextid ;
168
269
ctx -> hostfwds_nextid ++ ;
@@ -185,21 +286,46 @@ static void api_handle_req_list_hostfwd_foreach(gpointer data,
185
286
JSON_Value * entry_value = json_value_init_object ();
186
287
JSON_Object * entry_object = json_value_get_object (entry_value );
187
288
char host_addr [INET_ADDRSTRLEN ], guest_addr [INET_ADDRSTRLEN ];
188
- if (inet_ntop (AF_INET , & fwd -> host_addr , host_addr , sizeof (host_addr )) ==
189
- NULL ) {
190
- perror ("fatal: inet_ntop" );
191
- exit (EXIT_FAILURE );
289
+ char host_addr6 [INET6_ADDRSTRLEN ], guest_addr6 [INET6_ADDRSTRLEN ];
290
+ if (fwd -> is_ipv4 ) {
291
+ if (inet_ntop (AF_INET , & fwd -> host .sin_addr , host_addr , sizeof (host_addr )) ==
292
+ NULL ) {
293
+ perror ("fatal: inet_ntop" );
294
+ exit (EXIT_FAILURE );
295
+ }
296
+ if (inet_ntop (AF_INET , & fwd -> guest .sin_addr , guest_addr , sizeof (guest_addr )) ==
297
+ NULL ) {
298
+ perror ("fatal: inet_ntop" );
299
+ exit (EXIT_FAILURE );
300
+ }
192
301
}
193
- if (inet_ntop (AF_INET , & fwd -> guest_addr , guest_addr , sizeof (guest_addr )) ==
194
- NULL ) {
195
- perror ("fatal: inet_ntop" );
196
- exit (EXIT_FAILURE );
302
+ if (fwd -> is_ipv6 ) {
303
+ if (inet_ntop (AF_INET6 , & fwd -> host6 .sin6_addr , host_addr6 , sizeof (host_addr6 )) ==
304
+ NULL ) {
305
+ perror ("fatal: inet_ntop" );
306
+ exit (EXIT_FAILURE );
307
+ }
308
+ if (inet_ntop (AF_INET6 , & fwd -> guest6 .sin6_addr , guest_addr6 , sizeof (guest_addr6 )) ==
309
+ NULL ) {
310
+ perror ("fatal: inet_ntop" );
311
+ exit (EXIT_FAILURE );
312
+ }
197
313
}
198
314
json_object_set_number (entry_object , "id" , fwd -> id );
199
315
json_object_set_string (entry_object , "proto" , fwd -> is_udp ? "udp" : "tcp" );
200
- json_object_set_string (entry_object , "host_addr" , host_addr );
316
+ if (fwd -> is_ipv4 ) {
317
+ json_object_set_string (entry_object , "host_addr" , host_addr );
318
+ }
319
+ if (fwd -> is_ipv6 ) {
320
+ json_object_set_string (entry_object , "host_addr6" , host_addr6 );
321
+ }
201
322
json_object_set_number (entry_object , "host_port" , fwd -> host_port );
202
- json_object_set_string (entry_object , "guest_addr" , guest_addr );
323
+ if (fwd -> is_ipv4 ) {
324
+ json_object_set_string (entry_object , "guest_addr" , guest_addr );
325
+ }
326
+ if (fwd -> is_ipv6 ) {
327
+ json_object_set_string (entry_object , "guest_addr6" , guest_addr6 );
328
+ }
203
329
json_object_set_number (entry_object , "guest_port" , fwd -> guest_port );
204
330
/* json_array_append_value does not copy passed value */
205
331
if (json_array_append_value (entries_array , entry_value ) != JSONSuccess ) {
@@ -257,16 +383,25 @@ static int api_handle_req_remove_hostfwd(Slirp *slirp, int fd,
257
383
} else {
258
384
struct api_hostfwd * fwd = found -> data ;
259
385
const char * api_ok = "{\"return\":{}}" ;
260
- if (slirp_remove_hostfwd (slirp , fwd -> is_udp , fwd -> host_addr ,
261
- fwd -> host_port ) < 0 ) {
262
- const char * err = "{\"error\":{\"desc\":\"bad request: "
263
- "remove_hostfwd: slirp_remove_hostfwd failed\"}}" ;
264
- wrc = write (fd , err , strlen (err ));
265
- } else {
266
- ctx -> hostfwds = g_list_remove (ctx -> hostfwds , fwd );
267
- g_free (fwd );
268
- wrc = write (fd , api_ok , strlen (api_ok ));
386
+ if (fwd -> is_ipv4 ) {
387
+ if (slirp_remove_hostxfwd (slirp ,
388
+ (const struct sockaddr * )& fwd -> host , sizeof (fwd -> host ), 0 ) < 0 ) {
389
+ const char * err = "{\"error\":{\"desc\":\"bad request: "
390
+ "remove_hostfwd: slirp_remove_hostxfwd failed\"}}" ;
391
+ return write (fd , err , strlen (err ));
392
+ }
393
+ }
394
+ if (fwd -> is_ipv6 ) {
395
+ if (slirp_remove_hostxfwd (slirp ,
396
+ (const struct sockaddr * )& fwd -> host6 , sizeof (fwd -> host6 ), 0 ) < 0 ) {
397
+ const char * err = "{\"error\":{\"desc\":\"bad request: "
398
+ "remove_hostfwd: slirp_remove_hostxfwd failed\"}}" ;
399
+ return write (fd , err , strlen (err ));
400
+ }
269
401
}
402
+ ctx -> hostfwds = g_list_remove (ctx -> hostfwds , fwd );
403
+ g_free (fwd );
404
+ wrc = write (fd , api_ok , strlen (api_ok ));
270
405
}
271
406
return wrc ;
272
407
}
0 commit comments