/user/ser/parser/digest/param_parser.c

https://github.com/rhuitl/uClinux · C · 232 lines · 157 code · 38 blank · 37 comment · 34 complexity · 0f9244af9bb329c59de1601d32ac897e MD5 · raw file

  1. /*
  2. * $Id: param_parser.c,v 1.5 2004/08/24 09:01:29 janakj Exp $
  3. *
  4. * 32-bit Digest parameter name parser
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * info@iptel.org
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28. */
  29. #include "param_parser.h"
  30. #include "digest_keys.h"
  31. #include "../../trim.h"
  32. #include "../../ut.h"
  33. #define LOWER_BYTE(b) ((b) | 0x20)
  34. #define LOWER_DWORD(d) ((d) | 0x20202020)
  35. /*
  36. * Parse short (less than 4 bytes) parameter names
  37. */
  38. #define PARSE_SHORT \
  39. switch(LOWER_BYTE(*p)) { \
  40. case 'u': \
  41. if (LOWER_BYTE(*(p + 1)) == 'r') { \
  42. if (LOWER_BYTE(*(p + 2)) == 'i') { \
  43. *_type = PAR_URI; \
  44. p += 3; \
  45. goto end; \
  46. } \
  47. } \
  48. break; \
  49. \
  50. case 'q': \
  51. if (LOWER_BYTE(*(p + 1)) == 'o') { \
  52. if (LOWER_BYTE(*(p + 2)) == 'p') { \
  53. *_type = PAR_QOP; \
  54. p += 3; \
  55. goto end; \
  56. } \
  57. } \
  58. break; \
  59. \
  60. case 'n': \
  61. if (LOWER_BYTE(*(p + 1)) == 'c') { \
  62. *_type = PAR_NC; \
  63. p += 2; \
  64. goto end; \
  65. } \
  66. break; \
  67. }
  68. /*
  69. * Read 4-bytes from memory and store them in an integer variable
  70. * Reading byte by byte ensures, that the code works also on HW which
  71. * does not allow reading 4-bytes at once from unaligned memory position
  72. * (Sparc for example)
  73. */
  74. #define READ(val) \
  75. (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
  76. #define name_CASE \
  77. switch(LOWER_DWORD(val)) { \
  78. case _name_: \
  79. *_type = PAR_USERNAME; \
  80. p += 4; \
  81. goto end; \
  82. }
  83. #define user_CASE \
  84. p += 4; \
  85. val = READ(p); \
  86. name_CASE; \
  87. goto other;
  88. #define real_CASE \
  89. p += 4; \
  90. if (LOWER_BYTE(*p) == 'm') { \
  91. *_type = PAR_REALM; \
  92. p++; \
  93. goto end; \
  94. }
  95. #define nonc_CASE \
  96. p += 4; \
  97. if (LOWER_BYTE(*p) == 'e') { \
  98. *_type = PAR_NONCE; \
  99. p++; \
  100. goto end; \
  101. }
  102. #define onse_CASE \
  103. switch(LOWER_DWORD(val)) { \
  104. case _onse_: \
  105. *_type = PAR_RESPONSE; \
  106. p += 4; \
  107. goto end; \
  108. }
  109. #define resp_CASE \
  110. p += 4; \
  111. val = READ(p); \
  112. onse_CASE; \
  113. goto other;
  114. #define cnon_CASE \
  115. p += 4; \
  116. if (LOWER_BYTE(*p) == 'c') { \
  117. p++; \
  118. if (LOWER_BYTE(*p) == 'e') { \
  119. *_type = PAR_CNONCE; \
  120. p++; \
  121. goto end; \
  122. } \
  123. } \
  124. goto other;
  125. #define opaq_CASE \
  126. p += 4; \
  127. if (LOWER_BYTE(*p) == 'u') { \
  128. p++; \
  129. if (LOWER_BYTE(*p) == 'e') { \
  130. *_type = PAR_OPAQUE; \
  131. p++; \
  132. goto end; \
  133. } \
  134. } \
  135. goto other;
  136. #define rith_CASE \
  137. switch(LOWER_DWORD(val)) { \
  138. case _rith_: \
  139. p += 4; \
  140. if (LOWER_BYTE(*p) == 'm') { \
  141. *_type = PAR_ALGORITHM; \
  142. p++; \
  143. goto end; \
  144. } \
  145. goto other; \
  146. }
  147. #define algo_CASE \
  148. p += 4; \
  149. val = READ(p); \
  150. rith_CASE; \
  151. goto other
  152. #define FIRST_QUATERNIONS \
  153. case _user_: user_CASE; \
  154. case _real_: real_CASE; \
  155. case _nonc_: nonc_CASE; \
  156. case _resp_: resp_CASE; \
  157. case _cnon_: cnon_CASE; \
  158. case _opaq_: opaq_CASE; \
  159. case _algo_: algo_CASE;
  160. int parse_param_name(str* _s, dig_par_t* _type)
  161. {
  162. register char* p;
  163. register int val;
  164. char* end;
  165. end = _s->s + _s->len;
  166. p = _s->s;
  167. val = READ(p);
  168. if (_s->len < 4) {
  169. goto other;
  170. }
  171. switch(LOWER_DWORD(val)) {
  172. FIRST_QUATERNIONS;
  173. default:
  174. PARSE_SHORT;
  175. goto other;
  176. }
  177. end:
  178. _s->len -= p - _s->s;
  179. _s->s = p;
  180. trim_leading(_s);
  181. if (_s->s[0] == '=') {
  182. return 0;
  183. }
  184. other:
  185. p = q_memchr(p, '=', end - p);
  186. if (!p) {
  187. return -1; /* Parse error */
  188. } else {
  189. *_type = PAR_OTHER;
  190. _s->len -= p - _s->s;
  191. _s->s = p;
  192. return 0;
  193. }
  194. }