Fix W32 interface listing, and correctly copy addr in test-nat (patch by LRN)
[oweals/gnunet.git] / src / nat / upnp-igd-parse.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /*
22  * Code in this file is originally based on the miniupnp library.
23  * Copyright (c) 2005-2008, Thomas BERNARD. All rights reserved.
24  *
25  * Original licence:
26  * 
27  * Redistribution and use in source and binary forms, with or without
28  * modification, are permitted provided that the following conditions are met:
29  * 
30  *   * Redistributions of source code must retain the above copyright notice,
31  *     this list of conditions and the following disclaimer.
32  *   * Redistributions in binary form must reproduce the above copyright notice,
33  *     this list of conditions and the following disclaimer in the documentation
34  *     and/or other materials provided with the distribution.
35  *   * The name of the author may not be used to endorse or promote products
36  *         derived from this software without specific prior written permission.
37  * 
38  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
39  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
42  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  */
50
51 /**
52  * @file nat/upnp-igd-parse.h
53  * @brief Parser for XML descriptions of UPnP Internet Gateway Devices
54  *
55  * @author Milan Bouchet-Valat
56  */
57 #include <stdio.h>
58 #include <string.h>
59
60 #include "platform.h"
61 #include "gnunet_util_lib.h"
62 #include "upnp-minixml.h"
63 #include "upnp-igd-parse.h"
64
65 /**
66  * Start element handler: update nesting level counter
67  * and copy element name.
68  */
69 static void
70 start_elt (void *d, const char *name, int l)
71 {
72   struct UPNP_IGD_Data_ *datas = (struct UPNP_IGD_Data_ *) d;
73
74   memcpy (datas->cur_elt_name, name, l);
75   datas->cur_elt_name[l] = '\0';
76   datas->level++;
77   if ((l == 7) && !memcmp (name, "service", l))
78     {
79       datas->control_url_tmp[0] = '\0';
80       datas->event_sub_url_tmp[0] = '\0';
81       datas->scpd_url_tmp[0] = '\0';
82       datas->service_type_tmp[0] = '\0';
83     }
84 }
85
86 /**
87  * End element handler: update nesting level counter
88  * and update parser state if service element is parsed.
89  */
90 static void
91 end_elt (void *d, const char *name, int l)
92 {
93   struct UPNP_IGD_Data_ *datas = (struct UPNP_IGD_Data_ *) d;
94
95   datas->level--;
96
97   if ((l == 7) && !memcmp (name, "service", l))
98     {
99       if (0 == strcmp (datas->service_type_tmp,
100                        "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
101         {
102           memcpy (datas->control_url_CIF, datas->control_url_tmp,
103                   MINIUPNPC_URL_MAXSIZE);
104           memcpy (datas->event_sub_url_CIF, datas->event_sub_url_tmp,
105                   MINIUPNPC_URL_MAXSIZE);
106           memcpy (datas->scpd_url_CIF, datas->scpd_url_tmp,
107                   MINIUPNPC_URL_MAXSIZE);
108           memcpy (datas->service_type_CIF, datas->service_type_tmp,
109                   MINIUPNPC_URL_MAXSIZE);
110         }
111       else if (0 == strcmp (datas->service_type_tmp,
112                             "urn:schemas-upnp-org:service:WANIPConnection:1")
113                || 0 == strcmp (datas->service_type_tmp,
114                                "urn:schemas-upnp-org:service:WANPPPConnection:1"))
115         {
116           memcpy (datas->control_url, datas->control_url_tmp,
117                   MINIUPNPC_URL_MAXSIZE);
118           memcpy (datas->event_sub_url, datas->event_sub_url_tmp,
119                   MINIUPNPC_URL_MAXSIZE);
120           memcpy (datas->scpd_url, datas->scpd_url_tmp,
121                   MINIUPNPC_URL_MAXSIZE);
122           memcpy (datas->service_type, datas->service_type_tmp,
123                   MINIUPNPC_URL_MAXSIZE);
124         }
125     }
126 }
127
128 /**
129  * Data handler: copy data depending on the current
130  * element name and state.
131  */
132 static void
133 IGDdata (void *d, const char *data, int l)
134 {
135   struct UPNP_IGD_Data_ *datas = (struct UPNP_IGD_Data_ *) d;
136   char *dstmember = NULL;
137
138   if (!strcmp (datas->cur_elt_name, "URLBase"))
139     dstmember = datas->base_url;
140   else if (!strcmp (datas->cur_elt_name, "serviceType"))
141     dstmember = datas->service_type_tmp;
142   else if (!strcmp (datas->cur_elt_name, "controlURL"))
143     dstmember = datas->control_url_tmp;
144   else if (!strcmp (datas->cur_elt_name, "eventSubURL"))
145     dstmember = datas->event_sub_url_tmp;
146   else if (!strcmp (datas->cur_elt_name, "SCPDURL"))
147     dstmember = datas->scpd_url_tmp;
148
149   /* Copy current element name into destination member */
150   if (dstmember)
151     {
152       if (l >= MINIUPNPC_URL_MAXSIZE)
153         l = MINIUPNPC_URL_MAXSIZE - 1;
154
155       memcpy (dstmember, data, l);
156       dstmember[l] = '\0';
157     }
158 }
159
160 #ifdef DEBUG_UPNP
161 static void
162 print_IGD (struct UPNP_IGD_Data_ *d)
163 {
164   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "UPnP",
165                    "base_url = %s\n", d->base_url);
166   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "UPnP",
167                    "WAN Device (Common interface config) :\n"
168                    " sevice_type = %s\n"
169                    " control_url = %s\n"
170                    " event_sub_url = %s\n"
171                    " scpd_url = %s\n",
172                    d->service_type_CIF,
173                    d->control_url_CIF, d->event_sub_url_CIF, d->scpd_url_CIF);
174   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "UPnP",
175                    "WAN Connection Device (IP or PPP Connection):\n"
176                    " service_type = %s\n"
177                    " control_url = %s\n"
178                    " event_sub_url = %s\n"
179                    " scpd_url = %s\n",
180                    d->service_type,
181                    d->control_url, d->event_sub_url, d->scpd_url);
182 }
183 #endif
184
185 /**
186  * Parse XML description of an IGD device into a UPNP_IGD_Data_ struct.
187  */
188 void
189 UPNP_IGD_parse_desc_ (const char *buffer, int buf_size,
190                       struct UPNP_IGD_Data_ *data)
191 {
192   struct UPNP_xml_parser_ parser;
193
194   parser.xml_start = buffer;
195   parser.xml_size = buf_size;
196   parser.cls = data;
197   parser.start_elt_func = start_elt;
198   parser.end_elt_func = end_elt;
199   parser.data_func = IGDdata;
200   parser.att_func = 0;
201
202   UPNP_parse_xml_ (&parser);
203
204 #ifdef DEBUG_UPNP
205   print_IGD (data);
206 #endif
207 }