Path: blob/master/thirdparty/miniupnpc/src/portlistingparse.c
9904 views
/* $Id: portlistingparse.c,v 1.12 2025/03/29 17:58:33 nanard Exp $ */1/* MiniUPnP project2* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/3* (c) 2011-2025 Thomas Bernard4* This software is subject to the conditions detailed5* in the LICENCE file provided within the distribution */6#include <string.h>7#include <stdlib.h>8#ifdef DEBUG9#include <stdio.h>10#endif /* DEBUG */11#include "portlistingparse.h"12#include "minixml.h"1314#if defined(__HAIKU__)15/* rename our private function because Haiku already defines a atoui() function */16#define atoui atoui217#endif1819/* list of the elements */20static const struct {21const portMappingElt code;22const char * const str;23} elements[] = {24{ PortMappingEntry, "PortMappingEntry"},25{ NewRemoteHost, "NewRemoteHost"},26{ NewExternalPort, "NewExternalPort"},27{ NewProtocol, "NewProtocol"},28{ NewInternalPort, "NewInternalPort"},29{ NewInternalClient, "NewInternalClient"},30{ NewEnabled, "NewEnabled"},31{ NewDescription, "NewDescription"},32{ NewLeaseTime, "NewLeaseTime"},33{ PortMappingEltNone, NULL}34};3536/* Helper function */37static UNSIGNED_INTEGER38atoui(const char * p, int l)39{40UNSIGNED_INTEGER r = 0;41while(l > 0 && *p)42{43if(*p >= '0' && *p <= '9')44r = r*10 + (*p - '0');45else46break;47p++;48l--;49}50return r;51}5253/* Start element handler */54static void55startelt(void * d, const char * name, int l)56{57int i;58struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;59pdata->curelt = PortMappingEltNone;60for(i = 0; elements[i].str; i++)61{62if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0)63{64pdata->curelt = elements[i].code;65break;66}67}68if(pdata->curelt == PortMappingEntry)69{70struct PortMapping * pm;71pm = calloc(1, sizeof(struct PortMapping));72if(pm == NULL)73{74/* malloc error */75#ifdef DEBUG76fprintf(stderr, "%s: error allocating memory",77"startelt");78#endif /* DEBUG */79return;80}81pm->l_next = pdata->l_head; /* insert in list */82pdata->l_head = pm;83}84}8586/* End element handler */87static void88endelt(void * d, const char * name, int l)89{90struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;91(void)name;92(void)l;93pdata->curelt = PortMappingEltNone;94}9596/* Data handler */97static void98data(void * d, const char * data, int l)99{100struct PortMapping * pm;101struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;102pm = pdata->l_head;103if(!pm)104return;105if(l > 63)106l = 63;107switch(pdata->curelt)108{109case NewRemoteHost:110memcpy(pm->remoteHost, data, l);111pm->remoteHost[l] = '\0';112break;113case NewExternalPort:114pm->externalPort = (unsigned short)atoui(data, l);115break;116case NewProtocol:117if(l > 3)118l = 3;119memcpy(pm->protocol, data, l);120pm->protocol[l] = '\0';121break;122case NewInternalPort:123pm->internalPort = (unsigned short)atoui(data, l);124break;125case NewInternalClient:126memcpy(pm->internalClient, data, l);127pm->internalClient[l] = '\0';128break;129case NewEnabled:130pm->enabled = (unsigned char)atoui(data, l);131break;132case NewDescription:133memcpy(pm->description, data, l);134pm->description[l] = '\0';135break;136case NewLeaseTime:137pm->leaseTime = atoui(data, l);138break;139default:140break;141}142}143144145/* Parse the PortMappingList XML document for IGD version 2146*/147void148ParsePortListing(const char * buffer, int bufsize,149struct PortMappingParserData * pdata)150{151struct xmlparser parser;152153memset(pdata, 0, sizeof(struct PortMappingParserData));154/* init xmlparser */155parser.xmlstart = buffer;156parser.xmlsize = bufsize;157parser.data = pdata;158parser.starteltfunc = startelt;159parser.endeltfunc = endelt;160parser.datafunc = data;161parser.attfunc = 0;162parsexml(&parser);163}164165void166FreePortListing(struct PortMappingParserData * pdata)167{168struct PortMapping * pm;169while((pm = pdata->l_head) != NULL)170{171/* remove from list */172pdata->l_head = pm->l_next;173free(pm);174}175}176177178179