portlistingparse.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */
  2. /* MiniUPnP project
  3. * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
  4. * (c) 2011-2016 Thomas Bernard
  5. * This software is subject to the conditions detailed
  6. * in the LICENCE file provided within the distribution */
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #ifdef DEBUG
  10. #include <stdio.h>
  11. #endif /* DEBUG */
  12. #include "portlistingparse.h"
  13. #include "minixml.h"
  14. /* list of the elements */
  15. static const struct {
  16. const portMappingElt code;
  17. const char * const str;
  18. } elements[] = {
  19. { PortMappingEntry, "PortMappingEntry"},
  20. { NewRemoteHost, "NewRemoteHost"},
  21. { NewExternalPort, "NewExternalPort"},
  22. { NewProtocol, "NewProtocol"},
  23. { NewInternalPort, "NewInternalPort"},
  24. { NewInternalClient, "NewInternalClient"},
  25. { NewEnabled, "NewEnabled"},
  26. { NewDescription, "NewDescription"},
  27. { NewLeaseTime, "NewLeaseTime"},
  28. { PortMappingEltNone, NULL}
  29. };
  30. /* Helper function */
  31. static UNSIGNED_INTEGER
  32. atoui(const char * p, int l)
  33. {
  34. UNSIGNED_INTEGER r = 0;
  35. while(l > 0 && *p)
  36. {
  37. if(*p >= '0' && *p <= '9')
  38. r = r*10 + (*p - '0');
  39. else
  40. break;
  41. p++;
  42. l--;
  43. }
  44. return r;
  45. }
  46. /* Start element handler */
  47. static void
  48. startelt(void * d, const char * name, int l)
  49. {
  50. int i;
  51. struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
  52. pdata->curelt = PortMappingEltNone;
  53. for(i = 0; elements[i].str; i++)
  54. {
  55. if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0)
  56. {
  57. pdata->curelt = elements[i].code;
  58. break;
  59. }
  60. }
  61. if(pdata->curelt == PortMappingEntry)
  62. {
  63. struct PortMapping * pm;
  64. pm = calloc(1, sizeof(struct PortMapping));
  65. if(pm == NULL)
  66. {
  67. /* malloc error */
  68. #ifdef DEBUG
  69. fprintf(stderr, "%s: error allocating memory",
  70. "startelt");
  71. #endif /* DEBUG */
  72. return;
  73. }
  74. pm->l_next = pdata->l_head; /* insert in list */
  75. pdata->l_head = pm;
  76. }
  77. }
  78. /* End element handler */
  79. static void
  80. endelt(void * d, const char * name, int l)
  81. {
  82. struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
  83. (void)name;
  84. (void)l;
  85. pdata->curelt = PortMappingEltNone;
  86. }
  87. /* Data handler */
  88. static void
  89. data(void * d, const char * data, int l)
  90. {
  91. struct PortMapping * pm;
  92. struct PortMappingParserData * pdata = (struct PortMappingParserData *)d;
  93. pm = pdata->l_head;
  94. if(!pm)
  95. return;
  96. if(l > 63)
  97. l = 63;
  98. switch(pdata->curelt)
  99. {
  100. case NewRemoteHost:
  101. memcpy(pm->remoteHost, data, l);
  102. pm->remoteHost[l] = '\0';
  103. break;
  104. case NewExternalPort:
  105. pm->externalPort = (unsigned short)atoui(data, l);
  106. break;
  107. case NewProtocol:
  108. if(l > 3)
  109. l = 3;
  110. memcpy(pm->protocol, data, l);
  111. pm->protocol[l] = '\0';
  112. break;
  113. case NewInternalPort:
  114. pm->internalPort = (unsigned short)atoui(data, l);
  115. break;
  116. case NewInternalClient:
  117. memcpy(pm->internalClient, data, l);
  118. pm->internalClient[l] = '\0';
  119. break;
  120. case NewEnabled:
  121. pm->enabled = (unsigned char)atoui(data, l);
  122. break;
  123. case NewDescription:
  124. memcpy(pm->description, data, l);
  125. pm->description[l] = '\0';
  126. break;
  127. case NewLeaseTime:
  128. pm->leaseTime = atoui(data, l);
  129. break;
  130. default:
  131. break;
  132. }
  133. }
  134. /* Parse the PortMappingList XML document for IGD version 2
  135. */
  136. void
  137. ParsePortListing(const char * buffer, int bufsize,
  138. struct PortMappingParserData * pdata)
  139. {
  140. struct xmlparser parser;
  141. memset(pdata, 0, sizeof(struct PortMappingParserData));
  142. /* init xmlparser */
  143. parser.xmlstart = buffer;
  144. parser.xmlsize = bufsize;
  145. parser.data = pdata;
  146. parser.starteltfunc = startelt;
  147. parser.endeltfunc = endelt;
  148. parser.datafunc = data;
  149. parser.attfunc = 0;
  150. parsexml(&parser);
  151. }
  152. void
  153. FreePortListing(struct PortMappingParserData * pdata)
  154. {
  155. struct PortMapping * pm;
  156. while((pm = pdata->l_head) != NULL)
  157. {
  158. /* remove from list */
  159. pdata->l_head = pm->l_next;
  160. free(pm);
  161. }
  162. }