plcfwd.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or
  8. * without modification, are permitted (subject to the limitations
  9. * in the disclaimer below) provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer in the documentation and/or other materials
  18. * provided with the distribution.
  19. *
  20. * * Neither the name of Qualcomm Atheros nor the names of
  21. * its contributors may be used to endorse or promote products
  22. * derived from this software without specific prior written
  23. * permission.
  24. *
  25. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  26. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
  27. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  28. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  29. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  31. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  37. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. *--------------------------------------------------------------------*/
  41. /*====================================================================*
  42. *
  43. * plcfwd.c - Atheros PLC Forward Configuration Manager;
  44. *
  45. *
  46. *--------------------------------------------------------------------*/
  47. /*====================================================================*"
  48. * system header files;
  49. *--------------------------------------------------------------------*/
  50. #include <unistd.h>
  51. #include <stdlib.h>
  52. #include <stdint.h>
  53. #include <limits.h>
  54. #include <ctype.h>
  55. /*====================================================================*
  56. * custom header files;
  57. *--------------------------------------------------------------------*/
  58. #include "../tools/getoptv.h"
  59. #include "../tools/putoptv.h"
  60. #include "../tools/memory.h"
  61. #include "../tools/number.h"
  62. #include "../tools/symbol.h"
  63. #include "../tools/types.h"
  64. #include "../tools/flags.h"
  65. #include "../tools/files.h"
  66. #include "../tools/error.h"
  67. #include "../plc/plc.h"
  68. /*====================================================================*
  69. * custom source files;
  70. *--------------------------------------------------------------------*/
  71. #ifndef MAKEFILE
  72. #include "../plc/Confirm.c"
  73. #include "../plc/Display.c"
  74. #include "../plc/Failure.c"
  75. #include "../plc/Request.c"
  76. #include "../plc/ReadMME.c"
  77. #include "../plc/SendMME.c"
  78. #include "../plc/Devices.c"
  79. #endif
  80. #ifndef MAKEFILE
  81. #include "../tools/getoptv.c"
  82. #include "../tools/putoptv.c"
  83. #include "../tools/version.c"
  84. #include "../tools/uintspec.c"
  85. #include "../tools/basespec.c"
  86. #include "../tools/hexdump.c"
  87. #include "../tools/hexview.c"
  88. #include "../tools/hexencode.c"
  89. #include "../tools/hexdecode.c"
  90. #include "../tools/hexout.c"
  91. #include "../tools/todigit.c"
  92. #include "../tools/synonym.c"
  93. #include "../tools/binout.c"
  94. #include "../tools/error.c"
  95. #endif
  96. #ifndef MAKEFILE
  97. #include "../ether/openchannel.c"
  98. #include "../ether/closechannel.c"
  99. #include "../ether/readpacket.c"
  100. #include "../ether/sendpacket.c"
  101. #include "../ether/channel.c"
  102. #endif
  103. #ifndef MAKEFILE
  104. #include "../mme/MMECode.c"
  105. #include "../mme/EthernetHeader.c"
  106. #include "../mme/QualcommHeader.c"
  107. #include "../mme/UnwantedMessage.c"
  108. #endif
  109. /*====================================================================*
  110. * program constants;
  111. *--------------------------------------------------------------------*/
  112. #define PLCFWD_VERBOSE (1 << 0)
  113. #define PLCFWD_SILENCE (1 << 1)
  114. #define PLCFWD_LENGTH 0
  115. #define PLCFWD_OFFSET 0
  116. #define PLCFWD_GET 0
  117. #define PLCFWD_ADD 1
  118. #define PLCFWD_REM 2
  119. #define PLCFWD_STO 3
  120. #define PLCFWD_CTL 4
  121. #define PLCFWD_SET 5
  122. #define PLCFWD_FWD 6
  123. #define PLCFWD_VER 0
  124. /*====================================================================*
  125. * program variables;
  126. *--------------------------------------------------------------------*/
  127. /*
  128. * this structure is only used in the VS_FORWARD_CONFIG message but
  129. * it is common to several variations of the message and is used in
  130. * arrays;
  131. */
  132. #ifndef __GNUC__
  133. #pragma pack (push,1)
  134. #endif
  135. typedef struct item
  136. {
  137. uint8_t MAC_ADDR [ETHER_ADDR_LEN];
  138. uint16_t NUM_VLANIDS;
  139. uint16_t VLANID [10];
  140. }
  141. item;
  142. #ifndef __GNUC__
  143. #pragma pack (pop)
  144. #endif
  145. /*
  146. * synonym table for options -M and -S;
  147. */
  148. #define STATES (sizeof (states) / sizeof (struct _term_))
  149. static const struct _term_ states [] =
  150. {
  151. {
  152. "disable",
  153. "0"
  154. },
  155. {
  156. "enable",
  157. "1"
  158. },
  159. {
  160. "off",
  161. "0"
  162. },
  163. {
  164. "on",
  165. "1"
  166. }
  167. };
  168. /*====================================================================*
  169. *
  170. * void readitem (struct item * item, char const * string);
  171. *
  172. * encode a slave structure with infomation specified by a string
  173. * specification has the following production:
  174. *
  175. * <spec> := <mac_addr>
  176. * <spec> := <spec>,<vlan_id>
  177. *
  178. * basically, encode slave->MAC_ADDR then encode slave->VLANID[]
  179. * with hexadecimal VLANID values; we allow 10 VLANID values but
  180. * only 8 are legal;
  181. *
  182. * the idea is to read multiple input strings and call this function
  183. * to initialize one or more slave structures; it is possible to fit
  184. * up to 128 slave structures in one message frame;
  185. *
  186. *
  187. *--------------------------------------------------------------------*/
  188. static void readitem (struct item * item, char const * string)
  189. {
  190. register uint8_t * origin = (uint8_t *)(item->MAC_ADDR);
  191. register uint8_t * offset = (uint8_t *)(item->MAC_ADDR);
  192. size_t extent = sizeof (item->MAC_ADDR);
  193. memset (item, 0, sizeof (* item));
  194. while ((extent) && (*string))
  195. {
  196. unsigned radix = RADIX_HEX;
  197. unsigned field = sizeof (uint8_t) + sizeof (uint8_t);
  198. unsigned value = 0;
  199. unsigned digit = 0;
  200. if ((offset != origin) && (*string == HEX_EXTENDER))
  201. {
  202. string++;
  203. }
  204. while (field--)
  205. {
  206. if ((digit = todigit (*string)) < radix)
  207. {
  208. value *= radix;
  209. value += digit;
  210. string++;
  211. continue;
  212. }
  213. error (1, EINVAL, "bad MAC address: ...[%s] (1)", string);
  214. }
  215. *offset = value;
  216. offset++;
  217. extent--;
  218. }
  219. if (extent)
  220. {
  221. error (1, EINVAL, "bad MAC address: ...[%s] (2)", string);
  222. }
  223. while (isspace (*string))
  224. {
  225. string++;
  226. }
  227. if ((*string) && (*string != ','))
  228. {
  229. error (1, EINVAL, "bad MAC address: ...[%s] (3)", string);
  230. }
  231. while (*string == ',')
  232. {
  233. unsigned radix = RADIX_DEC;
  234. unsigned digit = 0;
  235. unsigned value = 0;
  236. do
  237. {
  238. string++;
  239. }
  240. while (isspace (*string));
  241. while ((digit = todigit (*string)) < radix)
  242. {
  243. value *= radix;
  244. value += digit;
  245. string++;
  246. }
  247. while (isspace (*string))
  248. {
  249. string++;
  250. }
  251. if (item->NUM_VLANIDS < (sizeof (item->VLANID) / sizeof (uint16_t)))
  252. {
  253. item->VLANID [item->NUM_VLANIDS++] = value;
  254. }
  255. }
  256. while (isspace (*string))
  257. {
  258. string++;
  259. }
  260. if (*string)
  261. {
  262. error (1, EINVAL, "bad VLAN ID: ...[%s]", string);
  263. }
  264. return;
  265. }
  266. /*====================================================================*
  267. *
  268. * unsigned readlist (struct item list [], unsigned size);
  269. *
  270. * read one or more items from stdin; discard comments; assume one
  271. * item per line; permit multiple items on one line when separated
  272. * by semicolon; items cannot straddle lines; readitem () controls
  273. * what consitutes one item;
  274. *
  275. *--------------------------------------------------------------------*/
  276. static unsigned readlist (struct item list [], unsigned size)
  277. {
  278. struct item * item = list;
  279. char string [1024];
  280. char * sp = string;
  281. signed c;
  282. for (c = getc (stdin); c != EOF; c = getc (stdin))
  283. {
  284. if (isspace (c))
  285. {
  286. continue;
  287. }
  288. if (c == '#')
  289. {
  290. while ((c != '\n') && (c != EOF))
  291. {
  292. c = getc (stdin);
  293. }
  294. continue;
  295. }
  296. sp = string;
  297. while ((c != ';') && (c != '\n') && (c != EOF))
  298. {
  299. *sp++ = (char)(c);
  300. c = getc (stdin);
  301. }
  302. *sp = (char)(0);
  303. if (size)
  304. {
  305. readitem (item++, string);
  306. size--;
  307. }
  308. }
  309. return ((unsigned)(item - list));
  310. }
  311. /*====================================================================*
  312. *
  313. * void showlist (struct item list [], unsigned items)
  314. *
  315. * print item list on stdout in a format suitable for input using
  316. * readlist (); this function may be commented out if it not used;
  317. *
  318. *
  319. *--------------------------------------------------------------------*/
  320. #if 0
  321. static void showlist (struct item list [], unsigned items)
  322. {
  323. while (items--)
  324. {
  325. uint16_t fields = list->NUM_VLANIDS;
  326. uint16_t * field = list->VLANID;
  327. hexout (list->MAC_ADDR, sizeof (list->MAC_ADDR), 0, 0, stdout);
  328. while (fields--)
  329. {
  330. printf (", %d", *field);
  331. field++;
  332. }
  333. printf ("\n");
  334. list++;
  335. }
  336. return;
  337. }
  338. #endif
  339. /*====================================================================*
  340. *
  341. * signed ReadVLANIDs (struct plc * plc, uint32_t offset, uint32_t length);
  342. *
  343. *
  344. *--------------------------------------------------------------------*/
  345. static signed ReadVLANIDs (struct plc * plc, uint32_t offset, uint32_t length)
  346. {
  347. struct channel * channel = (struct channel *)(plc->channel);
  348. struct message * message = (struct message *)(plc->message);
  349. #ifndef __GNUC__
  350. #pragma pack (push,1)
  351. #endif
  352. struct __packed vs_forward_config_request
  353. {
  354. struct ethernet_hdr ethernet;
  355. struct qualcomm_hdr qualcomm;
  356. uint8_t RESERVED1;
  357. uint8_t MREQUEST;
  358. uint8_t MVERSION;
  359. uint32_t RESERVED2;
  360. uint32_t DATA_LENGTH;
  361. uint32_t DATA_OFFSET;
  362. uint16_t RESERVED3;
  363. }
  364. * request = (struct vs_forward_config_request *) (message);
  365. struct __packed vs_forward_config_confirm
  366. {
  367. struct ethernet_hdr ethernet;
  368. struct qualcomm_hdr qualcomm;
  369. uint8_t RESERVED1;
  370. uint8_t RESULTCODE;
  371. uint8_t OPERATION;
  372. uint8_t MVERSION;
  373. uint32_t RESERVED2;
  374. uint32_t DATA_LENGTH;
  375. uint32_t DATA_OFFSET;
  376. uint8_t DATA [PLC_MODULE_SIZE];
  377. }
  378. * confirm = (struct vs_forward_config_confirm *) (message);
  379. #ifndef __GNUC__
  380. #pragma pack (pop)
  381. #endif
  382. memset (message, 0, sizeof (* message));
  383. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  384. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  385. request->MREQUEST = PLCFWD_GET;
  386. request->MVERSION = PLCFWD_VER;
  387. request->DATA_OFFSET = HTOLE32 (offset);
  388. request->DATA_LENGTH = HTOLE32 (length);
  389. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  390. if (SendMME (plc) <= 0)
  391. {
  392. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  393. return (-1);
  394. }
  395. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  396. {
  397. if (confirm->RESULTCODE)
  398. {
  399. Failure (plc, PLC_WONTDOIT);
  400. continue;
  401. }
  402. hexview (confirm->DATA, LE32TOH (confirm->DATA_OFFSET), LE32TOH (confirm->DATA_LENGTH), stdout);
  403. }
  404. return (0);
  405. }
  406. /*====================================================================*
  407. *
  408. * signed AddVLANIDs (struct plc * plc, struct item list [], unsigned items);
  409. *
  410. *
  411. *--------------------------------------------------------------------*/
  412. static signed AddVLANIDs (struct plc * plc, struct item list [], unsigned items)
  413. {
  414. struct channel * channel = (struct channel *)(plc->channel);
  415. struct message * message = (struct message *)(plc->message);
  416. #ifndef __GNUC__
  417. #pragma pack (push,1)
  418. #endif
  419. struct __packed vs_forward_config_request
  420. {
  421. struct ethernet_hdr ethernet;
  422. struct qualcomm_hdr qualcomm;
  423. uint8_t RESERVED1;
  424. uint8_t MREQUEST;
  425. uint8_t MVERSION;
  426. uint32_t RESERVED2;
  427. uint16_t ITEMS;
  428. struct item LIST [1];
  429. }
  430. * request = (struct vs_forward_config_request *) (message);
  431. struct __packed vs_forward_config_confirm
  432. {
  433. struct ethernet_hdr ethernet;
  434. struct qualcomm_hdr qualcomm;
  435. uint8_t RESERVED1;
  436. uint8_t RESULTCODE;
  437. uint8_t OPERATION;
  438. uint8_t MVERSION;
  439. uint32_t RESERVED2;
  440. }
  441. * confirm = (struct vs_forward_config_confirm *) (message);
  442. #ifndef __GNUC__
  443. #pragma pack (pop)
  444. #endif
  445. struct item * item = request->LIST;
  446. memset (message, 0, sizeof (* message));
  447. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  448. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  449. request->MREQUEST = PLCFWD_ADD;
  450. request->MVERSION = PLCFWD_VER;
  451. request->ITEMS = HTOLE16 (items);
  452. while (items--)
  453. {
  454. unsigned count;
  455. memcpy (item->MAC_ADDR, list->MAC_ADDR, sizeof (item->MAC_ADDR));
  456. item->NUM_VLANIDS = HTOLE16 (list->NUM_VLANIDS);
  457. for (count = 0; count < list->NUM_VLANIDS; count++)
  458. {
  459. item->VLANID [count] = HTOLE16 (list->VLANID [count]);
  460. }
  461. // item++;
  462. item = (struct item *)(&item->VLANID [count]);
  463. list++;
  464. }
  465. plc->packetsize = (signed)((uint8_t *)(item) - (uint8_t *)(request));
  466. if (SendMME (plc) <= 0)
  467. {
  468. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  469. return (-1);
  470. }
  471. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  472. {
  473. if (confirm->RESULTCODE)
  474. {
  475. Failure (plc, PLC_WONTDOIT);
  476. continue;
  477. }
  478. }
  479. return (0);
  480. }
  481. /*====================================================================*
  482. *
  483. * signed RemoveVLANIDs (struct plc * plc, struct item list [], unsigned items);
  484. *
  485. *
  486. *--------------------------------------------------------------------*/
  487. static signed RemoveVLANIDs (struct plc * plc, struct item list [], unsigned items)
  488. {
  489. struct channel * channel = (struct channel *)(plc->channel);
  490. struct message * message = (struct message *)(plc->message);
  491. #ifndef __GNUC__
  492. #pragma pack (push,1)
  493. #endif
  494. struct __packed vs_forward_config_request
  495. {
  496. struct ethernet_hdr ethernet;
  497. struct qualcomm_hdr qualcomm;
  498. uint8_t RESERVED1;
  499. uint8_t MREQUEST;
  500. uint8_t MVERSION;
  501. uint32_t RESERVED2;
  502. uint16_t ITEMS;
  503. struct item LIST [1];
  504. }
  505. * request = (struct vs_forward_config_request *) (message);
  506. struct __packed vs_forward_config_confirm
  507. {
  508. struct ethernet_hdr ethernet;
  509. struct qualcomm_hdr qualcomm;
  510. uint8_t RESERVED1;
  511. uint8_t RESULTCODE;
  512. uint8_t OPERATION;
  513. uint8_t MVERSION;
  514. uint32_t RESERVED2;
  515. }
  516. * confirm = (struct vs_forward_config_confirm *) (message);
  517. #ifndef __GNUC__
  518. #pragma pack (pop)
  519. #endif
  520. struct item * item = request->LIST;
  521. memset (message, 0, sizeof (* message));
  522. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  523. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  524. request->MREQUEST = PLCFWD_REM;
  525. request->MVERSION = PLCFWD_VER;
  526. request->ITEMS = HTOLE16 (items);
  527. while (items--)
  528. {
  529. unsigned count;
  530. memcpy (item->MAC_ADDR, list->MAC_ADDR, sizeof (item->MAC_ADDR));
  531. item->NUM_VLANIDS = HTOLE16 (list->NUM_VLANIDS);
  532. for (count = 0; count < list->NUM_VLANIDS; count++)
  533. {
  534. item->VLANID [count] = HTOLE16 (list->VLANID [count]);
  535. }
  536. // item++;
  537. item = (struct item *)(&item->VLANID [count]);
  538. list++;
  539. }
  540. plc->packetsize = (signed)((uint8_t *)(item) - (uint8_t *)(request));
  541. if (SendMME (plc) <= 0)
  542. {
  543. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  544. return (-1);
  545. }
  546. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  547. {
  548. if (confirm->RESULTCODE)
  549. {
  550. Failure (plc, PLC_WONTDOIT);
  551. continue;
  552. }
  553. }
  554. return (0);
  555. }
  556. /*====================================================================*
  557. *
  558. * signed CommitVLANIDs (struct plc * plc);
  559. *
  560. *
  561. *--------------------------------------------------------------------*/
  562. static signed CommitVLANIDs (struct plc * plc)
  563. {
  564. struct channel * channel = (struct channel *)(plc->channel);
  565. struct message * message = (struct message *)(plc->message);
  566. #ifndef __GNUC__
  567. #pragma pack (push,1)
  568. #endif
  569. struct __packed vs_forward_config_request
  570. {
  571. struct ethernet_hdr ethernet;
  572. struct qualcomm_hdr qualcomm;
  573. uint8_t RESERVED1;
  574. uint8_t MREQUEST;
  575. uint8_t MVERSION;
  576. uint32_t RESERVED2;
  577. }
  578. * request = (struct vs_forward_config_request *) (message);
  579. struct __packed vs_forward_config_confirm
  580. {
  581. struct ethernet_hdr ethernet;
  582. struct qualcomm_hdr qualcomm;
  583. uint8_t RESERVED1;
  584. uint8_t RESULTCODE;
  585. uint8_t OPERATION;
  586. uint8_t MVERSION;
  587. uint32_t RESERVED2;
  588. }
  589. * confirm = (struct vs_forward_config_confirm *) (message);
  590. #ifndef __GNUC__
  591. #pragma pack (pop)
  592. #endif
  593. memset (message, 0, sizeof (* message));
  594. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  595. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  596. request->MREQUEST = PLCFWD_STO;
  597. request->MVERSION = PLCFWD_VER;
  598. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  599. if (SendMME (plc) <= 0)
  600. {
  601. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  602. return (-1);
  603. }
  604. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  605. {
  606. if (confirm->RESULTCODE)
  607. {
  608. Failure (plc, PLC_WONTDOIT);
  609. continue;
  610. }
  611. }
  612. return (0);
  613. }
  614. /*====================================================================*
  615. *
  616. * signed ControlVLANIDs (struct plc * plc);
  617. *
  618. *
  619. *--------------------------------------------------------------------*/
  620. static signed ControlVLANIDs (struct plc * plc)
  621. {
  622. struct channel * channel = (struct channel *)(plc->channel);
  623. struct message * message = (struct message *)(plc->message);
  624. #ifndef __GNUC__
  625. #pragma pack (push,1)
  626. #endif
  627. struct __packed vs_forward_config_request
  628. {
  629. struct ethernet_hdr ethernet;
  630. struct qualcomm_hdr qualcomm;
  631. uint8_t RESERVED1;
  632. uint8_t MREQUEST;
  633. uint8_t MVERSION;
  634. uint32_t RESERVED2;
  635. uint8_t ENABLE;
  636. uint8_t UPSTREAMCHECK;
  637. uint8_t RESERVED3;
  638. }
  639. * request = (struct vs_forward_config_request *) (message);
  640. struct __packed vs_forward_config_confirm
  641. {
  642. struct ethernet_hdr ethernet;
  643. struct qualcomm_hdr qualcomm;
  644. uint8_t RESERVED1;
  645. uint8_t RESULTCODE;
  646. uint8_t OPERATION;
  647. uint8_t MVERSION;
  648. uint32_t RESERVED2;
  649. }
  650. * confirm = (struct vs_forward_config_confirm *) (message);
  651. #ifndef __GNUC__
  652. #pragma pack (pop)
  653. #endif
  654. memset (message, 0, sizeof (* message));
  655. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  656. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  657. request->MREQUEST = PLCFWD_CTL;
  658. request->MVERSION = PLCFWD_VER;
  659. request->ENABLE = plc->module;
  660. request->UPSTREAMCHECK = plc->pushbutton;
  661. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  662. if (SendMME (plc) <= 0)
  663. {
  664. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  665. return (-1);
  666. }
  667. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  668. {
  669. if (confirm->RESULTCODE)
  670. {
  671. Failure (plc, PLC_WONTDOIT);
  672. continue;
  673. }
  674. }
  675. return (0);
  676. }
  677. /*====================================================================*
  678. *
  679. * signed DefaultVLANIDs (struct plc * plc);
  680. *
  681. *
  682. *--------------------------------------------------------------------*/
  683. static signed DefaultVLANIDs (struct plc * plc, struct item list [], unsigned items)
  684. {
  685. struct channel * channel = (struct channel *)(plc->channel);
  686. struct message * message = (struct message *)(plc->message);
  687. #ifndef __GNUC__
  688. #pragma pack (push,1)
  689. #endif
  690. struct __packed vs_forward_config_request
  691. {
  692. struct ethernet_hdr ethernet;
  693. struct qualcomm_hdr qualcomm;
  694. uint8_t RESERVED1;
  695. uint8_t MREQUEST;
  696. uint8_t MVERSION;
  697. uint32_t RESERVED2;
  698. uint16_t VLANID;
  699. uint16_t RESERVED3;
  700. }
  701. * request = (struct vs_forward_config_request *) (message);
  702. struct __packed vs_forward_config_confirm
  703. {
  704. struct ethernet_hdr ethernet;
  705. struct qualcomm_hdr qualcomm;
  706. uint8_t RESERVED1;
  707. uint8_t RESULTCODE;
  708. uint8_t OPERATION;
  709. uint8_t MVERSION;
  710. uint32_t RESERVED2;
  711. }
  712. * confirm = (struct vs_forward_config_confirm *) (message);
  713. #ifndef __GNUC__
  714. #pragma pack (pop)
  715. #endif
  716. memset (message, 0, sizeof (* message));
  717. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  718. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  719. request->MREQUEST = PLCFWD_SET;
  720. request->MVERSION = PLCFWD_VER;
  721. request->VLANID = HTOLE16 (list [0].VLANID [0]);
  722. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  723. if (SendMME (plc) <= 0)
  724. {
  725. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  726. return (-1);
  727. }
  728. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  729. {
  730. if (confirm->RESULTCODE)
  731. {
  732. Failure (plc, PLC_WONTDOIT);
  733. continue;
  734. }
  735. }
  736. return (0);
  737. }
  738. /*====================================================================*
  739. *
  740. * signed ForwardVLANIDs (struct plc * plc);
  741. *
  742. *
  743. *--------------------------------------------------------------------*/
  744. static signed ForwardVLANIDs (struct plc * plc)
  745. {
  746. struct channel * channel = (struct channel *)(plc->channel);
  747. struct message * message = (struct message *)(plc->message);
  748. #ifndef __GNUC__
  749. #pragma pack (push,1)
  750. #endif
  751. struct __packed vs_forward_config_request
  752. {
  753. struct ethernet_hdr ethernet;
  754. struct qualcomm_hdr qualcomm;
  755. uint8_t RESERVED1;
  756. uint8_t MREQUEST;
  757. uint8_t MVERSION;
  758. uint32_t RESERVED2;
  759. uint8_t ENABLED;
  760. uint16_t VLANID;
  761. uint16_t RESERVED3;
  762. struct item ITEM;
  763. }
  764. * request = (struct vs_forward_config_request *) (message);
  765. struct __packed vs_forward_config_confirm
  766. {
  767. struct ethernet_hdr ethernet;
  768. struct qualcomm_hdr qualcomm;
  769. uint8_t RESERVED1;
  770. uint8_t RESULTCODE;
  771. uint8_t OPERATION;
  772. uint8_t MVERSION;
  773. uint32_t RESERVED2;
  774. }
  775. * confirm = (struct vs_forward_config_confirm *) (message);
  776. #ifndef __GNUC__
  777. #pragma pack (pop)
  778. #endif
  779. memset (message, 0, sizeof (* message));
  780. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  781. QualcommHeader (&request->qualcomm, 0, (VS_FORWARD_CONFIG | MMTYPE_REQ));
  782. request->MREQUEST = PLCFWD_FWD;
  783. request->MVERSION = PLCFWD_VER;
  784. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  785. if (SendMME (plc) <= 0)
  786. {
  787. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  788. return (-1);
  789. }
  790. while (ReadMME (plc, 0, (VS_FORWARD_CONFIG | MMTYPE_CNF)) > 0)
  791. {
  792. if (confirm->RESULTCODE)
  793. {
  794. Failure (plc, PLC_WONTDOIT);
  795. continue;
  796. }
  797. }
  798. return (0);
  799. }
  800. /*====================================================================*
  801. *
  802. * void function (struct plc * plc, struct item list [], unsigned items);
  803. *
  804. * perform the VLANID action specified by the action member
  805. * in struct plc as set in the main program; only one action
  806. * is performed;
  807. *
  808. *
  809. *--------------------------------------------------------------------*/
  810. static void function (struct plc * plc, uint32_t offset, uint32_t length, struct item * list, unsigned items)
  811. {
  812. if (plc->action == PLCFWD_GET)
  813. {
  814. ReadVLANIDs (plc, offset, length);
  815. return;
  816. }
  817. if (plc->action == PLCFWD_ADD)
  818. {
  819. AddVLANIDs (plc, list, items);
  820. return;
  821. }
  822. if (plc->action == PLCFWD_REM)
  823. {
  824. RemoveVLANIDs (plc, list, items);
  825. return;
  826. }
  827. if (plc->action == PLCFWD_STO)
  828. {
  829. CommitVLANIDs (plc);
  830. return;
  831. }
  832. if (plc->action == PLCFWD_CTL)
  833. {
  834. ControlVLANIDs (plc);
  835. return;
  836. }
  837. if (plc->action == PLCFWD_SET)
  838. {
  839. DefaultVLANIDs (plc, list, items);
  840. return;
  841. }
  842. if (plc->action == PLCFWD_FWD)
  843. {
  844. ForwardVLANIDs (plc);
  845. return;
  846. }
  847. return;
  848. }
  849. /*====================================================================*
  850. *
  851. * int main (int argc, char const * argv[]);
  852. *
  853. *
  854. *--------------------------------------------------------------------*/
  855. int main (int argc, char const * argv [])
  856. {
  857. extern struct channel channel;
  858. static char const * optv [] =
  859. {
  860. "ACD:ef:i:l:M:o:qRS:t:vxz:",
  861. "device [device] [...] [> stdout]",
  862. "Qualcomm Atheros VLANID Forward Configuration Manager",
  863. "A\tadd VLAN ID of multiple slaves to memory",
  864. "C\tcommit configuration to flash memory",
  865. "D x\tset default VLAN ID",
  866. "e\tredirect stderr to stdout",
  867. "f s\tread VLANIDS from file (s)",
  868. #if defined (WINPCAP) || defined (LIBPCAP)
  869. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  870. #else
  871. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  872. #endif
  873. "l n\tdata length in bytes [" LITERAL (PLCFWD_LENGTH) "]",
  874. "M n\tenable VLANID forwarding on the master",
  875. "o x\tdata offset in bytes [" LITERAL (PLCFWD_OFFSET) "]",
  876. "q\tquiet mode",
  877. "R\tremove VLAN ID of multiple slaves from memory",
  878. "S n\tenable VLANID forwarding on all slaves",
  879. "t n\ttimeout is (n) millisecond [" LITERAL (CHANNEL_TIMEOUT) "]",
  880. "v\tverbose mode",
  881. "x\texit on error",
  882. "z s\tslavespec",
  883. (char const *) (0)
  884. };
  885. #include "../plc/plc.c"
  886. struct item list [128];
  887. unsigned size = sizeof (list) / sizeof (struct item);
  888. unsigned items = 0;
  889. uint32_t offset = 0;
  890. uint32_t length = 0;
  891. signed c;
  892. memset (&list, 0, sizeof (list));
  893. if (getenv (PLCDEVICE))
  894. {
  895. channel.ifname = strdup (getenv (PLCDEVICE));
  896. }
  897. optind = 1;
  898. while ((c = getoptv (argc, argv, optv)) != -1)
  899. {
  900. switch (c)
  901. {
  902. case 'A':
  903. plc.action = PLCFWD_ADD;
  904. break;
  905. case 'C':
  906. plc.action = PLCFWD_STO;
  907. break;
  908. case 'D':
  909. plc.action = PLCFWD_SET;
  910. list [0].VLANID [0] = (uint16_t)(basespec (optarg, 10, sizeof (uint16_t)));
  911. break;
  912. case 'e':
  913. dup2 (STDOUT_FILENO, STDERR_FILENO);
  914. break;
  915. case 'f':
  916. if (!freopen (optarg, "rb", stdin))
  917. {
  918. error (1, errno, "%s", optarg);
  919. }
  920. items += readlist (&list [items], size - items);
  921. break;
  922. case 'i':
  923. #if defined (WINPCAP) || defined (LIBPCAP)
  924. channel.ifindex = atoi (optarg);
  925. #else
  926. channel.ifname = optarg;
  927. #endif
  928. break;
  929. case 'M':
  930. plc.action = PLCFWD_CTL;
  931. plc.module = (uint8_t)(uintspec (synonym (optarg, states, STATES), 0, UCHAR_MAX));
  932. break;
  933. case 'l':
  934. length = (uint32_t) (basespec (optarg, 10, sizeof (length)));
  935. break;
  936. case 'o':
  937. offset = (uint32_t) (basespec (optarg, 10, sizeof (offset)));
  938. break;
  939. case 'q':
  940. _setbits (channel.flags, CHANNEL_SILENCE);
  941. _setbits (plc.flags, PLC_SILENCE);
  942. break;
  943. case 'R':
  944. plc.action = PLCFWD_REM;
  945. break;
  946. case 'S':
  947. plc.action = PLCFWD_CTL;
  948. plc.pushbutton = (uint8_t)(uintspec (synonym (optarg, states, STATES), 0, UCHAR_MAX));
  949. break;
  950. case 't':
  951. channel.timeout = (signed)(uintspec (optarg, 0, UINT_MAX));
  952. break;
  953. case 'v':
  954. _setbits (channel.flags, CHANNEL_VERBOSE);
  955. _setbits (plc.flags, PLC_VERBOSE);
  956. break;
  957. case 'x':
  958. _setbits (plc.flags, PLC_BAILOUT);
  959. break;
  960. case 'z':
  961. readitem (&list [items++], optarg);
  962. break;
  963. default:
  964. break;
  965. }
  966. }
  967. argc -= optind;
  968. argv += optind;
  969. #if 0
  970. showlist (list, items);
  971. #endif
  972. openchannel (&channel);
  973. if (!(plc.message = malloc (sizeof (* plc.message))))
  974. {
  975. error (1, errno, PLC_NOMEMORY);
  976. }
  977. if (!argc)
  978. {
  979. function (&plc, offset, length, list, items);
  980. }
  981. while ((argc) && (* argv))
  982. {
  983. if (!hexencode (channel.peer, sizeof (channel.peer), synonym (* argv, devices, SIZEOF (devices))))
  984. {
  985. error (1, errno, PLC_BAD_MAC, * argv);
  986. }
  987. function (&plc, offset, length, list, items);
  988. argv++;
  989. argc--;
  990. }
  991. free (plc.message);
  992. closechannel (&channel);
  993. return (0);
  994. }