source: trunk/third-party/miniupnp/upnpcommands.c @ 8798

Last change on this file since 8798 was 8798, checked in by charles, 13 years ago

(trunk third-party) #2273: update to latest libnatpmp and miniupnpc libraries

File size: 16.1 KB
Line 
1/* $Id: upnpcommands.c,v 1.25 2009/07/09 16:00:42 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 * */
22LIBSPEC UNSIGNED_INTEGER
23UPNP_GetTotalBytesSent(const char * controlURL,
24                                        const char * servicetype)
25{
26        struct NameValueParserData pdata;
27        char buffer[4096];
28        int bufsize = 4096;
29        unsigned int r = 0;
30        char * p;
31        simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, 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 * */
42LIBSPEC UNSIGNED_INTEGER
43UPNP_GetTotalBytesReceived(const char * controlURL,
44                                                const char * servicetype)
45{
46        struct NameValueParserData pdata;
47        char buffer[4096];
48        int bufsize = 4096;
49        unsigned int r = 0;
50        char * p;
51        simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, 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 * */
62LIBSPEC UNSIGNED_INTEGER
63UPNP_GetTotalPacketsSent(const char * controlURL,
64                                                const char * servicetype)
65{
66        struct NameValueParserData pdata;
67        char buffer[4096];
68        int bufsize = 4096;
69        unsigned int r = 0;
70        char * p;
71        simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, 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 * */
82LIBSPEC UNSIGNED_INTEGER
83UPNP_GetTotalPacketsReceived(const char * controlURL,
84                                                const char * servicetype)
85{
86        struct NameValueParserData pdata;
87        char buffer[4096];
88        int bufsize = 4096;
89        unsigned int r = 0;
90        char * p;
91        simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 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 */
102LIBSPEC int
103UPNP_GetStatusInfo(const char * controlURL,
104                                const char * servicetype,
105                                char * status, 
106                                unsigned int * uptime,
107                                char * lastconnerror)
108{
109        struct NameValueParserData pdata;
110        char buffer[4096];
111        int bufsize = 4096;
112        char * p;
113        char * up;
114        char * err;
115        int ret = UPNPCOMMAND_UNKNOWN_ERROR;
116
117        if(!status && !uptime)
118                return UPNPCOMMAND_INVALID_ARGS;
119
120        simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize);
121        ParseNameValue(buffer, bufsize, &pdata);
122        /*DisplayNameValueList(buffer, bufsize);*/
123        up = GetValueFromNameValueList(&pdata, "NewUptime");
124        p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
125        err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
126        if(p && up)
127          ret = UPNPCOMMAND_SUCCESS;
128
129        if(status) {
130                if(p){
131                        strncpy(status, p, 64 );
132                        status[63] = '\0';
133                }else
134                        status[0]= '\0';
135        }
136
137        if(uptime) {
138                if(up)
139                        sscanf(up,"%u",uptime);
140                else
141                        uptime = 0;
142        }
143
144        if(lastconnerror) {
145                if(err) {
146                        strncpy(lastconnerror, err, 64 );
147                        lastconnerror[63] = '\0';
148                } else
149                        lastconnerror[0] = '\0';
150        }
151
152        p = GetValueFromNameValueList(&pdata, "errorCode");
153        if(p) {
154                ret = UPNPCOMMAND_UNKNOWN_ERROR;
155                sscanf(p, "%d", &ret);
156        }
157        ClearNameValueList(&pdata);
158        return ret;
159}
160
161/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
162 * returns the connection type */
163LIBSPEC int
164UPNP_GetConnectionTypeInfo(const char * controlURL,
165                           const char * servicetype,
166                           char * connectionType)
167{
168        struct NameValueParserData pdata;
169        char buffer[4096];
170        int bufsize = 4096;
171        char * p;
172        int ret = UPNPCOMMAND_UNKNOWN_ERROR;
173
174        if(!connectionType)
175                return UPNPCOMMAND_INVALID_ARGS;
176
177        simpleUPnPcommand(-1, controlURL, servicetype,
178                          "GetConnectionTypeInfo", 0, buffer, &bufsize);
179        ParseNameValue(buffer, bufsize, &pdata);
180        p = GetValueFromNameValueList(&pdata, "NewConnectionType");
181        /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
182        /* PossibleConnectionTypes will have several values.... */
183        if(p) {
184                strncpy(connectionType, p, 64 );
185                connectionType[63] = '\0';
186                ret = UPNPCOMMAND_SUCCESS;
187        } else
188                connectionType[0] = '\0';
189        p = GetValueFromNameValueList(&pdata, "errorCode");
190        if(p) {
191                ret = UPNPCOMMAND_UNKNOWN_ERROR;
192                sscanf(p, "%d", &ret);
193        }
194        ClearNameValueList(&pdata);
195        return ret;
196}
197
198/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
199 * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
200 * One of the values can be null
201 * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only
202 * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
203LIBSPEC int
204UPNP_GetLinkLayerMaxBitRates(const char * controlURL,
205                             const char * servicetype,
206                             unsigned int * bitrateDown,
207                             unsigned int* bitrateUp)
208{
209        struct NameValueParserData pdata;
210        char buffer[4096];
211        int bufsize = 4096;
212        int ret = UPNPCOMMAND_UNKNOWN_ERROR;
213        char * down;
214        char * up;
215        char * p;
216
217        if(!bitrateDown && !bitrateUp)
218                return UPNPCOMMAND_INVALID_ARGS;
219
220        /* shouldn't we use GetCommonLinkProperties ? */
221        simpleUPnPcommand(-1, controlURL, servicetype,
222                          "GetCommonLinkProperties", 0, buffer, &bufsize);
223                          /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/
224        /*DisplayNameValueList(buffer, bufsize);*/
225        ParseNameValue(buffer, bufsize, &pdata);
226        /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
227        /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
228        down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
229        up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
230        /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
231        /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus");*/
232        if(down && up)
233                ret = UPNPCOMMAND_SUCCESS;
234
235        if(bitrateDown) {
236                if(down)
237                        sscanf(down,"%u",bitrateDown);
238                else
239                        *bitrateDown = 0;
240        }
241
242        if(bitrateUp) {
243                if(up)
244                        sscanf(up,"%u",bitrateUp);
245                else
246                        *bitrateUp = 0;
247        }
248        p = GetValueFromNameValueList(&pdata, "errorCode");
249        if(p) {
250                ret = UPNPCOMMAND_UNKNOWN_ERROR;
251                sscanf(p, "%d", &ret);
252        }
253        ClearNameValueList(&pdata);
254        return ret;
255}
256
257
258/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
259 * if the third arg is not null the value is copied to it.
260 * at least 16 bytes must be available
261 *
262 * Return values :
263 * 0 : SUCCESS
264 * NON ZERO : ERROR Either an UPnP error code or an unknown error.
265 *
266 * 402 Invalid Args - See UPnP Device Architecture section on Control.
267 * 501 Action Failed - See UPnP Device Architecture section on Control.
268 */
269LIBSPEC int
270UPNP_GetExternalIPAddress(const char * controlURL,
271                          const char * servicetype,
272                          char * extIpAdd)
273{
274        struct NameValueParserData pdata;
275        char buffer[4096];
276        int bufsize = 4096;
277        char * p;
278        int ret = UPNPCOMMAND_UNKNOWN_ERROR;
279
280        if(!extIpAdd || !controlURL || !servicetype)
281                return UPNPCOMMAND_INVALID_ARGS;
282
283        simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize);
284        /*DisplayNameValueList(buffer, bufsize);*/
285        ParseNameValue(buffer, bufsize, &pdata);
286        /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
287        p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
288        if(p) {
289                strncpy(extIpAdd, p, 16 );
290                extIpAdd[15] = '\0';
291                ret = UPNPCOMMAND_SUCCESS;
292        } else
293                extIpAdd[0] = '\0';
294
295        p = GetValueFromNameValueList(&pdata, "errorCode");
296        if(p) {
297                ret = UPNPCOMMAND_UNKNOWN_ERROR;
298                sscanf(p, "%d", &ret);
299        }
300
301        ClearNameValueList(&pdata);
302        return ret;
303}
304
305LIBSPEC int
306UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
307                    const char * extPort,
308                                        const char * inPort,
309                                        const char * inClient,
310                                        const char * desc,
311                                        const char * proto,
312                    const char * remoteHost)
313{
314        struct UPNParg * AddPortMappingArgs;
315        char buffer[4096];
316        int bufsize = 4096;
317        struct NameValueParserData pdata;
318        const char * resVal;
319        int ret;
320
321        if(!inPort || !inClient || !proto || !extPort)
322                return UPNPCOMMAND_INVALID_ARGS;
323
324        AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
325        AddPortMappingArgs[0].elt = "NewRemoteHost";
326        AddPortMappingArgs[0].val = remoteHost;
327        AddPortMappingArgs[1].elt = "NewExternalPort";
328        AddPortMappingArgs[1].val = extPort;
329        AddPortMappingArgs[2].elt = "NewProtocol";
330        AddPortMappingArgs[2].val = proto;
331        AddPortMappingArgs[3].elt = "NewInternalPort";
332        AddPortMappingArgs[3].val = inPort;
333        AddPortMappingArgs[4].elt = "NewInternalClient";
334        AddPortMappingArgs[4].val = inClient;
335        AddPortMappingArgs[5].elt = "NewEnabled";
336        AddPortMappingArgs[5].val = "1";
337        AddPortMappingArgs[6].elt = "NewPortMappingDescription";
338        AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
339        AddPortMappingArgs[7].elt = "NewLeaseDuration";
340        AddPortMappingArgs[7].val = "0";
341        simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize);
342        /*DisplayNameValueList(buffer, bufsize);*/
343        /*buffer[bufsize] = '\0';*/
344        /*puts(buffer);*/
345        ParseNameValue(buffer, bufsize, &pdata);
346        resVal = GetValueFromNameValueList(&pdata, "errorCode");
347        if(resVal) {
348                /*printf("AddPortMapping errorCode = '%s'\n", resVal); */
349                ret = UPNPCOMMAND_UNKNOWN_ERROR;
350                sscanf(resVal, "%d", &ret);
351        } else {
352                ret = UPNPCOMMAND_SUCCESS;
353        }
354        ClearNameValueList(&pdata);
355        free(AddPortMappingArgs);
356        return ret;
357}
358
359LIBSPEC int
360UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
361                       const char * extPort, const char * proto,
362                       const char * remoteHost)
363{
364        /*struct NameValueParserData pdata;*/
365        struct UPNParg * DeletePortMappingArgs;
366        char buffer[4096];
367        int bufsize = 4096;
368        struct NameValueParserData pdata;
369        const char * resVal;
370        int ret;
371
372        if(!extPort || !proto)
373                return UPNPCOMMAND_INVALID_ARGS;
374
375        DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
376        DeletePortMappingArgs[0].elt = "NewRemoteHost";
377        DeletePortMappingArgs[0].val = remoteHost;
378        DeletePortMappingArgs[1].elt = "NewExternalPort";
379        DeletePortMappingArgs[1].val = extPort;
380        DeletePortMappingArgs[2].elt = "NewProtocol";
381        DeletePortMappingArgs[2].val = proto;
382        simpleUPnPcommand(-1, controlURL, servicetype,
383                          "DeletePortMapping",
384                                          DeletePortMappingArgs, buffer, &bufsize);
385        /*DisplayNameValueList(buffer, bufsize);*/
386        ParseNameValue(buffer, bufsize, &pdata);
387        resVal = GetValueFromNameValueList(&pdata, "errorCode");
388        if(resVal) {
389                ret = UPNPCOMMAND_UNKNOWN_ERROR;
390                sscanf(resVal, "%d", &ret);
391        } else {
392                ret = UPNPCOMMAND_SUCCESS;
393        }
394        ClearNameValueList(&pdata);
395        free(DeletePortMappingArgs);
396        return ret;
397}
398
399LIBSPEC int
400UPNP_GetGenericPortMappingEntry(const char * controlURL,
401                                const char * servicetype,
402                                                         const char * index,
403                                                         char * extPort,
404                                                         char * intClient,
405                                                         char * intPort,
406                                                         char * protocol,
407                                                         char * desc,
408                                                         char * enabled,
409                                                         char * rHost,
410                                                         char * duration)
411{
412        struct NameValueParserData pdata;
413        struct UPNParg * GetPortMappingArgs;
414        char buffer[4096];
415        int bufsize = 4096;
416        char * p;
417        int r = UPNPCOMMAND_UNKNOWN_ERROR;
418        if(!index)
419                return UPNPCOMMAND_INVALID_ARGS;
420        intClient[0] = '\0';
421        intPort[0] = '\0';
422        GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
423        GetPortMappingArgs[0].elt = "NewPortMappingIndex";
424        GetPortMappingArgs[0].val = index;
425        simpleUPnPcommand(-1, controlURL, servicetype,
426                          "GetGenericPortMappingEntry",
427                                          GetPortMappingArgs, buffer, &bufsize);
428        ParseNameValue(buffer, bufsize, &pdata);
429        p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
430        if(p && rHost)
431        {
432                strncpy(rHost, p, 64);
433                rHost[63] = '\0';
434        }
435        p = GetValueFromNameValueList(&pdata, "NewExternalPort");
436        if(p && extPort)
437        {
438                strncpy(extPort, p, 6);
439                extPort[5] = '\0';
440                r = UPNPCOMMAND_SUCCESS;
441        }
442        p = GetValueFromNameValueList(&pdata, "NewProtocol");
443        if(p && protocol)
444        {
445                strncpy(protocol, p, 4);
446                protocol[3] = '\0';
447        }
448        p = GetValueFromNameValueList(&pdata, "NewInternalClient");
449        if(p && intClient)
450        {
451                strncpy(intClient, p, 16);
452                intClient[15] = '\0';
453                r = 0;
454        }
455        p = GetValueFromNameValueList(&pdata, "NewInternalPort");
456        if(p && intPort)
457        {
458                strncpy(intPort, p, 6);
459                intPort[5] = '\0';
460        }
461        p = GetValueFromNameValueList(&pdata, "NewEnabled");
462        if(p && enabled)
463        {
464                strncpy(enabled, p, 4);
465                enabled[3] = '\0';
466        }
467        p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
468        if(p && desc)
469        {
470                strncpy(desc, p, 80);
471                desc[79] = '\0';
472        }
473        p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
474        if(p && duration)
475        {
476                strncpy(duration, p, 16);
477                duration[15] = '\0';
478        }
479        p = GetValueFromNameValueList(&pdata, "errorCode");
480        if(p) {
481                r = UPNPCOMMAND_UNKNOWN_ERROR;
482                sscanf(p, "%d", &r);
483        }
484        ClearNameValueList(&pdata);
485        free(GetPortMappingArgs);
486        return r;
487}
488
489LIBSPEC int
490UPNP_GetPortMappingNumberOfEntries(const char * controlURL,
491                                   const char * servicetype,
492                                   unsigned int * numEntries)
493{
494        struct NameValueParserData pdata;
495        char buffer[4096];
496        int bufsize = 4096;
497        char* p;
498        int ret = UPNPCOMMAND_UNKNOWN_ERROR;
499        simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
500#ifdef DEBUG
501        DisplayNameValueList(buffer, bufsize);
502#endif
503        ParseNameValue(buffer, bufsize, &pdata);
504
505        p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
506        if(numEntries && p) {
507                *numEntries = 0;
508                sscanf(p, "%u", numEntries);
509                ret = UPNPCOMMAND_SUCCESS;
510        }
511
512        p = GetValueFromNameValueList(&pdata, "errorCode");
513        if(p) {
514                ret = UPNPCOMMAND_UNKNOWN_ERROR;
515                sscanf(p, "%d", &ret);
516        }
517
518        ClearNameValueList(&pdata);
519        return ret;
520}
521
522/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
523 * the result is returned in the intClient and intPort strings
524 * please provide 16 and 6 bytes of data */
525LIBSPEC int
526UPNP_GetSpecificPortMappingEntry(const char * controlURL,
527                                 const char * servicetype,
528                                 const char * extPort,
529                                                             const char * proto,
530                                 char * intClient,
531                                 char * intPort)
532{
533        struct NameValueParserData pdata;
534        struct UPNParg * GetPortMappingArgs;
535        char buffer[4096];
536        int bufsize = 4096;
537        char * p;
538        int ret = UPNPCOMMAND_UNKNOWN_ERROR;
539
540        if(!intPort || !intClient || !extPort || !proto)
541                return UPNPCOMMAND_INVALID_ARGS;
542
543        GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
544        GetPortMappingArgs[0].elt = "NewRemoteHost";
545        GetPortMappingArgs[1].elt = "NewExternalPort";
546        GetPortMappingArgs[1].val = extPort;
547        GetPortMappingArgs[2].elt = "NewProtocol";
548        GetPortMappingArgs[2].val = proto;
549        simpleUPnPcommand(-1, controlURL, servicetype,
550                          "GetSpecificPortMappingEntry",
551                                          GetPortMappingArgs, buffer, &bufsize);
552        /*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
553        /*DisplayNameValueList(buffer, bufsize);*/
554        ParseNameValue(buffer, bufsize, &pdata);
555
556        p = GetValueFromNameValueList(&pdata, "NewInternalClient");
557        if(p) {
558                strncpy(intClient, p, 16);
559                intClient[15] = '\0';
560                ret = UPNPCOMMAND_SUCCESS;
561        } else
562                intClient[0] = '\0';
563
564        p = GetValueFromNameValueList(&pdata, "NewInternalPort");
565        if(p) {
566                strncpy(intPort, p, 6);
567                intPort[5] = '\0';
568        } else
569                intPort[0] = '\0';
570
571        p = GetValueFromNameValueList(&pdata, "errorCode");
572        if(p) {
573                ret = UPNPCOMMAND_UNKNOWN_ERROR;
574                sscanf(p, "%d", &ret);
575        }
576
577        ClearNameValueList(&pdata);
578        free(GetPortMappingArgs);
579        return ret;
580}
581
582
Note: See TracBrowser for help on using the repository browser.