pibruin1.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * pibruin.c - Qualcomm Atheros Classification Rule Insert Utility;
  11. *
  12. * This inserts classification rules into pib files from a rule
  13. * description file;
  14. *
  15. * Contributor(s):
  16. * Nathaniel Houghton <nhoughto@qca.qualcomm.com>
  17. *
  18. *--------------------------------------------------------------------*/
  19. /*====================================================================*
  20. * system header files;
  21. *--------------------------------------------------------------------*/
  22. #include <ctype.h>
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include <netinet/in.h>
  28. #include <arpa/inet.h>
  29. /*====================================================================*
  30. * custom header files;
  31. *--------------------------------------------------------------------*/
  32. #include "../tools/getoptv.h"
  33. #include "../tools/memory.h"
  34. #include "../tools/number.h"
  35. #include "../tools/symbol.h"
  36. #include "../tools/types.h"
  37. #include "../tools/flags.h"
  38. #include "../tools/files.h"
  39. #include "../tools/error.h"
  40. #include "../plc/rules.h"
  41. #include "../pib/pib.h"
  42. /*====================================================================*
  43. * custom source files;
  44. *--------------------------------------------------------------------*/
  45. #ifndef MAKEFILE
  46. #include "../tools/getoptv.c"
  47. #include "../tools/putoptv.c"
  48. #include "../tools/version.c"
  49. #include "../tools/lookup.c"
  50. #include "../tools/reword.c"
  51. #include "../tools/hexstring.c"
  52. #include "../tools/hexdecode.c"
  53. #include "../tools/fdchecksum32.c"
  54. #include "../tools/memout.c"
  55. #include "../tools/assist.c"
  56. #include "../tools/bytespec.c"
  57. #include "../tools/basespec.c"
  58. #include "../tools/ipv4spec.c"
  59. #include "../tools/ipv6spec.c"
  60. #include "../tools/endian.c"
  61. #include "../tools/emalloc.c"
  62. #include "../tools/todigit.c"
  63. #include "../tools/codelist.c"
  64. #include "../tools/error.c"
  65. #endif
  66. #ifndef MAKEFILE
  67. #include "../pib/lightning_pib_file.c"
  68. #include "../pib/lightning_pib_lock.c"
  69. #endif
  70. #ifndef MAKEFILE
  71. #include "../plc/rules.c"
  72. #include "../plc/ParseRule.c"
  73. #endif
  74. /*====================================================================*
  75. * program variables;
  76. *--------------------------------------------------------------------*/
  77. #ifndef __GNUC__
  78. #pragma pack (push,1)
  79. #endif
  80. typedef struct __packed classifier_pib
  81. {
  82. uint32_t CR_PID;
  83. uint32_t CR_OPERAND;
  84. uint8_t CR_VALUE [16];
  85. }
  86. classifier_pib;
  87. struct __packed auto_connection
  88. {
  89. uint8_t MACTION;
  90. uint8_t MOPERAND;
  91. uint16_t NUM_CLASSIFIERS;
  92. struct classifier_pib CLASSIFIER [3];
  93. struct cspec cspec;
  94. uint8_t RSVD [14];
  95. }
  96. auto_connection;
  97. struct __packed classifier_priority_map
  98. {
  99. uint32_t Priority;
  100. struct classifier_pib CLASSIFIER;
  101. }
  102. classifier_priority_map;
  103. #ifndef __GNUC__
  104. #pragma pack (pop)
  105. #endif
  106. /*====================================================================*
  107. * program constants;
  108. *--------------------------------------------------------------------*/
  109. #define PIB_MAX_AUTOCONN 16
  110. #define PIB_MAX_PRIORITY_MAPS 8
  111. #define PIB_AUTOCONN_COUNT_OFFSET 0x22C
  112. #define PIB_PRIORITY_COUNT_OFFSET 0x228
  113. #define PIB_AUTOCONN_OFFSET 0x310
  114. #define PIB_PRIORITY_MAPS_OFFSET 0x230
  115. /*====================================================================*
  116. *
  117. * signed handle_rule (char * str, int argc, struct auto_connection * autoconn, struct classifier_priority_map * priority_map, int * autoconn_count, int * priority_count);
  118. *
  119. *--------------------------------------------------------------------*/
  120. static signed handle_rule (char * str, int argc, struct auto_connection * autoconn, struct classifier_priority_map * priority_map, int * autoconn_count, int * priority_count)
  121. {
  122. char const ** argv;
  123. char ** mem;
  124. unsigned i;
  125. signed c;
  126. size_t len;
  127. struct rule rule;
  128. struct cspec cspec;
  129. static char const * optv [] =
  130. {
  131. "T:V:",
  132. "",
  133. "Qualcomm Atheros Classification Rule Insert Utility",
  134. "T\ttag",
  135. "V\tversion",
  136. (char const *) (0)
  137. };
  138. extern char const * program_name;
  139. mem = emalloc ((argc + 2) * sizeof (char *));
  140. argv = (char const **) (mem);
  141. * argv = program_name;
  142. ++ argv;
  143. * argv = str;
  144. ++ argv;
  145. len = strlen (str);
  146. for (i = 1; i < len; ++ i)
  147. {
  148. if (str [i] == ' ')
  149. {
  150. str [i] = '\0';
  151. * argv = & str [i + 1];
  152. ++ argv;
  153. }
  154. }
  155. * argv = NULL;
  156. optind = 1;
  157. argv = (char const **) (mem);
  158. memset (& rule, 0, sizeof (rule));
  159. memset (& cspec, 0, sizeof (cspec));
  160. while (~ (c = getoptv (argc, (char const **) (argv), optv)))
  161. {
  162. switch ((char) (c))
  163. {
  164. case 'T':
  165. cspec.VLAN_TAG = (uint32_t) (basespec (optarg, 16, sizeof (cspec.VLAN_TAG)));
  166. cspec.VLAN_TAG = htonl (cspec.VLAN_TAG);
  167. break;
  168. case 'V':
  169. cspec.CSPEC_VERSION = (uint16_t) (basespec (optarg, 10, sizeof (cspec.CSPEC_VERSION)));
  170. break;
  171. default:
  172. break;
  173. }
  174. }
  175. argc -= optind;
  176. argv += optind;
  177. ParseRule (& argc, (char const ** *) & argv, & rule, & cspec);
  178. /* Now migrate the rule into the correct PIB structure. */
  179. if (rule.NUM_CLASSIFIERS > 1 || rule.MACTION == ACTION_STRIPTX || rule.MACTION == ACTION_STRIPRX || rule.MACTION == ACTION_TAGTX || * priority_count >= PIB_MAX_PRIORITY_MAPS)
  180. {
  181. if (* autoconn_count >= PIB_MAX_AUTOCONN)
  182. {
  183. error (1, 0, "too many rules");
  184. }
  185. autoconn = & autoconn [* autoconn_count];
  186. autoconn->CLASSIFIER [0].CR_PID = 0xFF;
  187. autoconn->CLASSIFIER [1].CR_PID = 0xFF;
  188. autoconn->CLASSIFIER [2].CR_PID = 0xFF;
  189. autoconn->MACTION = rule.MACTION;
  190. autoconn->MOPERAND = rule.MOPERAND;
  191. autoconn->NUM_CLASSIFIERS = rule.NUM_CLASSIFIERS;
  192. for (i = 0; i < rule.NUM_CLASSIFIERS; ++ i)
  193. {
  194. autoconn->CLASSIFIER [i].CR_PID = rule.CLASSIFIER [i].CR_PID;
  195. autoconn->CLASSIFIER [i].CR_OPERAND = rule.CLASSIFIER [i].CR_OPERAND;
  196. memcpy (& autoconn->CLASSIFIER [i].CR_VALUE, & rule.CLASSIFIER [i].CR_VALUE, sizeof (autoconn->CLASSIFIER [i].CR_VALUE));
  197. }
  198. memcpy (& autoconn->cspec, & rule.cspec, sizeof (autoconn->cspec));
  199. ++ (* autoconn_count);
  200. }
  201. else
  202. {
  203. if (* priority_count >= PIB_MAX_PRIORITY_MAPS)
  204. {
  205. error (1, 0, "too many rules");
  206. }
  207. priority_map = & priority_map [* priority_count];
  208. priority_map->Priority = rule.MACTION;
  209. priority_map->CLASSIFIER.CR_PID = rule.CLASSIFIER [0].CR_PID;
  210. priority_map->CLASSIFIER.CR_OPERAND = rule.CLASSIFIER [0].CR_OPERAND;
  211. memcpy (& priority_map->CLASSIFIER.CR_VALUE, & rule.CLASSIFIER [0].CR_VALUE, sizeof (priority_map->CLASSIFIER.CR_VALUE));
  212. ++ (* priority_count);
  213. }
  214. free (mem);
  215. return (0);
  216. }
  217. static void read_rules (struct auto_connection auto_connection [], unsigned * autoconn_count, struct classifier_priority_map classifier_priority_map [], unsigned * priority_count)
  218. {
  219. int len = 0;
  220. int wc = 0;
  221. while ((c = getc (stdin)) != EOF)
  222. {
  223. if (isspace (c))
  224. {
  225. continue;
  226. }
  227. if (c == '#')
  228. {
  229. do
  230. {
  231. c = getc (stdin);
  232. }
  233. while (nobreak (c));
  234. continue;
  235. }
  236. len = 0;
  237. wc = 0;
  238. do
  239. {
  240. if (isspace (c))
  241. {
  242. while (c != '\n' && (c = getc (stdin)) != EOF && isspace (c))
  243. {
  244. continue;
  245. }
  246. if (len > 0)
  247. {
  248. ++ wc;
  249. }
  250. if (c != '\n' && c != '#')
  251. {
  252. line [len++] = ' ';
  253. if (len == sizeof (line) - 1)
  254. {
  255. error (1, 0, "rule too long");
  256. }
  257. }
  258. }
  259. if (c == '\n' || c == '#')
  260. {
  261. line [len] = '\0';
  262. handle_rule (line, wc, auto_connection, classifier_priority_map, autoconn_count, priority_count);
  263. len = 0;
  264. wc = 0;
  265. if (c == '#')
  266. {
  267. ungetc (c, stdin);
  268. }
  269. break;
  270. }
  271. line [len++] = c;
  272. if (len == sizeof (line) - 1)
  273. {
  274. error (1, 0, "rule too long");
  275. }
  276. }
  277. while ((c = getc (stdin)) != EOF);
  278. }
  279. if (len > 0)
  280. {
  281. line [len] = '\0';
  282. handle_rule (line, wc, auto_connection, classifier_priority_map, autoconn_count, priority_count);
  283. }
  284. }
  285. /*====================================================================*
  286. *
  287. * int main (int argc, char const * argv[]);
  288. *
  289. *
  290. *--------------------------------------------------------------------*/
  291. int main (int argc, char const * argv [])
  292. {
  293. static char const * optv [] =
  294. {
  295. "eqv",
  296. "pibfile < rules",
  297. "Qualcomm Atheros Classification Rule Insert Utility",
  298. "e\tredirect stderr messages to stdout",
  299. "q\tquiet mode",
  300. "v\tverbose mode",
  301. (char const *) (0)
  302. };
  303. struct auto_connection auto_connection [PIB_MAX_AUTOCONN];
  304. struct classifier_priority_map classifier_priority_map [PIB_MAX_PRIORITY_MAPS];
  305. unsigned autoconn_count = 0;
  306. unsigned priority_count = 0;
  307. flag_t flags = (flag_t) (0);
  308. struct _file_ pib;
  309. char line [1024];
  310. signed c;
  311. optind = 1;
  312. while (~ (c = getoptv (argc, argv, optv)))
  313. {
  314. switch ((char) (c))
  315. {
  316. case 'e':
  317. dup2 (STDOUT_FILENO, STDERR_FILENO);
  318. break;
  319. case 'q':
  320. _setbits (flags, PIB_SILENCE);
  321. break;
  322. case 'v':
  323. _setbits (flags, PIB_VERBOSE);
  324. break;
  325. default:
  326. break;
  327. }
  328. }
  329. argc -= optind;
  330. argv += optind;
  331. if (! argc)
  332. {
  333. error (1, 0, "must specify PIB file");
  334. }
  335. memset (& auto_connection, 0, sizeof (auto_connection));
  336. memset (& classifier_priority_map, 0, sizeof (classifier_priority_map));
  337. read_rules (auto_connection, & autoconn_count, classifier_priority_map, & priority_count);
  338. pib.name = * argv;
  339. if ((pib.file = open (pib.name, O_BINARY | O_RDWR, FILE_FILEMODE)) == - 1)
  340. {
  341. error (1, errno, "%s", pib.name);
  342. }
  343. if (lightning_pib_file (& pib))
  344. {
  345. error (1, errno, "Bad PIB file: %s", pib.name);
  346. }
  347. if (lseek (pib.file, PIB_AUTOCONN_OFFSET, SEEK_SET) != PIB_AUTOCONN_OFFSET)
  348. {
  349. error (1, errno, "could not seek to AutoConnections");
  350. }
  351. if (write (pib.file, & auto_connection, sizeof (auto_connection)) != sizeof (auto_connection))
  352. {
  353. error (1, errno, "could not write AutoConnections");
  354. }
  355. if (lseek (pib.file, PIB_AUTOCONN_COUNT_OFFSET, SEEK_SET) != PIB_AUTOCONN_COUNT_OFFSET)
  356. {
  357. error (1, errno, "could not seek to AutoConnection count");
  358. }
  359. if (write (pib.file, & autoconn_count, sizeof (autoconn_count)) != sizeof (autoconn_count))
  360. {
  361. error (1, errno, "could not write AutoConnection count");
  362. }
  363. if (lseek (pib.file, PIB_PRIORITY_MAPS_OFFSET, SEEK_SET) != PIB_PRIORITY_MAPS_OFFSET)
  364. {
  365. error (1, errno, "could not seek to Priority Map");
  366. }
  367. if (write (pib.file, & classifier_priority_map, sizeof (classifier_priority_map)) != sizeof (classifier_priority_map))
  368. {
  369. error (1, errno, "could not write Priority Map");
  370. }
  371. if (lseek (pib.file, PIB_PRIORITY_COUNT_OFFSET, SEEK_SET) != PIB_PRIORITY_COUNT_OFFSET)
  372. {
  373. error (1, errno, "could not seek to PriorityMaps count");
  374. }
  375. if (write (pib.file, & priority_count, sizeof (priority_count)) != sizeof (priority_count))
  376. {
  377. error (1, errno, "could not write PriorityMaps count");
  378. }
  379. piblock (& pib);
  380. close (pib.file);
  381. exit (0);
  382. }