ipv4_opt.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*=============================================================================
  2. Copyright (c) 2002-2003 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #include <boost/spirit/include/classic_core.hpp>
  9. #include <boost/spirit/include/classic_push_back_actor.hpp>
  10. #include <boost/spirit/include/classic_if.hpp>
  11. #include <boost/spirit/include/classic_for.hpp>
  12. #include <boost/spirit/include/phoenix1.hpp>
  13. #include <iostream>
  14. #include <string>
  15. #include <vector>
  16. #include <algorithm>
  17. ///////////////////////////////////////////////////////////////////////////////
  18. //
  19. // Please check it out ipv4.cpp sample first!
  20. // << See ipv4.cpp sample for details >>
  21. //
  22. // This is a variation of the ipv4.cpp sample. The original ipv4.cpp code
  23. // compiles to 36k on MSVC7.1. Not bad! Yet, we want to shave a little bit
  24. // more. Is it possible? Yes! This time, we'll use subrules and just store
  25. // the rules in a plain old struct. We are parsing at the char level anyway,
  26. // so we know what type of rule we'll need: a plain rule<>. The result: we
  27. // shaved off another 20k. Now the code compiles to 16k on MSVC7.1.
  28. //
  29. // Could we have done better? Yes, but only if only we had typeof! << See
  30. // the techniques section of the User's guide >> ... Someday... :-)
  31. //
  32. ///////////////////////////////////////////////////////////////////////////////
  33. using namespace std;
  34. using namespace BOOST_SPIRIT_CLASSIC_NS;
  35. using namespace phoenix;
  36. struct ipv4_prefix_data
  37. {
  38. char prefix_len, n0, n1, n2, n3;
  39. ipv4_prefix_data()
  40. : prefix_len(0),n0(0),n1(0),n2(0),n3(0) {}
  41. };
  42. struct ipv4_data
  43. {
  44. char packet_len, header_len;
  45. std::string header;
  46. std::vector<ipv4_prefix_data> prefixes;
  47. ipv4_data()
  48. : packet_len(0),header_len(0){}
  49. };
  50. struct ipv4
  51. {
  52. ipv4(ipv4_data& data)
  53. : data(data)
  54. {
  55. start =
  56. (
  57. packet =
  58. '\xff'
  59. >> anychar_p[var(data.packet_len) = arg1]
  60. >> payload
  61. ,
  62. payload =
  63. anychar_p[var(data.header_len) = arg1]
  64. >> for_p(var(i) = 0, var(i) < var(data.header_len), ++var(i))
  65. [
  66. anychar_p[var(data.header) += arg1]
  67. ]
  68. >> *ipv4_prefix
  69. ,
  70. ipv4_prefix =
  71. anychar_p
  72. [
  73. var(temp.prefix_len) = arg1,
  74. var(temp.n0) = 0,
  75. var(temp.n1) = 0,
  76. var(temp.n2) = 0,
  77. var(temp.n3) = 0
  78. ]
  79. >> if_p(var(temp.prefix_len) > 0x00)
  80. [
  81. anychar_p[var(temp.n0) = arg1]
  82. >> if_p(var(temp.prefix_len) > 0x08)
  83. [
  84. anychar_p[var(temp.n1) = arg1]
  85. >> if_p(var(temp.prefix_len) > 0x10)
  86. [
  87. anychar_p[var(temp.n2) = arg1]
  88. >> if_p(var(temp.prefix_len) > 0x18)
  89. [
  90. anychar_p[var(temp.n3) = arg1]
  91. ]
  92. ]
  93. ]
  94. ]
  95. [
  96. push_back_a(data.prefixes, temp)
  97. ]
  98. );
  99. }
  100. int i;
  101. ipv4_prefix_data temp;
  102. rule<> start;
  103. subrule<0> packet;
  104. subrule<1> payload;
  105. subrule<2> ipv4_prefix;
  106. ipv4_data& data;
  107. };
  108. ////////////////////////////////////////////////////////////////////////////
  109. //
  110. // Main program
  111. //
  112. ////////////////////////////////////////////////////////////////////////////
  113. int
  114. as_byte(char n)
  115. {
  116. if (n < 0)
  117. return n + 256;
  118. return n;
  119. }
  120. void
  121. print_prefix(ipv4_prefix_data const& prefix)
  122. {
  123. cout << "prefix length = " << as_byte(prefix.prefix_len) << endl;
  124. cout << "n0 = " << as_byte(prefix.n0) << endl;
  125. cout << "n1 = " << as_byte(prefix.n1) << endl;
  126. cout << "n2 = " << as_byte(prefix.n2) << endl;
  127. cout << "n3 = " << as_byte(prefix.n3) << endl;
  128. }
  129. void
  130. parse_ipv4(char const* str, unsigned len)
  131. {
  132. ipv4_data data;
  133. ipv4 g(data);
  134. parse_info<> info = parse(str, str+len, g.start);
  135. if (info.full)
  136. {
  137. cout << "-------------------------\n";
  138. cout << "Parsing succeeded\n";
  139. cout << "packet length = " << as_byte(data.packet_len) << endl;
  140. cout << "header length = " << as_byte(data.header_len) << endl;
  141. cout << "header = " << data.header << endl;
  142. for_each(data.prefixes.begin(), data.prefixes.end(), print_prefix);
  143. cout << "-------------------------\n";
  144. }
  145. else
  146. {
  147. cout << "Parsing failed\n";
  148. cout << "stopped at:";
  149. for (char const* s = info.stop; s != str+len; ++s)
  150. cout << static_cast<int>(*s) << endl;
  151. }
  152. }
  153. // Test inputs:
  154. // The string in the header is "empty", the prefix list is empty.
  155. char const i1[8] =
  156. {
  157. 0xff,0x08,0x05,
  158. 'e','m','p','t','y'
  159. };
  160. // The string in the header is "default route", the prefix list
  161. // has just one element, 0.0.0.0/0.
  162. char const i2[17] =
  163. {
  164. 0xff,0x11,0x0d,
  165. 'd','e','f','a','u','l','t',' ',
  166. 'r','o','u','t','e',
  167. 0x00
  168. };
  169. // The string in the header is "private address space", the prefix list
  170. // has the elements 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
  171. char const i3[32] =
  172. {
  173. 0xff,0x20,0x15,
  174. 'p','r','i','v','a','t','e',' ',
  175. 'a','d','d','r','e','s','s',' ',
  176. 's','p','a','c','e',
  177. 0x08,0x0a,
  178. 0x0c,0xac,0x10,
  179. 0x10,0xc0,0xa8
  180. };
  181. int
  182. main()
  183. {
  184. parse_ipv4(i1, sizeof(i1));
  185. parse_ipv4(i2, sizeof(i2));
  186. parse_ipv4(i3, sizeof(i3));
  187. return 0;
  188. }