aboutsummaryrefslogtreecommitdiff
path: root/src/nat/miniupnp
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/miniupnp')
-rw-r--r--src/nat/miniupnp/Makefile.am31
-rw-r--r--src/nat/miniupnp/README3
-rw-r--r--src/nat/miniupnp/bsdqueue.h531
-rw-r--r--src/nat/miniupnp/codelength.h23
-rw-r--r--src/nat/miniupnp/declspec.h14
-rw-r--r--src/nat/miniupnp/igd_desc_parse.c126
-rw-r--r--src/nat/miniupnp/igd_desc_parse.h47
-rw-r--r--src/nat/miniupnp/minisoap.c106
-rw-r--r--src/nat/miniupnp/minisoap.h14
-rw-r--r--src/nat/miniupnp/minissdpc.c111
-rw-r--r--src/nat/miniupnp/minissdpc.h14
-rw-r--r--src/nat/miniupnp/miniupnpc.c901
-rw-r--r--src/nat/miniupnp/miniupnpc.h120
-rw-r--r--src/nat/miniupnp/miniupnpcstrings.h14
-rw-r--r--src/nat/miniupnp/miniwget.c224
-rw-r--r--src/nat/miniupnp/miniwget.h28
-rw-r--r--src/nat/miniupnp/minixml.c200
-rw-r--r--src/nat/miniupnp/minixml.h37
-rw-r--r--src/nat/miniupnp/upnpcommands.c605
-rw-r--r--src/nat/miniupnp/upnpcommands.h189
-rw-r--r--src/nat/miniupnp/upnpreplyparse.c122
-rw-r--r--src/nat/miniupnp/upnpreplyparse.h60
22 files changed, 0 insertions, 3520 deletions
diff --git a/src/nat/miniupnp/Makefile.am b/src/nat/miniupnp/Makefile.am
deleted file mode 100644
index 731c41a84..000000000
--- a/src/nat/miniupnp/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
1noinst_LTLIBRARIES = libminiupnp.la
2
3AM_CPPFLAGS = -DNDEBUG
4
5libminiupnp_la_SOURCES = \
6 igd_desc_parse.c \
7 minisoap.c \
8 minissdpc.c \
9 miniupnpc.c \
10 miniwget.c \
11 minixml.c \
12 upnpcommands.c \
13 upnpreplyparse.c
14
15noinst_HEADERS = \
16 bsdqueue.h \
17 codelength.h \
18 declspec.h \
19 igd_desc_parse.h \
20 minisoap.h \
21 minissdpc.h \
22 miniupnpc.h \
23 miniupnpcstrings.h \
24 miniwget.h \
25 minixml.h \
26 upnpcommands.h \
27 upnpreplyparse.h
28
29extra_DIST = \
30 README \
31 LICENSE
diff --git a/src/nat/miniupnp/README b/src/nat/miniupnp/README
deleted file mode 100644
index 45aec9084..000000000
--- a/src/nat/miniupnp/README
+++ /dev/null
@@ -1,3 +0,0 @@
1MiniUPnP is written by Thomas Bernard.
2Its homepage is http://miniupnp.free.fr/
3This is from miniupnpc-1.3.tar.gz
diff --git a/src/nat/miniupnp/bsdqueue.h b/src/nat/miniupnp/bsdqueue.h
deleted file mode 100644
index f763172c4..000000000
--- a/src/nat/miniupnp/bsdqueue.h
+++ /dev/null
@@ -1,531 +0,0 @@
1/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
2/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
3
4/*
5 * Copyright (c) 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)queue.h 8.5 (Berkeley) 8/20/94
33 */
34
35#ifndef _SYS_QUEUE_H_
36#define _SYS_QUEUE_H_
37
38/*
39 * This file defines five types of data structures: singly-linked lists,
40 * lists, simple queues, tail queues, and circular queues.
41 *
42 *
43 * A singly-linked list is headed by a single forward pointer. The elements
44 * are singly linked for minimum space and pointer manipulation overhead at
45 * the expense of O(n) removal for arbitrary elements. New elements can be
46 * added to the list after an existing element or at the head of the list.
47 * Elements being removed from the head of the list should use the explicit
48 * macro for this purpose for optimum efficiency. A singly-linked list may
49 * only be traversed in the forward direction. Singly-linked lists are ideal
50 * for applications with large datasets and few or no removals or for
51 * implementing a LIFO queue.
52 *
53 * A list is headed by a single forward pointer (or an array of forward
54 * pointers for a hash table header). The elements are doubly linked
55 * so that an arbitrary element can be removed without a need to
56 * traverse the list. New elements can be added to the list before
57 * or after an existing element or at the head of the list. A list
58 * may only be traversed in the forward direction.
59 *
60 * A simple queue is headed by a pair of pointers, one the head of the
61 * list and the other to the tail of the list. The elements are singly
62 * linked to save space, so elements can only be removed from the
63 * head of the list. New elements can be added to the list before or after
64 * an existing element, at the head of the list, or at the end of the
65 * list. A simple queue may only be traversed in the forward direction.
66 *
67 * A tail queue is headed by a pair of pointers, one to the head of the
68 * list and the other to the tail of the list. The elements are doubly
69 * linked so that an arbitrary element can be removed without a need to
70 * traverse the list. New elements can be added to the list before or
71 * after an existing element, at the head of the list, or at the end of
72 * the list. A tail queue may be traversed in either direction.
73 *
74 * A circle queue is headed by a pair of pointers, one to the head of the
75 * list and the other to the tail of the list. The elements are doubly
76 * linked so that an arbitrary element can be removed without a need to
77 * traverse the list. New elements can be added to the list before or after
78 * an existing element, at the head of the list, or at the end of the list.
79 * A circle queue may be traversed in either direction, but has a more
80 * complex end of list detection.
81 *
82 * For details on the use of these macros, see the queue(3) manual page.
83 */
84
85#ifdef QUEUE_MACRO_DEBUG
86#define _Q_INVALIDATE(a) (a) = ((void *)-1)
87#else
88#define _Q_INVALIDATE(a)
89#endif
90
91/*
92 * Singly-linked List definitions.
93 */
94#define SLIST_HEAD(name, type) \
95struct name { \
96 struct type *slh_first; /* first element */ \
97}
98
99#define SLIST_HEAD_INITIALIZER(head) \
100 { NULL }
101
102#ifdef SLIST_ENTRY
103#undef SLIST_ENTRY
104#endif
105
106#define SLIST_ENTRY(type) \
107struct { \
108 struct type *sle_next; /* next element */ \
109}
110
111/*
112 * Singly-linked List access methods.
113 */
114#define SLIST_FIRST(head) ((head)->slh_first)
115#define SLIST_END(head) NULL
116#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
117#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
118
119#define SLIST_FOREACH(var, head, field) \
120 for((var) = SLIST_FIRST(head); \
121 (var) != SLIST_END(head); \
122 (var) = SLIST_NEXT(var, field))
123
124#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
125 for ((varp) = &SLIST_FIRST((head)); \
126 ((var) = *(varp)) != SLIST_END(head); \
127 (varp) = &SLIST_NEXT((var), field))
128
129/*
130 * Singly-linked List functions.
131 */
132#define SLIST_INIT(head) { \
133 SLIST_FIRST(head) = SLIST_END(head); \
134}
135
136#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
137 (elm)->field.sle_next = (slistelm)->field.sle_next; \
138 (slistelm)->field.sle_next = (elm); \
139} while (0)
140
141#define SLIST_INSERT_HEAD(head, elm, field) do { \
142 (elm)->field.sle_next = (head)->slh_first; \
143 (head)->slh_first = (elm); \
144} while (0)
145
146#define SLIST_REMOVE_NEXT(head, elm, field) do { \
147 (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
148} while (0)
149
150#define SLIST_REMOVE_HEAD(head, field) do { \
151 (head)->slh_first = (head)->slh_first->field.sle_next; \
152} while (0)
153
154#define SLIST_REMOVE(head, elm, type, field) do { \
155 if ((head)->slh_first == (elm)) { \
156 SLIST_REMOVE_HEAD((head), field); \
157 } else { \
158 struct type *curelm = (head)->slh_first; \
159 \
160 while (curelm->field.sle_next != (elm)) \
161 curelm = curelm->field.sle_next; \
162 curelm->field.sle_next = \
163 curelm->field.sle_next->field.sle_next; \
164 _Q_INVALIDATE((elm)->field.sle_next); \
165 } \
166} while (0)
167
168/*
169 * List definitions.
170 */
171#define LIST_HEAD(name, type) \
172struct name { \
173 struct type *lh_first; /* first element */ \
174}
175
176#define LIST_HEAD_INITIALIZER(head) \
177 { NULL }
178
179#define LIST_ENTRY(type) \
180struct { \
181 struct type *le_next; /* next element */ \
182 struct type **le_prev; /* address of previous next element */ \
183}
184
185/*
186 * List access methods
187 */
188#define LIST_FIRST(head) ((head)->lh_first)
189#define LIST_END(head) NULL
190#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
191#define LIST_NEXT(elm, field) ((elm)->field.le_next)
192
193#define LIST_FOREACH(var, head, field) \
194 for((var) = LIST_FIRST(head); \
195 (var)!= LIST_END(head); \
196 (var) = LIST_NEXT(var, field))
197
198/*
199 * List functions.
200 */
201#define LIST_INIT(head) do { \
202 LIST_FIRST(head) = LIST_END(head); \
203} while (0)
204
205#define LIST_INSERT_AFTER(listelm, elm, field) do { \
206 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
207 (listelm)->field.le_next->field.le_prev = \
208 &(elm)->field.le_next; \
209 (listelm)->field.le_next = (elm); \
210 (elm)->field.le_prev = &(listelm)->field.le_next; \
211} while (0)
212
213#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
214 (elm)->field.le_prev = (listelm)->field.le_prev; \
215 (elm)->field.le_next = (listelm); \
216 *(listelm)->field.le_prev = (elm); \
217 (listelm)->field.le_prev = &(elm)->field.le_next; \
218} while (0)
219
220#define LIST_INSERT_HEAD(head, elm, field) do { \
221 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
222 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
223 (head)->lh_first = (elm); \
224 (elm)->field.le_prev = &(head)->lh_first; \
225} while (0)
226
227#define LIST_REMOVE(elm, field) do { \
228 if ((elm)->field.le_next != NULL) \
229 (elm)->field.le_next->field.le_prev = \
230 (elm)->field.le_prev; \
231 *(elm)->field.le_prev = (elm)->field.le_next; \
232 _Q_INVALIDATE((elm)->field.le_prev); \
233 _Q_INVALIDATE((elm)->field.le_next); \
234} while (0)
235
236#define LIST_REPLACE(elm, elm2, field) do { \
237 if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
238 (elm2)->field.le_next->field.le_prev = \
239 &(elm2)->field.le_next; \
240 (elm2)->field.le_prev = (elm)->field.le_prev; \
241 *(elm2)->field.le_prev = (elm2); \
242 _Q_INVALIDATE((elm)->field.le_prev); \
243 _Q_INVALIDATE((elm)->field.le_next); \
244} while (0)
245
246/*
247 * Simple queue definitions.
248 */
249#define SIMPLEQ_HEAD(name, type) \
250struct name { \
251 struct type *sqh_first; /* first element */ \
252 struct type **sqh_last; /* addr of last next element */ \
253}
254
255#define SIMPLEQ_HEAD_INITIALIZER(head) \
256 { NULL, &(head).sqh_first }
257
258#define SIMPLEQ_ENTRY(type) \
259struct { \
260 struct type *sqe_next; /* next element */ \
261}
262
263/*
264 * Simple queue access methods.
265 */
266#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
267#define SIMPLEQ_END(head) NULL
268#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
269#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
270
271#define SIMPLEQ_FOREACH(var, head, field) \
272 for((var) = SIMPLEQ_FIRST(head); \
273 (var) != SIMPLEQ_END(head); \
274 (var) = SIMPLEQ_NEXT(var, field))
275
276/*
277 * Simple queue functions.
278 */
279#define SIMPLEQ_INIT(head) do { \
280 (head)->sqh_first = NULL; \
281 (head)->sqh_last = &(head)->sqh_first; \
282} while (0)
283
284#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
285 if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
286 (head)->sqh_last = &(elm)->field.sqe_next; \
287 (head)->sqh_first = (elm); \
288} while (0)
289
290#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
291 (elm)->field.sqe_next = NULL; \
292 *(head)->sqh_last = (elm); \
293 (head)->sqh_last = &(elm)->field.sqe_next; \
294} while (0)
295
296#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
297 if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
298 (head)->sqh_last = &(elm)->field.sqe_next; \
299 (listelm)->field.sqe_next = (elm); \
300} while (0)
301
302#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
303 if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
304 (head)->sqh_last = &(head)->sqh_first; \
305} while (0)
306
307/*
308 * Tail queue definitions.
309 */
310#define TAILQ_HEAD(name, type) \
311struct name { \
312 struct type *tqh_first; /* first element */ \
313 struct type **tqh_last; /* addr of last next element */ \
314}
315
316#define TAILQ_HEAD_INITIALIZER(head) \
317 { NULL, &(head).tqh_first }
318
319#define TAILQ_ENTRY(type) \
320struct { \
321 struct type *tqe_next; /* next element */ \
322 struct type **tqe_prev; /* address of previous next element */ \
323}
324
325/*
326 * tail queue access methods
327 */
328#define TAILQ_FIRST(head) ((head)->tqh_first)
329#define TAILQ_END(head) NULL
330#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
331#define TAILQ_LAST(head, headname) \
332 (*(((struct headname *)((head)->tqh_last))->tqh_last))
333/* XXX */
334#define TAILQ_PREV(elm, headname, field) \
335 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
336#define TAILQ_EMPTY(head) \
337 (TAILQ_FIRST(head) == TAILQ_END(head))
338
339#define TAILQ_FOREACH(var, head, field) \
340 for((var) = TAILQ_FIRST(head); \
341 (var) != TAILQ_END(head); \
342 (var) = TAILQ_NEXT(var, field))
343
344#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
345 for((var) = TAILQ_LAST(head, headname); \
346 (var) != TAILQ_END(head); \
347 (var) = TAILQ_PREV(var, headname, field))
348
349/*
350 * Tail queue functions.
351 */
352#define TAILQ_INIT(head) do { \
353 (head)->tqh_first = NULL; \
354 (head)->tqh_last = &(head)->tqh_first; \
355} while (0)
356
357#define TAILQ_INSERT_HEAD(head, elm, field) do { \
358 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
359 (head)->tqh_first->field.tqe_prev = \
360 &(elm)->field.tqe_next; \
361 else \
362 (head)->tqh_last = &(elm)->field.tqe_next; \
363 (head)->tqh_first = (elm); \
364 (elm)->field.tqe_prev = &(head)->tqh_first; \
365} while (0)
366
367#define TAILQ_INSERT_TAIL(head, elm, field) do { \
368 (elm)->field.tqe_next = NULL; \
369 (elm)->field.tqe_prev = (head)->tqh_last; \
370 *(head)->tqh_last = (elm); \
371 (head)->tqh_last = &(elm)->field.tqe_next; \
372} while (0)
373
374#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
375 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
376 (elm)->field.tqe_next->field.tqe_prev = \
377 &(elm)->field.tqe_next; \
378 else \
379 (head)->tqh_last = &(elm)->field.tqe_next; \
380 (listelm)->field.tqe_next = (elm); \
381 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
382} while (0)
383
384#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
385 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
386 (elm)->field.tqe_next = (listelm); \
387 *(listelm)->field.tqe_prev = (elm); \
388 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
389} while (0)
390
391#define TAILQ_REMOVE(head, elm, field) do { \
392 if (((elm)->field.tqe_next) != NULL) \
393 (elm)->field.tqe_next->field.tqe_prev = \
394 (elm)->field.tqe_prev; \
395 else \
396 (head)->tqh_last = (elm)->field.tqe_prev; \
397 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
398 _Q_INVALIDATE((elm)->field.tqe_prev); \
399 _Q_INVALIDATE((elm)->field.tqe_next); \
400} while (0)
401
402#define TAILQ_REPLACE(head, elm, elm2, field) do { \
403 if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
404 (elm2)->field.tqe_next->field.tqe_prev = \
405 &(elm2)->field.tqe_next; \
406 else \
407 (head)->tqh_last = &(elm2)->field.tqe_next; \
408 (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
409 *(elm2)->field.tqe_prev = (elm2); \
410 _Q_INVALIDATE((elm)->field.tqe_prev); \
411 _Q_INVALIDATE((elm)->field.tqe_next); \
412} while (0)
413
414/*
415 * Circular queue definitions.
416 */
417#define CIRCLEQ_HEAD(name, type) \
418struct name { \
419 struct type *cqh_first; /* first element */ \
420 struct type *cqh_last; /* last element */ \
421}
422
423#define CIRCLEQ_HEAD_INITIALIZER(head) \
424 { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
425
426#define CIRCLEQ_ENTRY(type) \
427struct { \
428 struct type *cqe_next; /* next element */ \
429 struct type *cqe_prev; /* previous element */ \
430}
431
432/*
433 * Circular queue access methods
434 */
435#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
436#define CIRCLEQ_LAST(head) ((head)->cqh_last)
437#define CIRCLEQ_END(head) ((void *)(head))
438#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
439#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
440#define CIRCLEQ_EMPTY(head) \
441 (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
442
443#define CIRCLEQ_FOREACH(var, head, field) \
444 for((var) = CIRCLEQ_FIRST(head); \
445 (var) != CIRCLEQ_END(head); \
446 (var) = CIRCLEQ_NEXT(var, field))
447
448#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
449 for((var) = CIRCLEQ_LAST(head); \
450 (var) != CIRCLEQ_END(head); \
451 (var) = CIRCLEQ_PREV(var, field))
452
453/*
454 * Circular queue functions.
455 */
456#define CIRCLEQ_INIT(head) do { \
457 (head)->cqh_first = CIRCLEQ_END(head); \
458 (head)->cqh_last = CIRCLEQ_END(head); \
459} while (0)
460
461#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
462 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
463 (elm)->field.cqe_prev = (listelm); \
464 if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
465 (head)->cqh_last = (elm); \
466 else \
467 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
468 (listelm)->field.cqe_next = (elm); \
469} while (0)
470
471#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
472 (elm)->field.cqe_next = (listelm); \
473 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
474 if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
475 (head)->cqh_first = (elm); \
476 else \
477 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
478 (listelm)->field.cqe_prev = (elm); \
479} while (0)
480
481#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
482 (elm)->field.cqe_next = (head)->cqh_first; \
483 (elm)->field.cqe_prev = CIRCLEQ_END(head); \
484 if ((head)->cqh_last == CIRCLEQ_END(head)) \
485 (head)->cqh_last = (elm); \
486 else \
487 (head)->cqh_first->field.cqe_prev = (elm); \
488 (head)->cqh_first = (elm); \
489} while (0)
490
491#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
492 (elm)->field.cqe_next = CIRCLEQ_END(head); \
493 (elm)->field.cqe_prev = (head)->cqh_last; \
494 if ((head)->cqh_first == CIRCLEQ_END(head)) \
495 (head)->cqh_first = (elm); \
496 else \
497 (head)->cqh_last->field.cqe_next = (elm); \
498 (head)->cqh_last = (elm); \
499} while (0)
500
501#define CIRCLEQ_REMOVE(head, elm, field) do { \
502 if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
503 (head)->cqh_last = (elm)->field.cqe_prev; \
504 else \
505 (elm)->field.cqe_next->field.cqe_prev = \
506 (elm)->field.cqe_prev; \
507 if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
508 (head)->cqh_first = (elm)->field.cqe_next; \
509 else \
510 (elm)->field.cqe_prev->field.cqe_next = \
511 (elm)->field.cqe_next; \
512 _Q_INVALIDATE((elm)->field.cqe_prev); \
513 _Q_INVALIDATE((elm)->field.cqe_next); \
514} while (0)
515
516#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
517 if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
518 CIRCLEQ_END(head)) \
519 (head).cqh_last = (elm2); \
520 else \
521 (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
522 if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
523 CIRCLEQ_END(head)) \
524 (head).cqh_first = (elm2); \
525 else \
526 (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
527 _Q_INVALIDATE((elm)->field.cqe_prev); \
528 _Q_INVALIDATE((elm)->field.cqe_next); \
529} while (0)
530
531#endif /* !_SYS_QUEUE_H_ */
diff --git a/src/nat/miniupnp/codelength.h b/src/nat/miniupnp/codelength.h
deleted file mode 100644
index 8a5f49517..000000000
--- a/src/nat/miniupnp/codelength.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/* $Id: codelength.h,v 1.1 2008/10/06 22:04:06 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas BERNARD
4 * copyright (c) 2005-2008 Thomas Bernard
5 * This software is subjet to the conditions detailed in the
6 * provided LICENCE file. */
7#ifndef __CODELENGTH_H__
8#define __CODELENGTH_H__
9
10/* Encode length by using 7bit per Byte :
11 * Most significant bit of each byte specifies that the
12 * following byte is part of the code */
13#define DECODELENGTH(n, p) n = 0; \
14 do { n = (n << 7) | (*p & 0x7f); } \
15 while(*(p++)&0x80);
16
17#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
18 if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
19 if(n>=16384) *(p++) = (n >> 14) | 0x80; \
20 if(n>=128) *(p++) = (n >> 7) | 0x80; \
21 *(p++) = n & 0x7f;
22
23#endif
diff --git a/src/nat/miniupnp/declspec.h b/src/nat/miniupnp/declspec.h
deleted file mode 100644
index c064bded2..000000000
--- a/src/nat/miniupnp/declspec.h
+++ /dev/null
@@ -1,14 +0,0 @@
1#ifndef __DECLSPEC_H__
2#define __DECLSPEC_H__
3
4#if defined(WIN32) && !defined(STATICLIB)
5#ifdef MINIUPNP_EXPORTS
6#define LIBSPEC __declspec(dllexport)
7#else
8#define LIBSPEC __declspec(dllimport)
9#endif
10#else
11#define LIBSPEC
12#endif
13
14#endif
diff --git a/src/nat/miniupnp/igd_desc_parse.c b/src/nat/miniupnp/igd_desc_parse.c
deleted file mode 100644
index deb53152c..000000000
--- a/src/nat/miniupnp/igd_desc_parse.c
+++ /dev/null
@@ -1,126 +0,0 @@
1/* $Id: igd_desc_parse.c,v 1.8 2008/04/23 11:51:06 nanard Exp $ */
2/* Project : miniupnp
3 * http://miniupnp.free.fr/
4 * Author : Thomas Bernard
5 * Copyright (c) 2005-2008 Thomas Bernard
6 * This software is subject to the conditions detailed in the
7 * LICENCE file provided in this distribution.
8 * */
9#include "igd_desc_parse.h"
10#include <stdio.h>
11#include <string.h>
12
13/* TODO : rewrite this code so it correctly handle descriptions with
14 * both WANIPConnection and/or WANPPPConnection */
15
16/* Start element handler :
17 * update nesting level counter and copy element name */
18void
19IGDstartelt (void *d, const char *name, int l)
20{
21 struct IGDdatas *datas = (struct IGDdatas *) d;
22 memcpy (datas->cureltname, name, l);
23 datas->cureltname[l] = '\0';
24 datas->level++;
25 if ((l == 7) && !memcmp (name, "service", l))
26 {
27 datas->controlurl_tmp[0] = '\0';
28 datas->eventsuburl_tmp[0] = '\0';
29 datas->scpdurl_tmp[0] = '\0';
30 datas->servicetype_tmp[0] = '\0';
31 }
32}
33
34/* End element handler :
35 * update nesting level counter and update parser state if
36 * service element is parsed */
37void
38IGDendelt (void *d, const char *name, int l)
39{
40 struct IGDdatas *datas = (struct IGDdatas *) d;
41 datas->level--;
42 /*printf("endelt %2d %.*s\n", datas->level, l, name); */
43 if ((l == 7) && !memcmp (name, "service", l))
44 {
45 /*
46 if( datas->state < 1
47 && !strcmp(datas->servicetype,
48 // "urn:schemas-upnp-org:service:WANIPConnection:1") )
49 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
50 datas->state ++;
51 */
52 if (0 == strcmp (datas->servicetype_tmp,
53 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
54 {
55 memcpy (datas->controlurl_CIF, datas->controlurl_tmp,
56 MINIUPNPC_URL_MAXSIZE);
57 memcpy (datas->eventsuburl_CIF, datas->eventsuburl_tmp,
58 MINIUPNPC_URL_MAXSIZE);
59 memcpy (datas->scpdurl_CIF, datas->scpdurl_tmp,
60 MINIUPNPC_URL_MAXSIZE);
61 memcpy (datas->servicetype_CIF, datas->servicetype_tmp,
62 MINIUPNPC_URL_MAXSIZE);
63 }
64 else if (0 == strcmp (datas->servicetype_tmp,
65 "urn:schemas-upnp-org:service:WANIPConnection:1")
66 || 0 == strcmp (datas->servicetype_tmp,
67 "urn:schemas-upnp-org:service:WANPPPConnection:1"))
68 {
69 memcpy (datas->controlurl, datas->controlurl_tmp,
70 MINIUPNPC_URL_MAXSIZE);
71 memcpy (datas->eventsuburl, datas->eventsuburl_tmp,
72 MINIUPNPC_URL_MAXSIZE);
73 memcpy (datas->scpdurl, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE);
74 memcpy (datas->servicetype, datas->servicetype_tmp,
75 MINIUPNPC_URL_MAXSIZE);
76 }
77 }
78}
79
80/* Data handler :
81 * copy data depending on the current element name and state */
82void
83IGDdata (void *d, const char *data, int l)
84{
85 struct IGDdatas *datas = (struct IGDdatas *) d;
86 char *dstmember = 0;
87 /*printf("%2d %s : %.*s\n",
88 datas->level, datas->cureltname, l, data); */
89 if (!strcmp (datas->cureltname, "URLBase"))
90 dstmember = datas->urlbase;
91 else if (!strcmp (datas->cureltname, "serviceType"))
92 dstmember = datas->servicetype_tmp;
93 else if (!strcmp (datas->cureltname, "controlURL"))
94 dstmember = datas->controlurl_tmp;
95 else if (!strcmp (datas->cureltname, "eventSubURL"))
96 dstmember = datas->eventsuburl_tmp;
97 else if (!strcmp (datas->cureltname, "SCPDURL"))
98 dstmember = datas->scpdurl_tmp;
99/* else if( !strcmp(datas->cureltname, "deviceType") )
100 dstmember = datas->devicetype_tmp;*/
101 if (dstmember)
102 {
103 if (l >= MINIUPNPC_URL_MAXSIZE)
104 l = MINIUPNPC_URL_MAXSIZE - 1;
105 memcpy (dstmember, data, l);
106 dstmember[l] = '\0';
107 }
108}
109
110void
111printIGD (struct IGDdatas *d)
112{
113 printf ("urlbase = %s\n", d->urlbase);
114 printf ("WAN Device (Common interface config) :\n");
115 /*printf(" deviceType = %s\n", d->devicetype_CIF); */
116 printf (" serviceType = %s\n", d->servicetype_CIF);
117 printf (" controlURL = %s\n", d->controlurl_CIF);
118 printf (" eventSubURL = %s\n", d->eventsuburl_CIF);
119 printf (" SCPDURL = %s\n", d->scpdurl_CIF);
120 printf ("WAN Connection Device (IP or PPP Connection):\n");
121 /*printf(" deviceType = %s\n", d->devicetype); */
122 printf (" servicetype = %s\n", d->servicetype);
123 printf (" controlURL = %s\n", d->controlurl);
124 printf (" eventSubURL = %s\n", d->eventsuburl);
125 printf (" SCPDURL = %s\n", d->scpdurl);
126}
diff --git a/src/nat/miniupnp/igd_desc_parse.h b/src/nat/miniupnp/igd_desc_parse.h
deleted file mode 100644
index 5e7e24b86..000000000
--- a/src/nat/miniupnp/igd_desc_parse.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/* $Id: igd_desc_parse.h,v 1.6 2008/04/23 11:51:07 nanard Exp $ */
2/* Project : miniupnp
3 * http://miniupnp.free.fr/
4 * Author : Thomas Bernard
5 * Copyright (c) 2005-2008 Thomas Bernard
6 * This software is subject to the conditions detailed in the
7 * LICENCE file provided in this distribution.
8 * */
9#ifndef __IGD_DESC_PARSE_H__
10#define __IGD_DESC_PARSE_H__
11
12/* Structure to store the result of the parsing of UPnP
13 * descriptions of Internet Gateway Devices */
14#define MINIUPNPC_URL_MAXSIZE (128)
15struct IGDdatas
16{
17 char cureltname[MINIUPNPC_URL_MAXSIZE];
18 char urlbase[MINIUPNPC_URL_MAXSIZE];
19 int level;
20 /*int state; */
21 /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
22 char controlurl_CIF[MINIUPNPC_URL_MAXSIZE];
23 char eventsuburl_CIF[MINIUPNPC_URL_MAXSIZE];
24 char scpdurl_CIF[MINIUPNPC_URL_MAXSIZE];
25 char servicetype_CIF[MINIUPNPC_URL_MAXSIZE];
26 /*char devicetype_CIF[MINIUPNPC_URL_MAXSIZE]; */
27 /* "urn:schemas-upnp-org:service:WANIPConnection:1"
28 * "urn:schemas-upnp-org:service:WANPPPConnection:1" */
29 char controlurl[MINIUPNPC_URL_MAXSIZE];
30 char eventsuburl[MINIUPNPC_URL_MAXSIZE];
31 char scpdurl[MINIUPNPC_URL_MAXSIZE];
32 char servicetype[MINIUPNPC_URL_MAXSIZE];
33 /*char devicetype[MINIUPNPC_URL_MAXSIZE]; */
34 /* tmp */
35 char controlurl_tmp[MINIUPNPC_URL_MAXSIZE];
36 char eventsuburl_tmp[MINIUPNPC_URL_MAXSIZE];
37 char scpdurl_tmp[MINIUPNPC_URL_MAXSIZE];
38 char servicetype_tmp[MINIUPNPC_URL_MAXSIZE];
39 /*char devicetype_tmp[MINIUPNPC_URL_MAXSIZE]; */
40};
41
42void IGDstartelt (void *, const char *, int);
43void IGDendelt (void *, const char *, int);
44void IGDdata (void *, const char *, int);
45void printIGD (struct IGDdatas *);
46
47#endif
diff --git a/src/nat/miniupnp/minisoap.c b/src/nat/miniupnp/minisoap.c
deleted file mode 100644
index a020f9a64..000000000
--- a/src/nat/miniupnp/minisoap.c
+++ /dev/null
@@ -1,106 +0,0 @@
1/* $Id: minisoap.c,v 1.16 2008/10/11 16:39:29 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 *
8 * Minimal SOAP implementation for UPnP protocol.
9 */
10#include <stdio.h>
11#include <string.h>
12#ifdef WIN32
13#include <io.h>
14#include <winsock2.h>
15#define snprintf _snprintf
16#else
17#include <unistd.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20#endif
21#include "minisoap.h"
22#include "miniupnpcstrings.h"
23
24/* only for malloc */
25#include <stdlib.h>
26
27#ifdef WIN32
28#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
29#else
30#define PRINT_SOCKET_ERROR(x) perror(x)
31#endif
32
33/* httpWrite sends the headers and the body to the socket
34 * and returns the number of bytes sent */
35static int
36httpWrite (int fd, const char *body, int bodysize,
37 const char *headers, int headerssize)
38{
39 int n = 0;
40 /*n = write(fd, headers, headerssize); */
41 /*if(bodysize>0)
42 n += write(fd, body, bodysize); */
43 /* Note : my old linksys router only took into account
44 * soap request that are sent into only one packet */
45 char *p;
46 /* TODO: AVOID MALLOC */
47 p = malloc (headerssize + bodysize);
48 if (!p)
49 return 0;
50 memcpy (p, headers, headerssize);
51 memcpy (p + headerssize, body, bodysize);
52 /*n = write(fd, p, headerssize+bodysize); */
53 n = send (fd, p, headerssize + bodysize, 0);
54 if (n < 0)
55 {
56 PRINT_SOCKET_ERROR ("send");
57 }
58 /* disable send on the socket */
59 /* draytek routers dont seems to like that... */
60#if 0
61#ifdef WIN32
62 if (shutdown (fd, SD_SEND) < 0)
63 {
64#else
65 if (shutdown (fd, SHUT_WR) < 0)
66 { /*SD_SEND */
67#endif
68 PRINT_SOCKET_ERROR ("shutdown");
69 }
70#endif
71 free (p);
72 return n;
73}
74
75/* self explanatory */
76int
77soapPostSubmit (int fd,
78 const char *url,
79 const char *host,
80 unsigned short port, const char *action, const char *body)
81{
82 int bodysize;
83 char headerbuf[512];
84 int headerssize;
85 char portstr[8];
86 bodysize = (int) strlen (body);
87 /* We are not using keep-alive HTTP connections.
88 * HTTP/1.1 needs the header Connection: close to do that.
89 * This is the default with HTTP/1.0 */
90 /* Connection: Close is normally there only in HTTP/1.1 but who knows */
91 portstr[0] = '\0';
92 if (port != 80)
93 snprintf (portstr, sizeof (portstr), ":%hu", port);
94 headerssize = snprintf (headerbuf, sizeof (headerbuf),
95 "POST %s HTTP/1.1\r\n"
96/* "POST %s HTTP/1.0\r\n"*/
97 "Host: %s%s\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "Content-Length: %d\r\n" "Content-Type: text/xml\r\n" "SOAPAction: \"%s\"\r\n" "Connection: Close\r\n" "Cache-Control: no-cache\r\n" /* ??? */
98 "Pragma: no-cache\r\n"
99 "\r\n", url, host, portstr, bodysize, action);
100#ifdef DEBUG
101 printf ("SOAP request : headersize=%d bodysize=%d\n",
102 headerssize, bodysize);
103 /*printf("%s", headerbuf); */
104#endif
105 return httpWrite (fd, body, bodysize, headerbuf, headerssize);
106}
diff --git a/src/nat/miniupnp/minisoap.h b/src/nat/miniupnp/minisoap.h
deleted file mode 100644
index 2505e4c20..000000000
--- a/src/nat/miniupnp/minisoap.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution. */
7#ifndef __MINISOAP_H__
8#define __MINISOAP_H__
9
10/*int httpWrite(int, const char *, int, const char *);*/
11int soapPostSubmit (int, const char *, const char *, unsigned short,
12 const char *, const char *);
13
14#endif
diff --git a/src/nat/miniupnp/minissdpc.c b/src/nat/miniupnp/minissdpc.c
deleted file mode 100644
index 3fe89ef94..000000000
--- a/src/nat/miniupnp/minissdpc.c
+++ /dev/null
@@ -1,111 +0,0 @@
1/* $Id: minissdpc.c,v 1.7 2008/12/18 17:45:48 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas BERNARD
4 * copyright (c) 2005-2008 Thomas Bernard
5 * This software is subjet to the conditions detailed in the
6 * provided LICENCE file. */
7/*#include <syslog.h>*/
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <sys/types.h>
13#ifdef WIN32
14#include <winsock2.h>
15#include <Ws2tcpip.h>
16#include <io.h>
17#else
18#include <sys/socket.h>
19#include <sys/un.h>
20#endif
21
22#include "minissdpc.h"
23#include "miniupnpc.h"
24
25#include "codelength.h"
26
27struct UPNPDev *
28getDevicesFromMiniSSDPD (const char *devtype, const char *socketpath)
29{
30 struct UPNPDev *tmp;
31 struct UPNPDev *devlist = NULL;
32 unsigned char buffer[2048];
33 ssize_t n;
34 unsigned char *p;
35 unsigned char *url;
36 unsigned int i;
37 unsigned int urlsize, stsize, usnsize, l;
38 int s;
39 struct sockaddr_un addr;
40
41 s = socket (AF_UNIX, SOCK_STREAM, 0);
42 if (s < 0)
43 {
44 /*syslog(LOG_ERR, "socket(unix): %m"); */
45 perror ("socket(unix)");
46 return NULL;
47 }
48 addr.sun_family = AF_UNIX;
49 strncpy (addr.sun_path, socketpath, sizeof (addr.sun_path));
50 if (connect (s, (struct sockaddr *) &addr, sizeof (struct sockaddr_un)) < 0)
51 {
52 /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath); */
53 close (s);
54 return NULL;
55 }
56 stsize = strlen (devtype);
57 buffer[0] = 1; /* request type 1 : request devices/services by type */
58 p = buffer + 1;
59 l = stsize;
60 CODELENGTH (l, p);
61 memcpy (p, devtype, stsize);
62 p += stsize;
63 if (write (s, buffer, p - buffer) < 0)
64 {
65 /*syslog(LOG_ERR, "write(): %m"); */
66 perror ("minissdpc.c: write()");
67 close (s);
68 return NULL;
69 }
70 n = read (s, buffer, sizeof (buffer));
71 if (n <= 0)
72 {
73 perror ("minissdpc.c: read()");
74 close (s);
75 return NULL;
76 }
77 p = buffer + 1;
78 for (i = 0; i < buffer[0]; i++)
79 {
80 if (p + 2 >= buffer + sizeof (buffer))
81 break;
82 DECODELENGTH (urlsize, p);
83 if (p + urlsize + 2 >= buffer + sizeof (buffer))
84 break;
85 url = p;
86 p += urlsize;
87 DECODELENGTH (stsize, p);
88 if (p + stsize + 2 >= buffer + sizeof (buffer))
89 break;
90 tmp =
91 (struct UPNPDev *) malloc (sizeof (struct UPNPDev) + urlsize +
92 stsize);
93 tmp->pNext = devlist;
94 tmp->descURL = tmp->buffer;
95 tmp->st = tmp->buffer + 1 + urlsize;
96 memcpy (tmp->buffer, url, urlsize);
97 tmp->buffer[urlsize] = '\0';
98 memcpy (tmp->buffer + urlsize + 1, p, stsize);
99 p += stsize;
100 tmp->buffer[urlsize + 1 + stsize] = '\0';
101 devlist = tmp;
102 /* added for compatibility with recent versions of MiniSSDPd
103 * >= 2007/12/19 */
104 DECODELENGTH (usnsize, p);
105 p += usnsize;
106 if (p > buffer + sizeof (buffer))
107 break;
108 }
109 close (s);
110 return devlist;
111}
diff --git a/src/nat/miniupnp/minissdpc.h b/src/nat/miniupnp/minissdpc.h
deleted file mode 100644
index f6c7db547..000000000
--- a/src/nat/miniupnp/minissdpc.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */
2/* Project: miniupnp
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * Author: Thomas Bernard
5 * Copyright (c) 2005-2007 Thomas Bernard
6 * This software is subjects to the conditions detailed
7 * in the LICENCE file provided within this distribution */
8#ifndef __MINISSDPC_H__
9#define __MINISSDPC_H__
10
11struct UPNPDev *getDevicesFromMiniSSDPD (const char *devtype,
12 const char *socketpath);
13
14#endif
diff --git a/src/nat/miniupnp/miniupnpc.c b/src/nat/miniupnp/miniupnpc.c
deleted file mode 100644
index 34bae0ad8..000000000
--- a/src/nat/miniupnp/miniupnpc.c
+++ /dev/null
@@ -1,901 +0,0 @@
1/* $Id: miniupnpc.c,v 1.57 2008/12/18 17:46:36 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas BERNARD
4 * copyright (c) 2005-2007 Thomas Bernard
5 * This software is subjet to the conditions detailed in the
6 * provided LICENCE file. */
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#ifdef WIN32
11/* Win32 Specific includes and defines */
12#include <winsock2.h>
13#include <Ws2tcpip.h>
14#include <Iphlpapi.h>
15#include <io.h>
16#define snprintf _snprintf
17#if defined(_MSC_VER) && (_MSC_VER >= 1400)
18#define strncasecmp _memicmp
19#else
20#define strncasecmp memicmp
21#endif
22#define MAXHOSTNAMELEN 64
23#else
24/* Standard POSIX includes */
25#include <unistd.h>
26#include <sys/socket.h>
27#include <sys/types.h>
28#include <sys/param.h>
29#include <netinet/in.h>
30#include <net/if.h>
31#include <arpa/inet.h>
32#include <poll.h>
33#include <netdb.h>
34#define closesocket close
35#endif
36#include "miniupnpc.h"
37#include "minissdpc.h"
38#include "miniwget.h"
39#include "minisoap.h"
40#include "minixml.h"
41#include "upnpcommands.h"
42
43#ifdef WIN32
44#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
45#else
46#define PRINT_SOCKET_ERROR(x) perror(x)
47#endif
48
49#define SOAPPREFIX "s"
50#define SERVICEPREFIX "u"
51#define SERVICEPREFIX2 'u'
52
53/* root description parsing */
54void
55parserootdesc (const char *buffer, int bufsize, struct IGDdatas *data)
56{
57 struct xmlparser parser;
58 /* xmlparser object */
59 parser.xmlstart = buffer;
60 parser.xmlsize = bufsize;
61 parser.data = data;
62 parser.starteltfunc = IGDstartelt;
63 parser.endeltfunc = IGDendelt;
64 parser.datafunc = IGDdata;
65 parser.attfunc = 0;
66 parsexml (&parser);
67#ifdef DEBUG
68 printIGD (data);
69#endif
70}
71
72/* Content-length: nnn */
73static int
74getcontentlenfromline (const char *p, int n)
75{
76 static const char contlenstr[] = "content-length";
77 const char *p2 = contlenstr;
78 int a = 0;
79 while (*p2)
80 {
81 if (n == 0)
82 return -1;
83 if (*p2 != *p && *p2 != (*p + 32))
84 return -1;
85 p++;
86 p2++;
87 n--;
88 }
89 if (n == 0)
90 return -1;
91 if (*p != ':')
92 return -1;
93 p++;
94 n--;
95 while (*p == ' ')
96 {
97 if (n == 0)
98 return -1;
99 p++;
100 n--;
101 }
102 while (*p >= '0' && *p <= '9')
103 {
104 if (n == 0)
105 return -1;
106 a = (a * 10) + (*p - '0');
107 p++;
108 n--;
109 }
110 return a;
111}
112
113static void
114getContentLengthAndHeaderLength (char *p, int n,
115 int *contentlen, int *headerlen)
116{
117 char *line;
118 int linelen;
119 int r;
120 line = p;
121 while (line < p + n)
122 {
123 linelen = 0;
124 while (line[linelen] != '\r' && line[linelen] != '\r')
125 {
126 if (line + linelen >= p + n)
127 return;
128 linelen++;
129 }
130 r = getcontentlenfromline (line, linelen);
131 if (r > 0)
132 *contentlen = r;
133 line = line + linelen + 2;
134 if (line[0] == '\r' && line[1] == '\n')
135 {
136 *headerlen = (line - p) + 2;
137 return;
138 }
139 }
140}
141
142/* simpleUPnPcommand :
143 * not so simple !
144 * return values :
145 * 0 - OK
146 * -1 - error */
147int
148simpleUPnPcommand (int s, const char *url, const char *service,
149 const char *action, struct UPNParg *args,
150 char *buffer, int *bufsize)
151{
152 struct sockaddr_in dest;
153 struct sockaddr_in6 dest6;
154 char hostname[MAXHOSTNAMELEN + 1];
155 unsigned short port = 0;
156 char *path;
157 char soapact[128];
158 char soapbody[2048];
159 char *buf;
160 int buffree;
161 int n;
162 int err;
163 int contentlen, headerlen; /* for the response */
164 snprintf (soapact, sizeof (soapact), "%s#%s", service, action);
165 if (args == NULL)
166 {
167 /*soapbodylen = */ snprintf (soapbody, sizeof (soapbody),
168 "<?xml version=\"1.0\"?>\r\n"
169 "<" SOAPPREFIX ":Envelope "
170 "xmlns:" SOAPPREFIX
171 "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
172 SOAPPREFIX
173 ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
174 "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX
175 ":%s xmlns:" SERVICEPREFIX "=\"%s\">" "</"
176 SERVICEPREFIX ":%s>" "</" SOAPPREFIX
177 ":Body></" SOAPPREFIX ":Envelope>" "\r\n",
178 action, service, action);
179 }
180 else
181 {
182 char *p;
183 const char *pe, *pv;
184 int soapbodylen;
185 soapbodylen = snprintf (soapbody, sizeof (soapbody),
186 "<?xml version=\"1.0\"?>\r\n"
187 "<" SOAPPREFIX ":Envelope "
188 "xmlns:" SOAPPREFIX
189 "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
190 SOAPPREFIX
191 ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
192 "<" SOAPPREFIX ":Body>" "<" SERVICEPREFIX
193 ":%s xmlns:" SERVICEPREFIX "=\"%s\">", action,
194 service);
195 p = soapbody + soapbodylen;
196 while (args->elt)
197 {
198 /* check that we are never overflowing the string... */
199 if (soapbody + sizeof (soapbody) <= p + 100)
200 {
201 /* we keep a margin of at least 100 bytes */
202 *bufsize = 0;
203 return -1;
204 }
205 *(p++) = '<';
206 pe = args->elt;
207 while (*pe)
208 *(p++) = *(pe++);
209 *(p++) = '>';
210 if ((pv = args->val))
211 {
212 while (*pv)
213 *(p++) = *(pv++);
214 }
215 *(p++) = '<';
216 *(p++) = '/';
217 pe = args->elt;
218 while (*pe)
219 *(p++) = *(pe++);
220 *(p++) = '>';
221 args++;
222 }
223 *(p++) = '<';
224 *(p++) = '/';
225 *(p++) = SERVICEPREFIX2;
226 *(p++) = ':';
227 pe = action;
228 while (*pe)
229 *(p++) = *(pe++);
230 strncpy (p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
231 soapbody + sizeof (soapbody) - p);
232 }
233 if (!parseURL (url, hostname, &port, &path))
234 return -1;
235
236 if (s < 0)
237 {
238 /* Test IPv4 address, else use IPv6 */
239 if (inet_pton (AF_INET, hostname, &dest.sin_addr) == 1)
240 {
241 memset (&dest, 0, sizeof (dest));
242 dest.sin_family = AF_INET;
243 dest.sin_port = htons (port);
244#ifdef HAVE_SOCKADDR_IN_SIN_LEN
245 dest.sin_len = sizeof (dest);
246#endif
247 if ((s = socket (PF_INET, SOCK_STREAM, 0)) < 0)
248 {
249 PRINT_SOCKET_ERROR ("socket");
250 *bufsize = 0;
251 return -1;
252 }
253 err = connect (s, (struct sockaddr *) &dest, sizeof (dest));
254 }
255 else if (inet_pton (AF_INET6, hostname, &dest6.sin6_addr) == 1)
256 {
257 memset (&dest6, 0, sizeof (dest6));
258 dest6.sin6_family = AF_INET6;
259 dest6.sin6_port = htons (port);
260#ifdef HAVE_SOCKADDR_IN_SIN_LEN
261 dest6.sin6_len = sizeof (dest6);
262#endif
263 if ((s = socket (PF_INET6, SOCK_STREAM, 0)) < 0)
264 {
265 PRINT_SOCKET_ERROR ("socket");
266 *bufsize = 0;
267 return -1;
268 }
269 err = connect (s, (struct sockaddr *) &dest6, sizeof (dest6));
270 }
271 else
272 {
273 PRINT_SOCKET_ERROR ("inet_pton");
274 if (s > 0)
275 closesocket (s);
276
277 *bufsize = 0;
278 return -1;
279 }
280
281 if (err < 0)
282 {
283 PRINT_SOCKET_ERROR ("connect");
284 closesocket (s);
285 *bufsize = 0;
286 return -1;
287 }
288 }
289 n = soapPostSubmit (s, path, hostname, port, soapact, soapbody);
290 if (n <= 0)
291 {
292#ifdef DEBUG
293 printf ("Error sending SOAP request\n");
294#endif
295 closesocket (s);
296 return -1;
297 }
298
299 contentlen = -1;
300 headerlen = -1;
301 buf = buffer;
302 buffree = *bufsize;
303 *bufsize = 0;
304 while ((n = ReceiveData (s, buf, buffree, 5000)) > 0)
305 {
306 buffree -= n;
307 buf += n;
308 *bufsize += n;
309 getContentLengthAndHeaderLength (buffer, *bufsize,
310 &contentlen, &headerlen);
311#ifdef DEBUG
312 printf ("received n=%dbytes bufsize=%d ContLen=%d HeadLen=%d\n",
313 n, *bufsize, contentlen, headerlen);
314#endif
315 /* break if we received everything */
316 if (contentlen > 0 && headerlen > 0
317 && *bufsize >= contentlen + headerlen)
318 break;
319 }
320
321 closesocket (s);
322 return 0;
323}
324
325/* parseMSEARCHReply()
326 * the last 4 arguments are filled during the parsing :
327 * - location/locationsize : "location:" field of the SSDP reply packet
328 * - st/stsize : "st:" field of the SSDP reply packet.
329 * The strings are NOT null terminated */
330static void
331parseMSEARCHReply (const char *reply, int size,
332 const char **location, int *locationsize,
333 const char **st, int *stsize)
334{
335 int a, b, i;
336 i = 0;
337 a = i; /* start of the line */
338 b = 0;
339 while (i < size)
340 {
341 switch (reply[i])
342 {
343 case ':':
344 if (b == 0)
345 {
346 b = i; /* end of the "header" */
347 /*for(j=a; j<b; j++)
348 {
349 putchar(reply[j]);
350 }
351 */
352 }
353 break;
354 case '\x0a':
355 case '\x0d':
356 if (b != 0)
357 {
358 /*for(j=b+1; j<i; j++)
359 {
360 putchar(reply[j]);
361 }
362 putchar('\n'); */
363 do
364 {
365 b++;
366 }
367 while (reply[b] == ' ');
368 if (0 == strncasecmp (reply + a, "location", 8))
369 {
370 *location = reply + b;
371 *locationsize = i - b;
372 }
373 else if (0 == strncasecmp (reply + a, "st", 2))
374 {
375 *st = reply + b;
376 *stsize = i - b;
377 }
378 b = 0;
379 }
380 a = i + 1;
381 break;
382 default:
383 break;
384 }
385 i++;
386 }
387}
388
389/* port upnp discover : SSDP protocol */
390#define PORT 1900
391#define XSTR(s) STR(s)
392#define STR(s) #s
393#define UPNP_MCAST_ADDR "239.255.255.250"
394#define UPNP_MCAST_ADDR6 "FF02:0:0:0:0:0:0:F"
395
396/* upnpDiscover() :
397 * return a chained list of all devices found or NULL if
398 * no devices was found.
399 * It is up to the caller to free the chained list
400 * delay is in millisecond (poll) */
401struct UPNPDev *
402upnpDiscover (int delay, const char *multicastif,
403 const struct sockaddr *addr,
404 const char *minissdpdsock, int sameport)
405{
406 struct UPNPDev *tmp;
407 struct UPNPDev *devlist = 0;
408 int opt = 1;
409 static const char MSearchMsgFmt[] =
410 "M-SEARCH * HTTP/1.1\r\n"
411 "HOST: " UPNP_MCAST_ADDR ":" XSTR (PORT) "\r\n"
412 "ST: %s\r\n" "MAN: \"ssdp:discover\"\r\n" "MX: 3\r\n" "\r\n";
413 static const char *const deviceList[] = {
414 "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
415 "urn:schemas-upnp-org:service:WANIPConnection:1",
416 "urn:schemas-upnp-org:service:WANPPPConnection:1",
417 "upnp:rootdevice",
418 0
419 };
420 int deviceIndex = 0;
421 char bufr[1536]; /* reception and emission buffer */
422 int sudp;
423 int n;
424 int domain = PF_INET;
425 int if_index;
426 struct in6_addr any_addr = IN6ADDR_ANY_INIT;
427 struct sockaddr_in sockudp_r, sockudp_w;
428 struct sockaddr_in6 sockudp6_r, sockudp6_w;
429
430#ifndef WIN32
431 /* first try to get infos from minissdpd ! */
432 if (!minissdpdsock)
433 minissdpdsock = "/var/run/minissdpd.sock";
434 while (!devlist && deviceList[deviceIndex])
435 {
436 devlist = getDevicesFromMiniSSDPD (deviceList[deviceIndex],
437 minissdpdsock);
438 /* We return what we have found if it was not only a rootdevice */
439 if (devlist && !strstr (deviceList[deviceIndex], "rootdevice"))
440 return devlist;
441 deviceIndex++;
442 }
443 deviceIndex = 0;
444#endif
445
446 if (addr && addr->sa_family == AF_INET)
447 domain = PF_INET;
448 else if (addr && addr->sa_family == AF_INET6)
449 domain = PF_INET6;
450 else if (addr)
451 return NULL;
452
453 /* fallback to direct discovery */
454#ifdef WIN32
455 sudp = socket (domain, SOCK_DGRAM, IPPROTO_UDP);
456#else
457 sudp = socket (domain, SOCK_DGRAM, 0);
458#endif
459 if (sudp < 0)
460 {
461 PRINT_SOCKET_ERROR ("socket");
462 return NULL;
463 }
464
465 if (domain == PF_INET)
466 {
467 /* receive */
468 memset (&sockudp_r, 0, sizeof (struct sockaddr_in));
469 sockudp_r.sin_family = AF_INET;
470#ifdef HAVE_SOCKADDR_IN_SIN_LEN
471 sockudp_r.sin_len = sizeof (struct sockaddr_in);
472#endif
473 if (sameport)
474 sockudp_r.sin_port = htons (PORT);
475 sockudp_r.sin_addr.s_addr = INADDR_ANY;
476 /* send */
477 memset (&sockudp_w, 0, sizeof (struct sockaddr_in));
478 sockudp_w.sin_family = AF_INET;
479 sockudp_w.sin_port = htons (PORT);
480 sockudp_w.sin_addr.s_addr = inet_addr (UPNP_MCAST_ADDR);
481#ifdef HAVE_SOCKADDR_IN_SIN_LEN
482 sockudp_w.sin_len = sizeof (struct sockaddr_in);
483#endif
484 }
485 else
486 {
487 /* receive */
488 memcpy (&sockudp6_r, addr, sizeof (struct sockaddr_in6));
489 if (sameport)
490 sockudp6_r.sin6_port = htons (PORT);
491 else
492 sockudp6_r.sin6_port = 0;
493 sockudp6_r.sin6_addr = any_addr;
494#ifdef HAVE_SOCKADDR_IN_SIN_LEN
495 sockudp6_r.sin6_len = sizeof (struct sockaddr_in6);
496#endif
497 /* send */
498 memset (&sockudp6_w, 0, sizeof (struct sockaddr_in6));
499 sockudp6_w.sin6_family = AF_INET6;
500 sockudp6_w.sin6_port = htons (PORT);
501 if (inet_pton (AF_INET6, UPNP_MCAST_ADDR6, &sockudp6_w.sin6_addr) != 1)
502 {
503 PRINT_SOCKET_ERROR ("inet_pton");
504 return NULL;
505 }
506#ifdef HAVE_SOCKADDR_IN_SIN_LEN
507 sockudp6_w.sin6_len = sizeof (struct sockaddr_in6);
508#endif
509 }
510
511#ifdef WIN32
512 if (setsockopt
513 (sudp, SOL_SOCKET, SO_REUSEADDR, (const char *) &opt, sizeof (opt)) < 0)
514#else
515 if (setsockopt (sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
516#endif
517 {
518 PRINT_SOCKET_ERROR ("setsockopt");
519 return NULL;
520 }
521
522 if (addr)
523 {
524 if (domain == PF_INET)
525 {
526 sockudp_r.sin_addr.s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
527 if (setsockopt
528 (sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *) &sockudp_r.sin_addr,
529 sizeof (struct in_addr)) < 0)
530 {
531 PRINT_SOCKET_ERROR ("setsockopt");
532 }
533
534 /* Bind to receive response before sending packet */
535 if (bind (sudp, (struct sockaddr *) &sockudp_r, sizeof (struct sockaddr_in))
536 != 0)
537 {
538 PRINT_SOCKET_ERROR ("bind");
539 closesocket (sudp);
540 return NULL;
541 }
542 }
543 else
544 {
545 if (multicastif)
546 {
547 if_index = if_nametoindex (multicastif);
548 if (!if_index)
549 PRINT_SOCKET_ERROR ("if_nametoindex");
550
551 if (setsockopt
552 (sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof (if_index)) < 0)
553 {
554 PRINT_SOCKET_ERROR ("setsockopt");
555 }
556 }
557
558 /* Bind to receive response before sending packet */
559 memcpy (&sockudp6_r.sin6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
560 sizeof (sockudp6_r.sin6_addr));
561 if (bind (sudp, (struct sockaddr *) &sockudp6_r, sizeof (struct sockaddr_in6))
562 != 0)
563 {
564 PRINT_SOCKET_ERROR ("bind");
565 closesocket (sudp);
566 return NULL;
567 }
568 }
569 }
570
571 /* receiving SSDP response packet */
572 for (n = 0;;)
573 {
574 if (n == 0)
575 {
576 /* sending the SSDP M-SEARCH packet */
577 n = snprintf (bufr, sizeof (bufr),
578 MSearchMsgFmt, deviceList[deviceIndex++]);
579 /*printf("Sending %s", bufr); */
580 if (domain == PF_INET)
581 n = sendto (sudp, bufr, n, 0,
582 (struct sockaddr *) &sockudp_w,
583 sizeof (struct sockaddr_in));
584 else
585 n = sendto (sudp, bufr, n, 0,
586 (struct sockaddr *) &sockudp6_w,
587 sizeof (struct sockaddr_in6));
588
589 if (n < 0)
590 {
591 PRINT_SOCKET_ERROR ("sendto");
592 closesocket (sudp);
593 return devlist;
594 }
595 }
596 /* Waiting for SSDP REPLY packet to M-SEARCH */
597 n = ReceiveData (sudp, bufr, sizeof (bufr), delay);
598
599 if (n < 0)
600 {
601 /* error */
602 closesocket (sudp);
603 return devlist;
604 }
605 else if (n == 0)
606 {
607 /* no data or Time Out */
608 if (devlist || (deviceList[deviceIndex] == 0))
609 {
610 /* no more device type to look for... */
611 closesocket (sudp);
612 return devlist;
613 }
614 }
615 else
616 {
617 const char *descURL = NULL;
618 int urlsize = 0;
619 const char *st = NULL;
620 int stsize = 0;
621 /*printf("%d byte(s) :\n%s\n", n, bufr); *//* affichage du message */
622 parseMSEARCHReply (bufr, n, &descURL, &urlsize, &st, &stsize);
623 if (st && descURL)
624 {
625 /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
626 stsize, st, urlsize, descURL); */
627 tmp =
628 (struct UPNPDev *) malloc (sizeof (struct UPNPDev) + urlsize +
629 stsize);
630 tmp->pNext = devlist;
631 tmp->descURL = tmp->buffer;
632 tmp->st = tmp->buffer + 1 + urlsize;
633 memcpy (tmp->buffer, descURL, urlsize);
634 tmp->buffer[urlsize] = '\0';
635 memcpy (tmp->buffer + urlsize + 1, st, stsize);
636 tmp->buffer[urlsize + 1 + stsize] = '\0';
637 devlist = tmp;
638 }
639 }
640 }
641}
642
643/* freeUPNPDevlist() should be used to
644 * free the chained list returned by upnpDiscover() */
645void
646freeUPNPDevlist (struct UPNPDev *devlist)
647{
648 struct UPNPDev *next;
649 while (devlist)
650 {
651 next = devlist->pNext;
652 free (devlist);
653 devlist = next;
654 }
655}
656
657static void
658url_cpy_or_cat (char *dst, const char *src, int n)
659{
660 if ((src[0] == 'h')
661 && (src[1] == 't')
662 && (src[2] == 't')
663 && (src[3] == 'p')
664 && (src[4] == ':') && (src[5] == '/') && (src[6] == '/'))
665 {
666 strncpy (dst, src, n);
667 }
668 else
669 {
670 int l = strlen (dst);
671 if (src[0] != '/')
672 dst[l++] = '/';
673 if (l <= n)
674 strncpy (dst + l, src, n - l);
675 }
676}
677
678/* Prepare the Urls for usage...
679 */
680void
681GetUPNPUrls (struct UPNPUrls *urls, struct IGDdatas *data,
682 const char *descURL)
683{
684 char *p;
685 int n1, n2, n3;
686 n1 = strlen (data->urlbase);
687 if (n1 == 0)
688 n1 = strlen (descURL);
689 n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */
690 n2 = n1;
691 n3 = n1;
692 n1 += strlen (data->scpdurl);
693 n2 += strlen (data->controlurl);
694 n3 += strlen (data->controlurl_CIF);
695
696 urls->ipcondescURL = (char *) malloc (n1);
697 urls->controlURL = (char *) malloc (n2);
698 urls->controlURL_CIF = (char *) malloc (n3);
699 /* maintenant on chope la desc du WANIPConnection */
700 if (data->urlbase[0] != '\0')
701 strncpy (urls->ipcondescURL, data->urlbase, n1);
702 else
703 strncpy (urls->ipcondescURL, descURL, n1);
704 p = strchr (urls->ipcondescURL + 7, '/');
705 if (p)
706 p[0] = '\0';
707 strncpy (urls->controlURL, urls->ipcondescURL, n2);
708 strncpy (urls->controlURL_CIF, urls->ipcondescURL, n3);
709
710 url_cpy_or_cat (urls->ipcondescURL, data->scpdurl, n1);
711
712 url_cpy_or_cat (urls->controlURL, data->controlurl, n2);
713
714 url_cpy_or_cat (urls->controlURL_CIF, data->controlurl_CIF, n3);
715
716#ifdef DEBUG
717 printf ("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL,
718 strlen (urls->ipcondescURL), n1);
719 printf ("urls->controlURL='%s' %d n2=%d\n", urls->controlURL,
720 strlen (urls->controlURL), n2);
721 printf ("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF,
722 strlen (urls->controlURL_CIF), n3);
723#endif
724}
725
726void
727FreeUPNPUrls (struct UPNPUrls *urls)
728{
729 if (!urls)
730 return;
731 free (urls->controlURL);
732 urls->controlURL = 0;
733 free (urls->ipcondescURL);
734 urls->ipcondescURL = 0;
735 free (urls->controlURL_CIF);
736 urls->controlURL_CIF = 0;
737}
738
739
740int
741ReceiveData (int socket, char *data, int length, int timeout)
742{
743 int n;
744#ifndef WIN32
745 struct pollfd fds[1]; /* for the poll */
746 fds[0].fd = socket;
747 fds[0].events = POLLIN;
748 n = poll (fds, 1, timeout);
749 if (n < 0)
750 {
751 PRINT_SOCKET_ERROR ("poll");
752 return -1;
753 }
754 else if (n == 0)
755 {
756 return 0;
757 }
758#else
759 fd_set socketSet;
760 TIMEVAL timeval;
761 FD_ZERO (&socketSet);
762 FD_SET (socket, &socketSet);
763 timeval.tv_sec = timeout / 1000;
764 timeval.tv_usec = (timeout % 1000) * 1000;
765 /*n = select(0, &socketSet, NULL, NULL, &timeval); */
766 n = select (FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
767 if (n < 0)
768 {
769 PRINT_SOCKET_ERROR ("select");
770 return -1;
771 }
772 else if (n == 0)
773 {
774 return 0;
775 }
776#endif
777 n = recv (socket, data, length, 0);
778 if (n < 0)
779 {
780 PRINT_SOCKET_ERROR ("recv");
781 }
782 return n;
783}
784
785int
786UPNPIGD_IsConnected (struct UPNPUrls *urls, struct IGDdatas *data)
787{
788 char status[64];
789 unsigned int uptime;
790 status[0] = '\0';
791 UPNP_GetStatusInfo (urls->controlURL, data->servicetype,
792 status, &uptime, NULL);
793 if (0 == strcmp ("Connected", status))
794 {
795 return 1;
796 }
797 else
798 return 0;
799}
800
801
802/* UPNP_GetValidIGD() :
803 * return values :
804 * 0 = NO IGD found
805 * 1 = A valid connected IGD has been found
806 * 2 = A valid IGD has been found but it reported as
807 * not connected
808 * 3 = an UPnP device has been found but was not recognized as an IGD
809 *
810 * In any non zero return case, the urls and data structures
811 * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
812 * free allocated memory.
813 */
814int
815UPNP_GetValidIGD (struct UPNPDev *devlist,
816 struct UPNPUrls *urls,
817 struct IGDdatas *data, char *lanaddr, int lanaddrlen)
818{
819 char *descXML;
820 int descXMLsize = 0;
821 struct UPNPDev *dev;
822 int ndev = 0;
823 int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
824 if (!devlist)
825 {
826#ifdef DEBUG
827 printf ("Empty devlist\n");
828#endif
829 return 0;
830 }
831 for (state = 1; state <= 3; state++)
832 {
833 for (dev = devlist; dev; dev = dev->pNext)
834 {
835 /* we should choose an internet gateway device.
836 * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
837 descXML = miniwget_getaddr (dev->descURL, &descXMLsize,
838 lanaddr, lanaddrlen);
839 if (descXML)
840 {
841 ndev++;
842 memset (data, 0, sizeof (struct IGDdatas));
843 memset (urls, 0, sizeof (struct UPNPUrls));
844 parserootdesc (descXML, descXMLsize, data);
845 free (descXML);
846 descXML = NULL;
847 if (0 == strcmp (data->servicetype_CIF,
848 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
849 || state >= 3)
850 {
851 GetUPNPUrls (urls, data, dev->descURL);
852
853#ifdef DEBUG
854 printf ("UPNPIGD_IsConnected(%s) = %d\n",
855 urls->controlURL, UPNPIGD_IsConnected (urls, data));
856#endif
857 if ((state >= 2) || UPNPIGD_IsConnected (urls, data))
858 return state;
859 FreeUPNPUrls (urls);
860 }
861 memset (data, 0, sizeof (struct IGDdatas));
862 }
863#ifdef DEBUG
864 else
865 {
866 printf ("error getting XML description %s\n", dev->descURL);
867 }
868#endif
869 }
870 }
871 return 0;
872}
873
874/* UPNP_GetIGDFromUrl()
875 * Used when skipping the discovery process.
876 * return value :
877 * 0 - Not ok
878 * 1 - OK */
879int
880UPNP_GetIGDFromUrl (const char *rootdescurl,
881 struct UPNPUrls *urls,
882 struct IGDdatas *data, char *lanaddr, int lanaddrlen)
883{
884 char *descXML;
885 int descXMLsize = 0;
886 descXML = miniwget_getaddr (rootdescurl, &descXMLsize, lanaddr, lanaddrlen);
887 if (descXML)
888 {
889 memset (data, 0, sizeof (struct IGDdatas));
890 memset (urls, 0, sizeof (struct UPNPUrls));
891 parserootdesc (descXML, descXMLsize, data);
892 free (descXML);
893 descXML = NULL;
894 GetUPNPUrls (urls, data, rootdescurl);
895 return 1;
896 }
897 else
898 {
899 return 0;
900 }
901}
diff --git a/src/nat/miniupnp/miniupnpc.h b/src/nat/miniupnp/miniupnpc.h
deleted file mode 100644
index 8aa047b64..000000000
--- a/src/nat/miniupnp/miniupnpc.h
+++ /dev/null
@@ -1,120 +0,0 @@
1/* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */
2/* Project: miniupnp
3 * http://miniupnp.free.fr/
4 * Author: Thomas Bernard
5 * Copyright (c) 2005-2006 Thomas Bernard
6 * This software is subjects to the conditions detailed
7 * in the LICENCE file provided within this distribution */
8#ifndef __MINIUPNPC_H__
9#define __MINIUPNPC_H__
10
11#include "declspec.h"
12#include "igd_desc_parse.h"
13
14#ifdef WIN32
15#include <winsock2.h>
16#else
17#include <sys/socket.h>
18#endif
19
20#ifdef __cplusplus
21extern "C"
22{
23#endif
24
25/* Structures definitions : */
26 struct UPNParg
27 {
28 const char *elt;
29 const char *val;
30 };
31
32 int simpleUPnPcommand (int s, const char *, const char *,
33 const char *, struct UPNParg *, char *, int *);
34
35 struct UPNPDev
36 {
37 struct UPNPDev *pNext;
38 char *descURL;
39 char *st;
40 char buffer[2];
41 };
42
43/* upnpDiscover()
44 * discover UPnP devices on the network.
45 * The discovered devices are returned as a chained list.
46 * It is up to the caller to free the list with freeUPNPDevlist().
47 * delay (in millisecond) is the maximum time for waiting any device
48 * response.
49 * If available, device list will be obtained from MiniSSDPd.
50 * Default path for minissdpd socket will be used if minissdpdsock argument
51 * is NULL.
52 * If multicastif is not NULL, it will be used instead of the default
53 * multicast interface for sending SSDP discover packets.
54 * If sameport is not null, SSDP packets will be sent from the source port
55 * 1900 (same as destination port) otherwise system assign a source port. */
56 LIBSPEC struct UPNPDev *upnpDiscover (int delay, const char *multicastif, const struct sockaddr *addr,
57 const char *minissdpdsock, int sameport);
58/* freeUPNPDevlist()
59 * free list returned by upnpDiscover() */
60 LIBSPEC void freeUPNPDevlist (struct UPNPDev *devlist);
61
62/* parserootdesc() :
63 * parse root XML description of a UPnP device and fill the IGDdatas
64 * structure. */
65 LIBSPEC void parserootdesc (const char *, int, struct IGDdatas *);
66
67/* structure used to get fast access to urls
68 * controlURL: controlURL of the WANIPConnection
69 * ipcondescURL: url of the description of the WANIPConnection
70 * controlURL_CIF: controlURL of the WANCommonInterfaceConfig
71 */
72 struct UPNPUrls
73 {
74 char *controlURL;
75 char *ipcondescURL;
76 char *controlURL_CIF;
77 };
78
79/* UPNP_GetValidIGD() :
80 * return values :
81 * 0 = NO IGD found
82 * 1 = A valid connected IGD has been found
83 * 2 = A valid IGD has been found but it reported as
84 * not connected
85 * 3 = an UPnP device has been found but was not recognized as an IGD
86 *
87 * In any non zero return case, the urls and data structures
88 * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
89 * free allocated memory.
90 */
91 LIBSPEC int
92 UPNP_GetValidIGD (struct UPNPDev *devlist,
93 struct UPNPUrls *urls,
94 struct IGDdatas *data, char *lanaddr, int lanaddrlen);
95
96/* UPNP_GetIGDFromUrl()
97 * Used when skipping the discovery process.
98 * return value :
99 * 0 - Not ok
100 * 1 - OK */
101 LIBSPEC int
102 UPNP_GetIGDFromUrl (const char *rootdescurl,
103 struct UPNPUrls *urls,
104 struct IGDdatas *data, char *lanaddr, int lanaddrlen);
105
106 LIBSPEC void GetUPNPUrls (struct UPNPUrls *, struct IGDdatas *,
107 const char *);
108
109 LIBSPEC void FreeUPNPUrls (struct UPNPUrls *);
110
111/* Reads data from the specified socket.
112 * Returns the number of bytes read if successful, zero if no bytes were
113 * read or if we timed out. Returns negative if there was an error. */
114 int ReceiveData (int socket, char *data, int length, int timeout);
115
116#ifdef __cplusplus
117}
118#endif
119
120#endif
diff --git a/src/nat/miniupnp/miniupnpcstrings.h b/src/nat/miniupnp/miniupnpcstrings.h
deleted file mode 100644
index 3245e1f69..000000000
--- a/src/nat/miniupnp/miniupnpcstrings.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/* $Id: miniupnpcstrings.h,v 1.2 2008/10/14 17:39:04 nanard Exp $ */
2/* Project: miniupnp
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * Author: Thomas Bernard
5 * Copyright (c) 2005-2008 Thomas Bernard
6 * This software is subjects to the conditions detailed
7 * in the LICENCE file provided within this distribution */
8#ifndef __MINIUPNPCSTRINGS_H__
9#define __MINIUPNPCSTRINGS_H__
10
11#define OS_STRING "Debian/4.0"
12#define MINIUPNPC_VERSION_STRING "1.2"
13
14#endif
diff --git a/src/nat/miniupnp/miniwget.c b/src/nat/miniupnp/miniwget.c
deleted file mode 100644
index 38d5610d8..000000000
--- a/src/nat/miniupnp/miniwget.c
+++ /dev/null
@@ -1,224 +0,0 @@
1/* $Id: miniwget.c,v 1.22 2009/02/28 10:36:35 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include "miniupnpc.h"
12#ifdef WIN32
13#include <winsock2.h>
14#include <io.h>
15#define MAXHOSTNAMELEN 64
16#define MIN(x,y) (((x)<(y))?(x):(y))
17#define snprintf _snprintf
18#define herror
19#define socklen_t int
20#else
21#include <unistd.h>
22#include <sys/param.h>
23#include <sys/socket.h>
24#include <netdb.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#define closesocket close
28#endif
29#if defined(__sun) || defined(sun)
30#define MIN(x,y) (((x)<(y))?(x):(y))
31#endif
32
33#include "miniupnpcstrings.h"
34
35/* miniwget2() :
36 * */
37static void *
38miniwget2 (const char *url, const char *host,
39 unsigned short port, const char *path,
40 int *size, char *addr_str, int addr_str_len)
41{
42 char buf[2048];
43 int s;
44 struct sockaddr_in dest;
45 struct hostent *hp;
46 *size = 0;
47 hp = gethostbyname (host);
48 if (hp == NULL)
49 {
50 herror (host);
51 return NULL;
52 }
53 /* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */
54 memcpy (&dest.sin_addr, hp->h_addr, sizeof (dest.sin_addr));
55 memset (dest.sin_zero, 0, sizeof (dest.sin_zero));
56 s = socket (PF_INET, SOCK_STREAM, 0);
57 if (s < 0)
58 {
59 perror ("socket");
60 return NULL;
61 }
62 dest.sin_family = AF_INET;
63 dest.sin_port = htons (port);
64 if (connect (s, (struct sockaddr *) &dest, sizeof (struct sockaddr_in)) < 0)
65 {
66 perror ("connect");
67 closesocket (s);
68 return NULL;
69 }
70
71 /* get address for caller ! */
72 if (addr_str)
73 {
74 struct sockaddr_in saddr;
75 socklen_t len;
76
77 len = sizeof (saddr);
78 getsockname (s, (struct sockaddr *) &saddr, &len);
79#ifndef WIN32
80 inet_ntop (AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
81#else
82 /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
83 * But his function make a string with the port : nn.nn.nn.nn:port */
84/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
85 NULL, addr_str, (DWORD *)&addr_str_len))
86 {
87 printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
88 }*/
89 strncpy (addr_str, inet_ntoa (saddr.sin_addr), addr_str_len);
90#endif
91#ifdef DEBUG
92 printf ("address miniwget : %s\n", addr_str);
93#endif
94 }
95
96 snprintf (buf, sizeof (buf),
97 "GET %s HTTP/1.1\r\n"
98 "Host: %s:%d\r\n"
99 "Connection: Close\r\n"
100 "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/"
101 MINIUPNPC_VERSION_STRING "\r\n" "\r\n", path, host, port);
102 /*write(s, buf, strlen(buf)); */
103 send (s, buf, strlen (buf), 0);
104 {
105 int n, headers = 1;
106 char *respbuffer = NULL;
107 int allreadyread = 0;
108 /*while((n = recv(s, buf, 2048, 0)) > 0) */
109 while ((n = ReceiveData (s, buf, 2048, 5000)) > 0)
110 {
111 if (headers)
112 {
113 int i = 0;
114 while (i < n - 3)
115 {
116 if (buf[i] == '\r' && buf[i + 1] == '\n'
117 && buf[i + 2] == '\r' && buf[i + 3] == '\n')
118 {
119 headers = 0; /* end */
120 if (i < n - 4)
121 {
122 respbuffer = (char *) realloc ((void *) respbuffer,
123 allreadyread + (n - i -
124 4));
125 memcpy (respbuffer + allreadyread, buf + i + 4,
126 n - i - 4);
127 allreadyread += (n - i - 4);
128 }
129 break;
130 }
131 i++;
132 }
133 }
134 else
135 {
136 respbuffer = (char *) realloc ((void *) respbuffer,
137 allreadyread + n);
138 memcpy (respbuffer + allreadyread, buf, n);
139 allreadyread += n;
140 }
141 }
142 *size = allreadyread;
143#ifdef DEBUG
144 printf ("%d bytes read\n", *size);
145#endif
146 closesocket (s);
147 return respbuffer;
148 }
149}
150
151/* parseURL()
152 * arguments :
153 * url : source string not modified
154 * hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
155 * port : port (destination)
156 * path : pointer to the path part of the URL
157 *
158 * Return values :
159 * 0 - Failure
160 * 1 - Success */
161int
162parseURL (const char *url, char *hostname, unsigned short *port, char **path)
163{
164 char *p1, *p2, *p3;
165 p1 = strstr (url, "://");
166 if (!p1)
167 return 0;
168 p1 += 3;
169 if ((url[0] != 'h') || (url[1] != 't')
170 || (url[2] != 't') || (url[3] != 'p'))
171 return 0;
172 p2 = strchr (p1, ':');
173 p3 = strchr (p1, '/');
174 if (!p3)
175 return 0;
176 memset (hostname, 0, MAXHOSTNAMELEN + 1);
177 if (!p2 || (p2 > p3))
178 {
179 strncpy (hostname, p1, MIN (MAXHOSTNAMELEN, (int) (p3 - p1)));
180 *port = 80;
181 }
182 else
183 {
184 strncpy (hostname, p1, MIN (MAXHOSTNAMELEN, (int) (p2 - p1)));
185 *port = 0;
186 p2++;
187 while ((*p2 >= '0') && (*p2 <= '9'))
188 {
189 *port *= 10;
190 *port += (unsigned short) (*p2 - '0');
191 p2++;
192 }
193 }
194 *path = p3;
195 return 1;
196}
197
198void *
199miniwget (const char *url, int *size)
200{
201 unsigned short port;
202 char *path;
203 /* protocol://host:port/chemin */
204 char hostname[MAXHOSTNAMELEN + 1];
205 *size = 0;
206 if (!parseURL (url, hostname, &port, &path))
207 return NULL;
208 return miniwget2 (url, hostname, port, path, size, 0, 0);
209}
210
211void *
212miniwget_getaddr (const char *url, int *size, char *addr, int addrlen)
213{
214 unsigned short port;
215 char *path;
216 /* protocol://host:port/chemin */
217 char hostname[MAXHOSTNAMELEN + 1];
218 *size = 0;
219 if (addr)
220 addr[0] = '\0';
221 if (!parseURL (url, hostname, &port, &path))
222 return NULL;
223 return miniwget2 (url, hostname, port, path, size, addr, addrlen);
224}
diff --git a/src/nat/miniupnp/miniwget.h b/src/nat/miniupnp/miniwget.h
deleted file mode 100644
index 04e91df64..000000000
--- a/src/nat/miniupnp/miniwget.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#ifndef __MINIWGET_H__
9#define __MINIWGET_H__
10
11#include "declspec.h"
12
13#ifdef __cplusplus
14extern "C"
15{
16#endif
17
18 LIBSPEC void *miniwget (const char *, int *);
19
20 LIBSPEC void *miniwget_getaddr (const char *, int *, char *, int);
21
22 int parseURL (const char *, char *, unsigned short *, char **);
23
24#ifdef __cplusplus
25}
26#endif
27
28#endif
diff --git a/src/nat/miniupnp/minixml.c b/src/nat/miniupnp/minixml.c
deleted file mode 100644
index 094118cfa..000000000
--- a/src/nat/miniupnp/minixml.c
+++ /dev/null
@@ -1,200 +0,0 @@
1/* $Id: minixml.c,v 1.6 2007/05/15 18:14:08 nanard Exp $ */
2/* minixml.c : the minimum size a xml parser can be ! */
3/* Project : miniupnp
4 * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
5 * Author : Thomas Bernard
6
7Copyright (c) 2005-2007, Thomas BERNARD
8All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 * Redistributions of source code must retain the above copyright notice,
14 this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
18 * The name of the author may not be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE.
32*/
33#include "minixml.h"
34
35/* parseatt : used to parse the argument list
36 * return 0 (false) in case of success and -1 (true) if the end
37 * of the xmlbuffer is reached. */
38int
39parseatt (struct xmlparser *p)
40{
41 const char *attname;
42 int attnamelen;
43 const char *attvalue;
44 int attvaluelen;
45 while (p->xml < p->xmlend)
46 {
47 if (*p->xml == '/' || *p->xml == '>')
48 return 0;
49 if (!IS_WHITE_SPACE (*p->xml))
50 {
51 char sep;
52 attname = p->xml;
53 attnamelen = 0;
54 while (*p->xml != '=' && !IS_WHITE_SPACE (*p->xml))
55 {
56 attnamelen++;
57 p->xml++;
58 if (p->xml >= p->xmlend)
59 return -1;
60 }
61 while (*(p->xml++) != '=')
62 {
63 if (p->xml >= p->xmlend)
64 return -1;
65 }
66 while (IS_WHITE_SPACE (*p->xml))
67 {
68 p->xml++;
69 if (p->xml >= p->xmlend)
70 return -1;
71 }
72 sep = *p->xml;
73 if (sep == '\'' || sep == '\"')
74 {
75 p->xml++;
76 if (p->xml >= p->xmlend)
77 return -1;
78 attvalue = p->xml;
79 attvaluelen = 0;
80 while (*p->xml != sep)
81 {
82 attvaluelen++;
83 p->xml++;
84 if (p->xml >= p->xmlend)
85 return -1;
86 }
87 }
88 else
89 {
90 attvalue = p->xml;
91 attvaluelen = 0;
92 while (!IS_WHITE_SPACE (*p->xml)
93 && *p->xml != '>' && *p->xml != '/')
94 {
95 attvaluelen++;
96 p->xml++;
97 if (p->xml >= p->xmlend)
98 return -1;
99 }
100 }
101 /*printf("%.*s='%.*s'\n",
102 attnamelen, attname, attvaluelen, attvalue); */
103 if (p->attfunc)
104 p->attfunc (p->data, attname, attnamelen, attvalue, attvaluelen);
105 }
106 p->xml++;
107 }
108 return -1;
109}
110
111/* parseelt parse the xml stream and
112 * call the callback functions when needed... */
113void
114parseelt (struct xmlparser *p)
115{
116 int i;
117 const char *elementname;
118 while (p->xml < (p->xmlend - 1))
119 {
120 if ((p->xml)[0] == '<' && (p->xml)[1] != '?')
121 {
122 i = 0;
123 elementname = ++p->xml;
124 while (!IS_WHITE_SPACE (*p->xml)
125 && (*p->xml != '>') && (*p->xml != '/'))
126 {
127 i++;
128 p->xml++;
129 if (p->xml >= p->xmlend)
130 return;
131 /* to ignore namespace : */
132 if (*p->xml == ':')
133 {
134 i = 0;
135 elementname = ++p->xml;
136 }
137 }
138 if (i > 0)
139 {
140 if (p->starteltfunc)
141 p->starteltfunc (p->data, elementname, i);
142 if (parseatt (p))
143 return;
144 if (*p->xml != '/')
145 {
146 const char *data;
147 i = 0;
148 data = ++p->xml;
149 if (p->xml >= p->xmlend)
150 return;
151 while (IS_WHITE_SPACE (*p->xml))
152 {
153 p->xml++;
154 if (p->xml >= p->xmlend)
155 return;
156 }
157 while (*p->xml != '<')
158 {
159 i++;
160 p->xml++;
161 if (p->xml >= p->xmlend)
162 return;
163 }
164 if (i > 0 && p->datafunc)
165 p->datafunc (p->data, data, i);
166 }
167 }
168 else if (*p->xml == '/')
169 {
170 i = 0;
171 elementname = ++p->xml;
172 if (p->xml >= p->xmlend)
173 return;
174 while ((*p->xml != '>'))
175 {
176 i++;
177 p->xml++;
178 if (p->xml >= p->xmlend)
179 return;
180 }
181 if (p->endeltfunc)
182 p->endeltfunc (p->data, elementname, i);
183 p->xml++;
184 }
185 }
186 else
187 {
188 p->xml++;
189 }
190 }
191}
192
193/* the parser must be initialized before calling this function */
194void
195parsexml (struct xmlparser *parser)
196{
197 parser->xml = parser->xmlstart;
198 parser->xmlend = parser->xmlstart + parser->xmlsize;
199 parseelt (parser);
200}
diff --git a/src/nat/miniupnp/minixml.h b/src/nat/miniupnp/minixml.h
deleted file mode 100644
index 6ffb987ac..000000000
--- a/src/nat/miniupnp/minixml.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
2/* minimal xml parser
3 *
4 * Project : miniupnp
5 * Website : http://miniupnp.free.fr/
6 * Author : Thomas Bernard
7 * Copyright (c) 2005 Thomas Bernard
8 * This software is subject to the conditions detailed in the
9 * LICENCE file provided in this distribution.
10 * */
11#ifndef __MINIXML_H__
12#define __MINIXML_H__
13#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
14
15/* if a callback function pointer is set to NULL,
16 * the function is not called */
17struct xmlparser
18{
19 const char *xmlstart;
20 const char *xmlend;
21 const char *xml; /* pointer to current character */
22 int xmlsize;
23 void *data;
24 void (*starteltfunc) (void *, const char *, int);
25 void (*endeltfunc) (void *, const char *, int);
26 void (*datafunc) (void *, const char *, int);
27 void (*attfunc) (void *, const char *, int, const char *, int);
28};
29
30/* parsexml()
31 * the xmlparser structure must be initialized before the call
32 * the following structure members have to be initialized :
33 * xmlstart, xmlsize, data, *func
34 * xml is for internal usage, xmlend is computed automatically */
35void parsexml (struct xmlparser *);
36
37#endif
diff --git a/src/nat/miniupnp/upnpcommands.c b/src/nat/miniupnp/upnpcommands.c
deleted file mode 100644
index 8b59bc7cc..000000000
--- a/src/nat/miniupnp/upnpcommands.c
+++ /dev/null
@@ -1,605 +0,0 @@
1/* $Id: upnpcommands.c,v 1.24 2009/04/17 21:21:19 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005-2009 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#include <stdlib.h>
9#include <stdio.h>
10#include <string.h>
11#include "upnpcommands.h"
12#include "miniupnpc.h"
13
14static UNSIGNED_INTEGER
15my_atoui (const char *s)
16{
17 return s ? ((UNSIGNED_INTEGER) STRTOUI (s, NULL, 0)) : 0;
18}
19
20/*
21 * */
22UNSIGNED_INTEGER
23UPNP_GetTotalBytesSent (const char *controlURL, const char *servicetype)
24{
25 struct NameValueParserData pdata;
26 char buffer[4096];
27 int bufsize = 4096;
28 unsigned int r = 0;
29 char *p;
30 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalBytesSent", 0,
31 buffer, &bufsize);
32 ParseNameValue (buffer, bufsize, &pdata);
33 /*DisplayNameValueList(buffer, bufsize); */
34 p = GetValueFromNameValueList (&pdata, "NewTotalBytesSent");
35 r = my_atoui (p);
36 ClearNameValueList (&pdata);
37 return r;
38}
39
40/*
41 * */
42UNSIGNED_INTEGER
43UPNP_GetTotalBytesReceived (const char *controlURL, const char *servicetype)
44{
45 struct NameValueParserData pdata;
46 char buffer[4096];
47 int bufsize = 4096;
48 unsigned int r = 0;
49 char *p;
50 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalBytesReceived", 0,
51 buffer, &bufsize);
52 ParseNameValue (buffer, bufsize, &pdata);
53 /*DisplayNameValueList(buffer, bufsize); */
54 p = GetValueFromNameValueList (&pdata, "NewTotalBytesReceived");
55 r = my_atoui (p);
56 ClearNameValueList (&pdata);
57 return r;
58}
59
60/*
61 * */
62UNSIGNED_INTEGER
63UPNP_GetTotalPacketsSent (const char *controlURL, const char *servicetype)
64{
65 struct NameValueParserData pdata;
66 char buffer[4096];
67 int bufsize = 4096;
68 unsigned int r = 0;
69 char *p;
70 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalPacketsSent", 0,
71 buffer, &bufsize);
72 ParseNameValue (buffer, bufsize, &pdata);
73 /*DisplayNameValueList(buffer, bufsize); */
74 p = GetValueFromNameValueList (&pdata, "NewTotalPacketsSent");
75 r = my_atoui (p);
76 ClearNameValueList (&pdata);
77 return r;
78}
79
80/*
81 * */
82UNSIGNED_INTEGER
83UPNP_GetTotalPacketsReceived (const char *controlURL, const char *servicetype)
84{
85 struct NameValueParserData pdata;
86 char buffer[4096];
87 int bufsize = 4096;
88 unsigned int r = 0;
89 char *p;
90 simpleUPnPcommand (-1, controlURL, servicetype, "GetTotalPacketsReceived",
91 0, buffer, &bufsize);
92 ParseNameValue (buffer, bufsize, &pdata);
93 /*DisplayNameValueList(buffer, bufsize); */
94 p = GetValueFromNameValueList (&pdata, "NewTotalPacketsReceived");
95 r = my_atoui (p);
96 ClearNameValueList (&pdata);
97 return r;
98}
99
100/* UPNP_GetStatusInfo() call the corresponding UPNP method
101 * returns the current status and uptime */
102int
103UPNP_GetStatusInfo (const char *controlURL,
104 const char *servicetype,
105 char *status, unsigned int *uptime, char *lastconnerror)
106{
107 struct NameValueParserData pdata;
108 char buffer[4096];
109 int bufsize = 4096;
110 char *p;
111 char *up;
112 char *err;
113 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
114
115 if (!status && !uptime)
116 return UPNPCOMMAND_INVALID_ARGS;
117
118 simpleUPnPcommand (-1, controlURL, servicetype, "GetStatusInfo", 0, buffer,
119 &bufsize);
120 ParseNameValue (buffer, bufsize, &pdata);
121 /*DisplayNameValueList(buffer, bufsize); */
122 up = GetValueFromNameValueList (&pdata, "NewUptime");
123 p = GetValueFromNameValueList (&pdata, "NewConnectionStatus");
124 err = GetValueFromNameValueList (&pdata, "NewLastConnectionError");
125 if (p && up)
126 ret = UPNPCOMMAND_SUCCESS;
127
128 if (status)
129 {
130 if (p)
131 {
132 strncpy (status, p, 64);
133 status[63] = '\0';
134 }
135 else
136 status[0] = '\0';
137 }
138
139 if (uptime)
140 {
141 if (up)
142 sscanf (up, "%u", uptime);
143 else
144 uptime = 0;
145 }
146
147 if (lastconnerror)
148 {
149 if (err)
150 {
151 strncpy (lastconnerror, err, 64);
152 lastconnerror[63] = '\0';
153 }
154 else
155 lastconnerror[0] = '\0';
156 }
157
158 p = GetValueFromNameValueList (&pdata, "errorCode");
159 if (p)
160 {
161 ret = UPNPCOMMAND_UNKNOWN_ERROR;
162 sscanf (p, "%d", &ret);
163 }
164 ClearNameValueList (&pdata);
165 return ret;
166}
167
168/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
169 * returns the connection type */
170int
171UPNP_GetConnectionTypeInfo (const char *controlURL,
172 const char *servicetype, char *connectionType)
173{
174 struct NameValueParserData pdata;
175 char buffer[4096];
176 int bufsize = 4096;
177 char *p;
178 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
179
180 if (!connectionType)
181 return UPNPCOMMAND_INVALID_ARGS;
182
183 simpleUPnPcommand (-1, controlURL, servicetype,
184 "GetConnectionTypeInfo", 0, buffer, &bufsize);
185 ParseNameValue (buffer, bufsize, &pdata);
186 p = GetValueFromNameValueList (&pdata, "NewConnectionType");
187 /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes"); */
188 /* PossibleConnectionTypes will have several values.... */
189 if (p)
190 {
191 strncpy (connectionType, p, 64);
192 connectionType[63] = '\0';
193 ret = UPNPCOMMAND_SUCCESS;
194 }
195 else
196 connectionType[0] = '\0';
197 p = GetValueFromNameValueList (&pdata, "errorCode");
198 if (p)
199 {
200 ret = UPNPCOMMAND_UNKNOWN_ERROR;
201 sscanf (p, "%d", &ret);
202 }
203 ClearNameValueList (&pdata);
204 return ret;
205}
206
207/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
208 * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
209 * One of the values can be null
210 * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
211 * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
212int
213UPNP_GetLinkLayerMaxBitRates (const char *controlURL, const char *servicetype,
214 unsigned int *bitrateDown,
215 unsigned int *bitrateUp)
216{
217 struct NameValueParserData pdata;
218 char buffer[4096];
219 int bufsize = 4096;
220 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
221 char *down;
222 char *up;
223 char *p;
224
225 if (!bitrateDown && !bitrateUp)
226 return UPNPCOMMAND_INVALID_ARGS;
227
228 /* shouldn't we use GetCommonLinkProperties ? */
229 simpleUPnPcommand (-1, controlURL, servicetype,
230 "GetCommonLinkProperties", 0, buffer, &bufsize);
231 /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize); */
232 /*DisplayNameValueList(buffer, bufsize); */
233 ParseNameValue (buffer, bufsize, &pdata);
234 /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate"); */
235 /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate"); */
236 down = GetValueFromNameValueList (&pdata, "NewLayer1DownstreamMaxBitRate");
237 up = GetValueFromNameValueList (&pdata, "NewLayer1UpstreamMaxBitRate");
238 /*GetValueFromNameValueList(&pdata, "NewWANAccessType"); */
239 /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus"); */
240 if (down && up)
241 ret = UPNPCOMMAND_SUCCESS;
242
243 if (bitrateDown)
244 {
245 if (down)
246 sscanf (down, "%u", bitrateDown);
247 else
248 *bitrateDown = 0;
249 }
250
251 if (bitrateUp)
252 {
253 if (up)
254 sscanf (up, "%u", bitrateUp);
255 else
256 *bitrateUp = 0;
257 }
258 p = GetValueFromNameValueList (&pdata, "errorCode");
259 if (p)
260 {
261 ret = UPNPCOMMAND_UNKNOWN_ERROR;
262 sscanf (p, "%d", &ret);
263 }
264 ClearNameValueList (&pdata);
265 return ret;
266}
267
268
269/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
270 * if the third arg is not null the value is copied to it.
271 * at least 128 bytes must be available
272 *
273 * Return values :
274 * 0 : SUCCESS
275 * NON ZERO : ERROR Either an UPnP error code or an unknown error.
276 *
277 * 402 Invalid Args - See UPnP Device Architecture section on Control.
278 * 501 Action Failed - See UPnP Device Architecture section on Control.
279 */
280int
281UPNP_GetExternalIPAddress (const char *controlURL,
282 const char *servicetype, char *extIpAdd)
283{
284 struct NameValueParserData pdata;
285 char buffer[4096];
286 int bufsize = 4096;
287 char *p;
288 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
289
290 if (!extIpAdd || !controlURL || !servicetype)
291 return UPNPCOMMAND_INVALID_ARGS;
292
293 simpleUPnPcommand (-1, controlURL, servicetype, "GetExternalIPAddress", 0,
294 buffer, &bufsize);
295 /*DisplayNameValueList(buffer, bufsize); */
296 ParseNameValue (buffer, bufsize, &pdata);
297 /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") ); */
298 p = GetValueFromNameValueList (&pdata, "NewExternalIPAddress");
299 if (p)
300 {
301 strncpy (extIpAdd, p, 128);
302 extIpAdd[127] = '\0';
303 ret = UPNPCOMMAND_SUCCESS;
304 }
305 else
306 extIpAdd[0] = '\0';
307
308 p = GetValueFromNameValueList (&pdata, "errorCode");
309 if (p)
310 {
311 ret = UPNPCOMMAND_UNKNOWN_ERROR;
312 sscanf (p, "%d", &ret);
313 }
314
315 ClearNameValueList (&pdata);
316 return ret;
317}
318
319int
320UPNP_AddPortMapping (const char *controlURL, const char *servicetype,
321 const char *extPort,
322 const char *inPort,
323 const char *inClient,
324 const char *desc,
325 const char *proto, const char *remoteHost)
326{
327 struct UPNParg *AddPortMappingArgs;
328 char buffer[4096];
329 int bufsize = 4096;
330 struct NameValueParserData pdata;
331 const char *resVal;
332 int ret;
333
334 if (!inPort || !inClient || !proto || !extPort)
335 return UPNPCOMMAND_INVALID_ARGS;
336
337 AddPortMappingArgs = calloc (9, sizeof (struct UPNParg));
338 AddPortMappingArgs[0].elt = "NewRemoteHost";
339 AddPortMappingArgs[0].val = remoteHost;
340 AddPortMappingArgs[1].elt = "NewExternalPort";
341 AddPortMappingArgs[1].val = extPort;
342 AddPortMappingArgs[2].elt = "NewProtocol";
343 AddPortMappingArgs[2].val = proto;
344 AddPortMappingArgs[3].elt = "NewInternalPort";
345 AddPortMappingArgs[3].val = inPort;
346 AddPortMappingArgs[4].elt = "NewInternalClient";
347 AddPortMappingArgs[4].val = inClient;
348 AddPortMappingArgs[5].elt = "NewEnabled";
349 AddPortMappingArgs[5].val = "1";
350 AddPortMappingArgs[6].elt = "NewPortMappingDescription";
351 AddPortMappingArgs[6].val = desc ? desc : "libminiupnpc";
352 AddPortMappingArgs[7].elt = "NewLeaseDuration";
353 AddPortMappingArgs[7].val = "0";
354 simpleUPnPcommand (-1, controlURL, servicetype, "AddPortMapping",
355 AddPortMappingArgs, buffer, &bufsize);
356 /*DisplayNameValueList(buffer, bufsize); */
357 /*buffer[bufsize] = '\0'; */
358 /*puts(buffer); */
359 ParseNameValue (buffer, bufsize, &pdata);
360 resVal = GetValueFromNameValueList (&pdata, "errorCode");
361 if (resVal)
362 {
363 /* printf("AddPortMapping errorCode = '%s'\n", resVal); */
364 ret = UPNPCOMMAND_UNKNOWN_ERROR;
365 sscanf (resVal, "%d", &ret);
366 }
367 else
368 {
369 ret = UPNPCOMMAND_SUCCESS;
370 }
371 ClearNameValueList (&pdata);
372 free (AddPortMappingArgs);
373 return ret;
374}
375
376int
377UPNP_DeletePortMapping (const char *controlURL, const char *servicetype,
378 const char *extPort, const char *proto,
379 const char *remoteHost)
380{
381 /*struct NameValueParserData pdata; */
382 struct UPNParg *DeletePortMappingArgs;
383 char buffer[4096];
384 int bufsize = 4096;
385 struct NameValueParserData pdata;
386 const char *resVal;
387 int ret;
388
389 if (!extPort || !proto)
390 return UPNPCOMMAND_INVALID_ARGS;
391
392 DeletePortMappingArgs = calloc (4, sizeof (struct UPNParg));
393 DeletePortMappingArgs[0].elt = "NewRemoteHost";
394 DeletePortMappingArgs[0].val = remoteHost;
395 DeletePortMappingArgs[1].elt = "NewExternalPort";
396 DeletePortMappingArgs[1].val = extPort;
397 DeletePortMappingArgs[2].elt = "NewProtocol";
398 DeletePortMappingArgs[2].val = proto;
399 simpleUPnPcommand (-1, controlURL, servicetype,
400 "DeletePortMapping",
401 DeletePortMappingArgs, buffer, &bufsize);
402 /*DisplayNameValueList(buffer, bufsize); */
403 ParseNameValue (buffer, bufsize, &pdata);
404 resVal = GetValueFromNameValueList (&pdata, "errorCode");
405 if (resVal)
406 {
407 ret = UPNPCOMMAND_UNKNOWN_ERROR;
408 sscanf (resVal, "%d", &ret);
409 }
410 else
411 {
412 ret = UPNPCOMMAND_SUCCESS;
413 }
414 ClearNameValueList (&pdata);
415 free (DeletePortMappingArgs);
416 return ret;
417}
418
419int
420UPNP_GetGenericPortMappingEntry (const char *controlURL,
421 const char *servicetype,
422 const char *index,
423 char *extPort,
424 char *intClient,
425 char *intPort,
426 char *protocol,
427 char *desc,
428 char *enabled, char *rHost, char *duration)
429{
430 struct NameValueParserData pdata;
431 struct UPNParg *GetPortMappingArgs;
432 char buffer[4096];
433 int bufsize = 4096;
434 char *p;
435 int r = UPNPCOMMAND_UNKNOWN_ERROR;
436 if (!index)
437 return UPNPCOMMAND_INVALID_ARGS;
438
439 GetPortMappingArgs = calloc (2, sizeof (struct UPNParg));
440 GetPortMappingArgs[0].elt = "NewPortMappingIndex";
441 GetPortMappingArgs[0].val = index;
442 simpleUPnPcommand (-1, controlURL, servicetype,
443 "GetGenericPortMappingEntry",
444 GetPortMappingArgs, buffer, &bufsize);
445 ParseNameValue (buffer, bufsize, &pdata);
446 p = GetValueFromNameValueList (&pdata, "NewRemoteHost");
447 if (p && rHost)
448 {
449 strncpy (rHost, p, 64);
450 rHost[63] = '\0';
451 }
452 p = GetValueFromNameValueList (&pdata, "NewExternalPort");
453 if (p && extPort)
454 {
455 strncpy (extPort, p, 6);
456 extPort[5] = '\0';
457 r = UPNPCOMMAND_SUCCESS;
458 }
459 p = GetValueFromNameValueList (&pdata, "NewProtocol");
460 if (p && protocol)
461 {
462 strncpy (protocol, p, 4);
463 protocol[3] = '\0';
464 }
465 p = GetValueFromNameValueList (&pdata, "NewInternalClient");
466 if (p && intClient)
467 {
468 strncpy (intClient, p, 128);
469 intClient[127] = '\0';
470 r = 0;
471 }
472 p = GetValueFromNameValueList (&pdata, "NewInternalPort");
473 if (p && intPort)
474 {
475 strncpy (intPort, p, 6);
476 intPort[5] = '\0';
477 }
478 p = GetValueFromNameValueList (&pdata, "NewEnabled");
479 if (p && enabled)
480 {
481 strncpy (enabled, p, 4);
482 enabled[3] = '\0';
483 }
484 p = GetValueFromNameValueList (&pdata, "NewPortMappingDescription");
485 if (p && desc)
486 {
487 strncpy (desc, p, 80);
488 desc[79] = '\0';
489 }
490 p = GetValueFromNameValueList (&pdata, "NewLeaseDuration");
491 if (p && duration)
492 {
493 strncpy (duration, p, 16);
494 duration[15] = '\0';
495 }
496 p = GetValueFromNameValueList (&pdata, "errorCode");
497 if (p)
498 {
499 r = UPNPCOMMAND_UNKNOWN_ERROR;
500 sscanf (p, "%d", &r);
501 }
502 ClearNameValueList (&pdata);
503 free (GetPortMappingArgs);
504 return r;
505}
506
507int
508UPNP_GetPortMappingNumberOfEntries (const char *controlURL,
509 const char *servicetype,
510 unsigned int *numEntries)
511{
512 struct NameValueParserData pdata;
513 char buffer[4096];
514 int bufsize = 4096;
515 char *p;
516 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
517 simpleUPnPcommand (-1, controlURL, servicetype,
518 "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
519#ifdef DEBUG
520 DisplayNameValueList (buffer, bufsize);
521#endif
522 ParseNameValue (buffer, bufsize, &pdata);
523
524 p = GetValueFromNameValueList (&pdata, "NewPortMappingNumberOfEntries");
525 if (numEntries && p)
526 {
527 *numEntries = 0;
528 sscanf (p, "%u", numEntries);
529 ret = UPNPCOMMAND_SUCCESS;
530 }
531
532 p = GetValueFromNameValueList (&pdata, "errorCode");
533 if (p)
534 {
535 ret = UPNPCOMMAND_UNKNOWN_ERROR;
536 sscanf (p, "%d", &ret);
537 }
538
539 ClearNameValueList (&pdata);
540 return ret;
541}
542
543/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
544 * the result is returned in the intClient and intPort strings
545 * please provide 128 and 6 bytes of data */
546int
547UPNP_GetSpecificPortMappingEntry (const char *controlURL,
548 const char *servicetype,
549 const char *extPort,
550 const char *proto,
551 char *intClient, char *intPort)
552{
553 struct NameValueParserData pdata;
554 struct UPNParg *GetPortMappingArgs;
555 char buffer[4096];
556 int bufsize = 4096;
557 char *p;
558 int ret = UPNPCOMMAND_UNKNOWN_ERROR;
559
560 if (!intPort || !intClient || !extPort || !proto)
561 return UPNPCOMMAND_INVALID_ARGS;
562
563 GetPortMappingArgs = calloc (4, sizeof (struct UPNParg));
564 GetPortMappingArgs[0].elt = "NewRemoteHost";
565 GetPortMappingArgs[1].elt = "NewExternalPort";
566 GetPortMappingArgs[1].val = extPort;
567 GetPortMappingArgs[2].elt = "NewProtocol";
568 GetPortMappingArgs[2].val = proto;
569 simpleUPnPcommand (-1, controlURL, servicetype,
570 "GetSpecificPortMappingEntry",
571 GetPortMappingArgs, buffer, &bufsize);
572 /*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
573 /*DisplayNameValueList(buffer, bufsize); */
574 ParseNameValue (buffer, bufsize, &pdata);
575
576 p = GetValueFromNameValueList (&pdata, "NewInternalClient");
577 if (p)
578 {
579 strncpy (intClient, p, 128);
580 intClient[127] = '\0';
581 ret = UPNPCOMMAND_SUCCESS;
582 }
583 else
584 intClient[0] = '\0';
585
586 p = GetValueFromNameValueList (&pdata, "NewInternalPort");
587 if (p)
588 {
589 strncpy (intPort, p, 6);
590 intPort[5] = '\0';
591 }
592 else
593 intPort[0] = '\0';
594
595 p = GetValueFromNameValueList (&pdata, "errorCode");
596 if (p)
597 {
598 ret = UPNPCOMMAND_UNKNOWN_ERROR;
599 sscanf (p, "%d", &ret);
600 }
601
602 ClearNameValueList (&pdata);
603 free (GetPortMappingArgs);
604 return ret;
605}
diff --git a/src/nat/miniupnp/upnpcommands.h b/src/nat/miniupnp/upnpcommands.h
deleted file mode 100644
index fa1d604ae..000000000
--- a/src/nat/miniupnp/upnpcommands.h
+++ /dev/null
@@ -1,189 +0,0 @@
1/* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
2/* Miniupnp project : http://miniupnp.free.fr/
3 * Author : Thomas Bernard
4 * Copyright (c) 2005-2008 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided within this distribution */
7#ifndef __UPNPCOMMANDS_H__
8#define __UPNPCOMMANDS_H__
9
10#include "upnpreplyparse.h"
11#include "declspec.h"
12
13/* MiniUPnPc return codes : */
14#define UPNPCOMMAND_SUCCESS (0)
15#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
16#define UPNPCOMMAND_INVALID_ARGS (-2)
17
18#ifdef __cplusplus
19extern "C"
20{
21#endif
22
23#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
24#define UNSIGNED_INTEGER unsigned long long
25#define STRTOUI strtoull
26#else
27#define UNSIGNED_INTEGER unsigned int
28#define STRTOUI strtoul
29#endif
30
31 LIBSPEC UNSIGNED_INTEGER
32 UPNP_GetTotalBytesSent (const char *controlURL, const char *servicetype);
33
34 LIBSPEC UNSIGNED_INTEGER
35 UPNP_GetTotalBytesReceived (const char *controlURL,
36 const char *servicetype);
37
38 LIBSPEC UNSIGNED_INTEGER
39 UPNP_GetTotalPacketsSent (const char *controlURL,
40 const char *servicetype);
41
42 LIBSPEC UNSIGNED_INTEGER
43 UPNP_GetTotalPacketsReceived (const char *controlURL,
44 const char *servicetype);
45
46/* UPNP_GetStatusInfo()
47 * status and lastconnerror are 64 byte buffers
48 * Return values :
49 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
50 * or a UPnP Error code */
51 LIBSPEC int
52 UPNP_GetStatusInfo (const char *controlURL,
53 const char *servicetype,
54 char *status,
55 unsigned int *uptime, char *lastconnerror);
56
57/* UPNP_GetConnectionTypeInfo()
58 * argument connectionType is a 64 character buffer
59 * Return Values :
60 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
61 * or a UPnP Error code */
62 LIBSPEC int
63 UPNP_GetConnectionTypeInfo (const char *controlURL,
64 const char *servicetype,
65 char *connectionType);
66
67/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
68 * if the third arg is not null the value is copied to it.
69 * at least 128 bytes must be available
70 *
71 * Return values :
72 * 0 : SUCCESS
73 * NON ZERO : ERROR Either an UPnP error code or an unknown error.
74 *
75 * possible UPnP Errors :
76 * 402 Invalid Args - See UPnP Device Architecture section on Control.
77 * 501 Action Failed - See UPnP Device Architecture section on Control. */
78 LIBSPEC int
79 UPNP_GetExternalIPAddress (const char *controlURL,
80 const char *servicetype, char *extIpAdd);
81
82/* UPNP_GetLinkLayerMaxBitRates()
83 * call WANCommonInterfaceConfig:1#GetCommonLinkProperties
84 *
85 * return values :
86 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
87 * or a UPnP Error Code. */
88 LIBSPEC int
89 UPNP_GetLinkLayerMaxBitRates (const char *controlURL,
90 const char *servicetype,
91 unsigned int *bitrateDown,
92 unsigned int *bitrateUp);
93
94/* UPNP_AddPortMapping()
95 * if desc is NULL, it will be defaulted to "libminiupnpc"
96 * remoteHost is usually NULL because IGD don't support it.
97 *
98 * Return values :
99 * 0 : SUCCESS
100 * NON ZERO : ERROR. Either an UPnP error code or an unknown error.
101 *
102 * List of possible UPnP errors for AddPortMapping :
103 * errorCode errorDescription (short) - Description (long)
104 * 402 Invalid Args - See UPnP Device Architecture section on Control.
105 * 501 Action Failed - See UPnP Device Architecture section on Control.
106 * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
107 * wild-carded
108 * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
109 * 718 ConflictInMappingEntry - The port mapping entry specified conflicts
110 * with a mapping assigned previously to another client
111 * 724 SamePortValuesRequired - Internal and External port values
112 * must be the same
113 * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
114 * permanent lease times on port mappings
115 * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard
116 * and cannot be a specific IP address or DNS name
117 * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and
118 * cannot be a specific port value */
119 LIBSPEC int
120 UPNP_AddPortMapping (const char *controlURL, const char *servicetype,
121 const char *extPort,
122 const char *inPort,
123 const char *inClient,
124 const char *desc,
125 const char *proto, const char *remoteHost);
126
127/* UPNP_DeletePortMapping()
128 * Use same argument values as what was used for AddPortMapping().
129 * remoteHost is usually NULL because IGD don't support it.
130 * Return Values :
131 * 0 : SUCCESS
132 * NON ZERO : error. Either an UPnP error code or an undefined error.
133 *
134 * List of possible UPnP errors for DeletePortMapping :
135 * 402 Invalid Args - See UPnP Device Architecture section on Control.
136 * 714 NoSuchEntryInArray - The specified value does not exist in the array */
137 LIBSPEC int
138 UPNP_DeletePortMapping (const char *controlURL, const char *servicetype,
139 const char *extPort, const char *proto,
140 const char *remoteHost);
141
142/* UPNP_GetPortMappingNumberOfEntries()
143 * not supported by all routers */
144 LIBSPEC int
145 UPNP_GetPortMappingNumberOfEntries (const char *controlURL,
146 const char *servicetype,
147 unsigned int *num);
148
149/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
150 * the result is returned in the intClient and intPort strings
151 * please provide 128 and 6 bytes of data
152 *
153 * return value :
154 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
155 * or a UPnP Error Code. */
156 LIBSPEC int
157 UPNP_GetSpecificPortMappingEntry (const char *controlURL,
158 const char *servicetype,
159 const char *extPort,
160 const char *proto,
161 char *intClient, char *intPort);
162
163/* UPNP_GetGenericPortMappingEntry()
164 *
165 * return value :
166 * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
167 * or a UPnP Error Code.
168 *
169 * Possible UPNP Error codes :
170 * 402 Invalid Args - See UPnP Device Architecture section on Control.
171 * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
172 */
173 LIBSPEC int
174 UPNP_GetGenericPortMappingEntry (const char *controlURL,
175 const char *servicetype,
176 const char *index,
177 char *extPort,
178 char *intClient,
179 char *intPort,
180 char *protocol,
181 char *desc,
182 char *enabled,
183 char *rHost, char *duration);
184
185#ifdef __cplusplus
186}
187#endif
188
189#endif
diff --git a/src/nat/miniupnp/upnpreplyparse.c b/src/nat/miniupnp/upnpreplyparse.c
deleted file mode 100644
index 9aa895d1d..000000000
--- a/src/nat/miniupnp/upnpreplyparse.c
+++ /dev/null
@@ -1,122 +0,0 @@
1/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */
2/* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
7
8#include <stdlib.h>
9#include <string.h>
10#include <stdio.h>
11
12#include "upnpreplyparse.h"
13#include "minixml.h"
14
15static void
16NameValueParserStartElt (void *d, const char *name, int l)
17{
18 struct NameValueParserData *data = (struct NameValueParserData *) d;
19 if (l > 63)
20 l = 63;
21 memcpy (data->curelt, name, l);
22 data->curelt[l] = '\0';
23}
24
25static void
26NameValueParserGetData (void *d, const char *datas, int l)
27{
28 struct NameValueParserData *data = (struct NameValueParserData *) d;
29 struct NameValue *nv;
30 nv = malloc (sizeof (struct NameValue));
31 if (l > 63)
32 l = 63;
33 strncpy (nv->name, data->curelt, 64);
34 nv->name[63] = '\0';
35 memcpy (nv->value, datas, l);
36 nv->value[l] = '\0';
37 LIST_INSERT_HEAD (&(data->head), nv, entries);
38}
39
40void
41ParseNameValue (const char *buffer, int bufsize,
42 struct NameValueParserData *data)
43{
44 struct xmlparser parser;
45 LIST_INIT (&(data->head));
46 /* init xmlparser object */
47 parser.xmlstart = buffer;
48 parser.xmlsize = bufsize;
49 parser.data = data;
50 parser.starteltfunc = NameValueParserStartElt;
51 parser.endeltfunc = 0;
52 parser.datafunc = NameValueParserGetData;
53 parser.attfunc = 0;
54 parsexml (&parser);
55}
56
57void
58ClearNameValueList (struct NameValueParserData *pdata)
59{
60 struct NameValue *nv;
61 while ((nv = pdata->head.lh_first) != NULL)
62 {
63 LIST_REMOVE (nv, entries);
64 free (nv);
65 }
66}
67
68char *
69GetValueFromNameValueList (struct NameValueParserData *pdata,
70 const char *Name)
71{
72 struct NameValue *nv;
73 char *p = NULL;
74 for (nv = pdata->head.lh_first;
75 (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
76 {
77 if (strcmp (nv->name, Name) == 0)
78 p = nv->value;
79 }
80 return p;
81}
82
83#if 0
84/* useless now that minixml ignores namespaces by itself */
85char *
86GetValueFromNameValueListIgnoreNS (struct NameValueParserData *pdata,
87 const char *Name)
88{
89 struct NameValue *nv;
90 char *p = NULL;
91 char *pname;
92 for (nv = pdata->head.lh_first;
93 (nv != NULL) && (p == NULL); nv = nv->entries.le_next)
94 {
95 pname = strrchr (nv->name, ':');
96 if (pname)
97 pname++;
98 else
99 pname = nv->name;
100 if (strcmp (pname, Name) == 0)
101 p = nv->value;
102 }
103 return p;
104}
105#endif
106
107/* debug all-in-one function
108 * do parsing then display to stdout */
109#ifdef DEBUG
110void
111DisplayNameValueList (char *buffer, int bufsize)
112{
113 struct NameValueParserData pdata;
114 struct NameValue *nv;
115 ParseNameValue (buffer, bufsize, &pdata);
116 for (nv = pdata.head.lh_first; nv != NULL; nv = nv->entries.le_next)
117 {
118 printf ("%s = %s\n", nv->name, nv->value);
119 }
120 ClearNameValueList (&pdata);
121}
122#endif
diff --git a/src/nat/miniupnp/upnpreplyparse.h b/src/nat/miniupnp/upnpreplyparse.h
deleted file mode 100644
index a1c8a9431..000000000
--- a/src/nat/miniupnp/upnpreplyparse.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/* $Id: upnpreplyparse.h,v 1.8 2008/02/21 13:05:27 nanard Exp $ */
2/* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
7
8#ifndef __UPNPREPLYPARSE_H__
9#define __UPNPREPLYPARSE_H__
10
11#if defined(NO_SYS_QUEUE_H) || defined(WIN32)
12#include "bsdqueue.h"
13#else
14#include <sys/queue.h>
15#endif
16
17#ifdef __cplusplus
18extern "C"
19{
20#endif
21
22 struct NameValue
23 {
24 LIST_ENTRY (NameValue) entries;
25 char name[64];
26 char value[64];
27 };
28
29 struct NameValueParserData
30 {
31 LIST_HEAD (listhead, NameValue) head;
32 char curelt[64];
33 };
34
35/* ParseNameValue() */
36 void
37 ParseNameValue (const char *buffer, int bufsize,
38 struct NameValueParserData *data);
39
40/* ClearNameValueList() */
41 void ClearNameValueList (struct NameValueParserData *pdata);
42
43/* GetValueFromNameValueList() */
44 char *GetValueFromNameValueList (struct NameValueParserData *pdata,
45 const char *Name);
46
47/* GetValueFromNameValueListIgnoreNS() */
48 char *GetValueFromNameValueListIgnoreNS (struct NameValueParserData *pdata,
49 const char *Name);
50
51/* DisplayNameValueList() */
52#ifdef DEBUG
53 void DisplayNameValueList (char *buffer, int bufsize);
54#endif
55
56#ifdef __cplusplus
57}
58#endif
59
60#endif