ax25_pad2.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. //
  2. // This file is part of Dire Wolf, an amateur radio packet TNC.
  3. //
  4. // Copyright (C) 2016 John Langner, WB2OSZ
  5. //
  6. // This program is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 2 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. //
  19. /*------------------------------------------------------------------
  20. *
  21. * Name: ax25_pad2.c
  22. *
  23. * Purpose: Packet assembler and disasembler, part 2.
  24. *
  25. * Description:
  26. *
  27. * The original ax25_pad.c was written with APRS in mind.
  28. * It handles UI frames and transparency for a KISS TNC.
  29. * Here we add new functions that can handle the
  30. * more general cases of AX.25 frames.
  31. *
  32. *
  33. * * Destination Address (note: opposite order in printed format)
  34. *
  35. * * Source Address
  36. *
  37. * * 0-8 Digipeater Addresses
  38. * (The AX.25 v2.2 spec reduced this number to
  39. * a maximum of 2 but I allow the original 8.)
  40. *
  41. * Each address is composed of:
  42. *
  43. * * 6 upper case letters or digits, blank padded.
  44. * These are shifted left one bit, leaving the LSB always 0.
  45. *
  46. * * a 7th octet containing the SSID and flags.
  47. * The LSB is always 0 except for the last octet of the address field.
  48. *
  49. * The final octet of the Destination has the form:
  50. *
  51. * C R R SSID 0, where,
  52. *
  53. * C = command/response. Set to 1 for command.
  54. * R R = Reserved = 1 1 (See RR note, below)
  55. * SSID = substation ID
  56. * 0 = zero
  57. *
  58. * The final octet of the Source has the form:
  59. *
  60. * C R R SSID 0, where,
  61. *
  62. * C = command/response. Must be inverse of destination C bit.
  63. * R R = Reserved = 1 1 (See RR note, below)
  64. * SSID = substation ID
  65. * 0 = zero (or 1 if no repeaters)
  66. *
  67. * The final octet of each repeater has the form:
  68. *
  69. * H R R SSID 0, where,
  70. *
  71. * H = has-been-repeated = 0 initially.
  72. * Set to 1 after this address has been used.
  73. * R R = Reserved = 1 1
  74. * SSID = substation ID
  75. * 0 = zero (or 1 if last repeater in list)
  76. *
  77. * A digipeater would repeat this frame if it finds its address
  78. * with the "H" bit set to 0 and all earlier repeater addresses
  79. * have the "H" bit set to 1.
  80. * The "H" bit would be set to 1 in the repeated frame.
  81. *
  82. * In standard monitoring format, an asterisk is displayed after the last
  83. * digipeater with the "H" bit set. That indicates who you are hearing
  84. * over the radio.
  85. *
  86. *
  87. * Next we have:
  88. *
  89. * * One or two byte Control Field - A U frame always has one control byte.
  90. * When using modulo 128 sequence numbers, the
  91. * I and S frames can have a second byte allowing
  92. * 7 bit fields instead of 3 bit fields.
  93. * Unfortunately, we can't tell which we have by looking
  94. * at a frame out of context. :-(
  95. * If we are one end of the link, we would know this
  96. * from SABM/SABME and possible later negotiation
  97. * with XID. But if we start monitoring two other
  98. * stations that are already conversing, we don't know.
  99. *
  100. * RR note: It seems that some implementations put a hint
  101. * in the "RR" reserved bits.
  102. * http://www.tapr.org/pipermail/ax25-layer2/2005-October/000297.html
  103. * The RR bits can also be used for "DAMA" which is
  104. * some sort of channel access coordination scheme.
  105. * http://internet.freepage.de/cgi-bin/feets/freepage_ext/41030x030A/rewrite/hennig/afu/afudoc/afudama.html
  106. * Neither is part of the official protocol spec.
  107. *
  108. * * One byte Protocol ID - Only for I and UI frames.
  109. * Normally we would use 0xf0 for no layer 3.
  110. *
  111. * Finally the Information Field. The initial max size is 256 but it
  112. * can be negotiated higher if both ends agree.
  113. *
  114. * Only these types of frames can have an information part:
  115. * - I
  116. * - UI
  117. * - XID
  118. * - TEST
  119. * - FRMR
  120. *
  121. * The 2 byte CRC is not stored here.
  122. *
  123. *
  124. * Constructors:
  125. * ax25_u_frame - Construct a U frame.
  126. * ax25_s_frame - Construct a S frame.
  127. * ax25_i_frame - Construct a I frame.
  128. *
  129. * Get methods: .... ???
  130. *
  131. *------------------------------------------------------------------*/
  132. #define AX25_PAD_C /* this will affect behavior of ax25_pad.h */
  133. #include "direwolf.h"
  134. #include <stdlib.h>
  135. #include <string.h>
  136. #include <assert.h>
  137. #include <stdio.h>
  138. #include <ctype.h>
  139. //#include "textcolor.h"
  140. #include "ax25_pad.h"
  141. #include "ax25_pad2.h"
  142. extern int ax25memdebug;
  143. static int set_addrs (packet_t pp, char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr);
  144. //#if AX25MEMDEBUG
  145. //#undef AX25MEMDEBUG
  146. //#endif
  147. /*------------------------------------------------------------------------------
  148. *
  149. * Name: ax25_u_frame
  150. *
  151. * Purpose: Construct a U frame.
  152. *
  153. * Input: addrs - Array of addresses.
  154. *
  155. * num_addr - Number of addresses, range 2 .. 10.
  156. *
  157. * cr - cr_cmd command frame, cr_res for a response frame.
  158. *
  159. * ftype - One of:
  160. * frame_type_U_SABME // Set Async Balanced Mode, Extended
  161. * frame_type_U_SABM // Set Async Balanced Mode
  162. * frame_type_U_DISC // Disconnect
  163. * frame_type_U_DM // Disconnect Mode
  164. * frame_type_U_UA // Unnumbered Acknowledge
  165. * frame_type_U_FRMR // Frame Reject
  166. * frame_type_U_UI // Unnumbered Information
  167. * frame_type_U_XID // Exchange Identification
  168. * frame_type_U_TEST // Test
  169. *
  170. * pf - Poll/Final flag.
  171. *
  172. * pid - Protocol ID. >>> Used ONLY for the UI type. <<<
  173. * Normally 0xf0 meaning no level 3.
  174. * Could be other values for NET/ROM, etc.
  175. *
  176. * pinfo - Pointer to data for Info field. Allowed only for UI, XID, TEST, FRMR.
  177. *
  178. * info_len - Length for Info field.
  179. *
  180. *
  181. * Returns: Pointer to new packet object.
  182. *
  183. *------------------------------------------------------------------------------*/
  184. #if AX25MEMDEBUG
  185. packet_t ax25_u_frame_debug (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int pf, int pid, unsigned char *pinfo, int info_len, char *src_file, int src_line)
  186. #else
  187. packet_t ax25_u_frame (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int pf, int pid, unsigned char *pinfo, int info_len)
  188. #endif
  189. {
  190. packet_t this_p;
  191. unsigned char *p;
  192. int ctrl = 0;
  193. unsigned int t = 999; // 1 = must be cmd, 0 = must be response, 2 = can be either.
  194. int i = 0; // Is Info part allowed?
  195. this_p = ax25_new ();
  196. #if AX25MEMDEBUG
  197. if (ax25memdebug) {
  198. printf ("ax25_u_frame, seq=%d, called from %s %d\n", this_p->seq, src_file, src_line);
  199. }
  200. #endif
  201. if (this_p == NULL) return (NULL);
  202. this_p->modulo = 0;
  203. if ( ! set_addrs (this_p, addrs, num_addr, cr)) {
  204. printf ("Internal error in %s: Could not set addresses for U frame.\n", __func__);
  205. ax25_delete (this_p);
  206. return (NULL);
  207. }
  208. switch (ftype) {
  209. // 1 = cmd only, 0 = res only, 2 = either
  210. case frame_type_U_SABME: ctrl = 0x6f; t = 1; break;
  211. case frame_type_U_SABM: ctrl = 0x2f; t = 1; break;
  212. case frame_type_U_DISC: ctrl = 0x43; t = 1; break;
  213. case frame_type_U_DM: ctrl = 0x0f; t = 0; break;
  214. case frame_type_U_UA: ctrl = 0x63; t = 0; break;
  215. case frame_type_U_FRMR: ctrl = 0x87; t = 0; i = 1; break;
  216. case frame_type_U_UI: ctrl = 0x03; t = 2; i = 1; break;
  217. case frame_type_U_XID: ctrl = 0xaf; t = 2; i = 1; break;
  218. case frame_type_U_TEST: ctrl = 0xe3; t = 2; i = 1; break;
  219. default:
  220. printf ("Internal error in %s: Invalid ftype %d for U frame.\n", __func__, ftype);
  221. ax25_delete (this_p);
  222. return (NULL);
  223. break;
  224. }
  225. if (pf) ctrl |= 0x10;
  226. if (t != 2) {
  227. if (cr != t) {
  228. printf ("Internal error in %s: U frame, cr is %d but must be %d. ftype=%d\n", __func__, cr, t, ftype);
  229. }
  230. }
  231. p = this_p->frame_data + this_p->frame_len;
  232. *p++ = ctrl;
  233. this_p->frame_len++;
  234. if (ftype == frame_type_U_UI) {
  235. // Definitely don't want pid value of 0 (not in valid list)
  236. // or 0xff (which means more bytes follow).
  237. if (pid < 0 || pid == 0 || pid == 0xff) {
  238. printf ("Internal error in %s: U frame, Invalid pid value 0x%02x.\n", __func__, pid);
  239. pid = AX25_PID_NO_LAYER_3;
  240. }
  241. *p++ = pid;
  242. this_p->frame_len++;
  243. }
  244. if (i) {
  245. if (pinfo != NULL && info_len > 0) {
  246. if (info_len > AX25_MAX_INFO_LEN) {
  247. printf ("Internal error in %s: U frame, Invalid information field length %d.\n", __func__, info_len);
  248. info_len = AX25_MAX_INFO_LEN;
  249. }
  250. memcpy (p, pinfo, info_len);
  251. p += info_len;
  252. this_p->frame_len += info_len;
  253. }
  254. }
  255. else {
  256. if (pinfo != NULL && info_len > 0) {
  257. printf ("Internal error in %s: Info part not allowed for U frame type.\n", __func__);
  258. }
  259. }
  260. *p = '\0';
  261. assert (p == this_p->frame_data + this_p->frame_len);
  262. assert (this_p->magic1 == MAGIC);
  263. assert (this_p->magic2 == MAGIC);
  264. #if PAD2TEST
  265. ax25_frame_type_t check_ftype;
  266. cmdres_t check_cr;
  267. char check_desc[80];
  268. int check_pf;
  269. int check_nr;
  270. int check_ns;
  271. check_ftype = ax25_frame_type (this_p, &check_cr, check_desc, &check_pf, &check_nr, &check_ns);
  272. printf ("check: ftype=%d, desc=\"%s\", pf=%d\n", check_ftype, check_desc, check_pf);
  273. assert (check_cr == cr);
  274. assert (check_ftype == ftype);
  275. assert (check_pf == pf);
  276. assert (check_nr == -1);
  277. assert (check_ns == -1);
  278. #endif
  279. return (this_p);
  280. } /* end ax25_u_frame */
  281. /*------------------------------------------------------------------------------
  282. *
  283. * Name: ax25_s_frame
  284. *
  285. * Purpose: Construct an S frame.
  286. *
  287. * Input: addrs - Array of addresses.
  288. *
  289. * num_addr - Number of addresses, range 2 .. 10.
  290. *
  291. * cr - cr_cmd command frame, cr_res for a response frame.
  292. *
  293. * ftype - One of:
  294. * frame_type_S_RR, // Receive Ready - System Ready To Receive
  295. * frame_type_S_RNR, // Receive Not Ready - TNC Buffer Full
  296. * frame_type_S_REJ, // Reject Frame - Out of Sequence or Duplicate
  297. * frame_type_S_SREJ, // Selective Reject - Request single frame repeat
  298. *
  299. * modulo - 8 or 128. Determines if we have 1 or 2 control bytes.
  300. *
  301. * nr - N(R) field --- describe.
  302. *
  303. * pf - Poll/Final flag.
  304. *
  305. * pinfo - Pointer to data for Info field. Allowed only for SREJ.
  306. *
  307. * info_len - Length for Info field.
  308. *
  309. *
  310. * Returns: Pointer to new packet object.
  311. *
  312. *------------------------------------------------------------------------------*/
  313. #if AX25MEMDEBUG
  314. packet_t ax25_s_frame_debug (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int modulo, int nr, int pf, unsigned char *pinfo, int info_len, char *src_file, int src_line)
  315. #else
  316. packet_t ax25_s_frame (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int modulo, int nr, int pf, unsigned char *pinfo, int info_len)
  317. #endif
  318. {
  319. packet_t this_p;
  320. unsigned char *p;
  321. int ctrl = 0;
  322. this_p = ax25_new ();
  323. #if AX25MEMDEBUG
  324. if (ax25memdebug) {
  325. printf ("ax25_s_frame, seq=%d, called from %s %d\n", this_p->seq, src_file, src_line);
  326. }
  327. #endif
  328. if (this_p == NULL) return (NULL);
  329. if ( ! set_addrs (this_p, addrs, num_addr, cr)) {
  330. printf ("Internal error in %s: Could not set addresses for S frame.\n", __func__);
  331. ax25_delete (this_p);
  332. return (NULL);
  333. }
  334. if (modulo != 8 && modulo != 128) {
  335. printf ("Internal error in %s: Invalid modulo %d for S frame.\n", __func__, modulo);
  336. modulo = 8;
  337. }
  338. this_p->modulo = modulo;
  339. if (nr < 0 || nr >= modulo) {
  340. printf ("Internal error in %s: Invalid N(R) %d for S frame.\n", __func__, nr);
  341. nr &= (modulo - 1);
  342. }
  343. // Erratum: The AX.25 spec is not clear about whether SREJ should be command, response, or both.
  344. // The underlying X.25 spec clearly says it is reponse only. Let's go with that.
  345. if (ftype == frame_type_S_SREJ && cr != cr_res) {
  346. printf ("Internal error in %s: SREJ must be response.\n", __func__);
  347. }
  348. switch (ftype) {
  349. case frame_type_S_RR: ctrl = 0x01; break;
  350. case frame_type_S_RNR: ctrl = 0x05; break;
  351. case frame_type_S_REJ: ctrl = 0x09; break;
  352. case frame_type_S_SREJ: ctrl = 0x0d; break;
  353. default:
  354. printf ("Internal error in %s: Invalid ftype %d for S frame.\n", __func__, ftype);
  355. ax25_delete (this_p);
  356. return (NULL);
  357. break;
  358. }
  359. p = this_p->frame_data + this_p->frame_len;
  360. if (modulo == 8) {
  361. if (pf) ctrl |= 0x10;
  362. ctrl |= nr << 5;
  363. *p++ = ctrl;
  364. this_p->frame_len++;
  365. }
  366. else {
  367. *p++ = ctrl;
  368. this_p->frame_len++;
  369. ctrl = pf & 1;
  370. ctrl |= nr << 1;
  371. *p++ = ctrl;
  372. this_p->frame_len++;
  373. }
  374. if (ftype == frame_type_S_SREJ) {
  375. if (pinfo != NULL && info_len > 0) {
  376. if (info_len > AX25_MAX_INFO_LEN) {
  377. printf ("Internal error in %s: SREJ frame, Invalid information field length %d.\n", __func__, info_len);
  378. info_len = AX25_MAX_INFO_LEN;
  379. }
  380. memcpy (p, pinfo, info_len);
  381. p += info_len;
  382. this_p->frame_len += info_len;
  383. }
  384. }
  385. else {
  386. if (pinfo != NULL || info_len != 0) {
  387. printf ("Internal error in %s: Info part not allowed for RR, RNR, REJ frame.\n", __func__);
  388. }
  389. }
  390. *p = '\0';
  391. assert (p == this_p->frame_data + this_p->frame_len);
  392. assert (this_p->magic1 == MAGIC);
  393. assert (this_p->magic2 == MAGIC);
  394. #if PAD2TEST
  395. ax25_frame_type_t check_ftype;
  396. cmdres_t check_cr;
  397. char check_desc[80];
  398. int check_pf;
  399. int check_nr;
  400. int check_ns;
  401. // todo modulo must be input.
  402. check_ftype = ax25_frame_type (this_p, &check_cr, check_desc, &check_pf, &check_nr, &check_ns);
  403. printf ("check: ftype=%d, desc=\"%s\", pf=%d, nr=%d\n", check_ftype, check_desc, check_pf, check_nr);
  404. assert (check_cr == cr);
  405. assert (check_ftype == ftype);
  406. assert (check_pf == pf);
  407. assert (check_nr == nr);
  408. assert (check_ns == -1);
  409. #endif
  410. return (this_p);
  411. } /* end ax25_s_frame */
  412. /*------------------------------------------------------------------------------
  413. *
  414. * Name: ax25_i_frame
  415. *
  416. * Purpose: Construct an I frame.
  417. *
  418. * Input: addrs - Array of addresses.
  419. *
  420. * num_addr - Number of addresses, range 2 .. 10.
  421. *
  422. * cr - cr_cmd command frame, cr_res for a response frame.
  423. *
  424. * modulo - 8 or 128.
  425. *
  426. * nr - N(R) field --- describe.
  427. *
  428. * ns - N(S) field --- describe.
  429. *-rw-r--r-- 1 curiousmuch curiousmuch 235 Feb 2 19:36 objects.mk
  430. *
  431. * pf - Poll/Final flag.
  432. *
  433. * pid - Protocol ID.
  434. * Normally 0xf0 meaning no level 3.
  435. * Could be other values for NET/ROM, etc.
  436. *
  437. * pinfo - Pointer to data for Info field.
  438. *
  439. * info_len - Length for Info field.
  440. *
  441. *
  442. * Returns: Pointer to new packet object.
  443. *
  444. *------------------------------------------------------------------------------*/
  445. #if AX25MEMDEBUG
  446. packet_t ax25_i_frame_debug (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, int modulo, int nr, int ns, int pf, int pid, unsigned char *pinfo, int info_len, char *src_file, int src_line)
  447. #else
  448. packet_t ax25_i_frame (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, int modulo, int nr, int ns, int pf, int pid, unsigned char *pinfo, int info_len)
  449. #endif
  450. {
  451. packet_t this_p;
  452. unsigned char *p;
  453. int ctrl = 0;
  454. this_p = ax25_new ();
  455. #if AX25MEMDEBUG
  456. if (ax25memdebug) {
  457. printf ("ax25_i_frame, seq=%d, called from %s %d\n", this_p->seq, src_file, src_line);
  458. }
  459. #endif
  460. if (this_p == NULL) return (NULL);
  461. if ( ! set_addrs (this_p, addrs, num_addr, cr)) {
  462. printf ("Internal error in %s: Could not set addresses for I frame.\n", __func__);
  463. ax25_delete (this_p);
  464. return (NULL);
  465. }
  466. if (modulo != 8 && modulo != 128) {
  467. printf ("Internal error in %s: Invalid modulo %d for I frame.\n", __func__, modulo);
  468. modulo = 8;
  469. }
  470. this_p->modulo = modulo;
  471. if (nr < 0 || nr >= modulo) {
  472. printf ("Internal error in %s: Invalid N(R) %d for I frame.\n", __func__, nr);
  473. nr &= (modulo - 1);
  474. }
  475. if (ns < 0 || ns >= modulo) {
  476. printf ("Internal error in %s: Invalid N(S) %d for I frame.\n", __func__, ns);
  477. ns &= (modulo - 1);
  478. }
  479. p = this_p->frame_data + this_p->frame_len;
  480. if (modulo == 8) {
  481. ctrl = (nr << 5) | (ns << 1);
  482. if (pf) ctrl |= 0x10;
  483. *p++ = ctrl;
  484. this_p->frame_len++;
  485. }
  486. else {
  487. ctrl = ns << 1;
  488. *p++ = ctrl;
  489. this_p->frame_len++;
  490. ctrl = nr << 1;
  491. if (pf) ctrl |= 0x01;
  492. *p++ = ctrl;
  493. this_p->frame_len++;
  494. }
  495. // Definitely don't want pid value of 0 (not in valid list)
  496. // or 0xff (which means more bytes follow).
  497. if (pid < 0 || pid == 0 || pid == 0xff) {
  498. printf ("Warning: Client application provided invalid PID value, 0x%02x, for I frame.\n", pid);
  499. pid = AX25_PID_NO_LAYER_3;
  500. }
  501. *p++ = pid;
  502. this_p->frame_len++;
  503. if (pinfo != NULL && info_len > 0) {
  504. if (info_len > AX25_MAX_INFO_LEN) {
  505. printf ("Internal error in %s: I frame, Invalid information field length %d.\n", __func__, info_len);
  506. info_len = AX25_MAX_INFO_LEN;
  507. }
  508. memcpy (p, pinfo, info_len);
  509. p += info_len;
  510. this_p->frame_len += info_len;
  511. }
  512. *p = '\0';
  513. assert (p == this_p->frame_data + this_p->frame_len);
  514. assert (this_p->magic1 == MAGIC);
  515. assert (this_p->magic2 == MAGIC);
  516. #if PAD2TEST
  517. ax25_frame_type_t check_ftype;
  518. cmdres_t check_cr;
  519. char check_desc[80];
  520. int check_pf;
  521. int check_nr;
  522. int check_ns;
  523. unsigned char *check_pinfo;
  524. int check_info_len;
  525. check_ftype = ax25_frame_type (this_p, &check_cr, check_desc, &check_pf, &check_nr, &check_ns);
  526. printf ("check: ftype=%d, desc=\"%s\", pf=%d, nr=%d, ns=%d\n", check_ftype, check_desc, check_pf, check_nr, check_ns);
  527. check_info_len = ax25_get_info (this_p, &check_pinfo);
  528. assert (check_cr == cr);
  529. assert (check_ftype == frame_type_I);
  530. assert (check_pf == pf);
  531. assert (check_nr == nr);
  532. assert (check_ns == ns);
  533. assert (check_info_len == info_len);
  534. assert (strcmp((char*)check_pinfo,(char*)pinfo) == 0);
  535. #endif
  536. return (this_p);
  537. } /* end ax25_i_frame */
  538. /*------------------------------------------------------------------------------
  539. *
  540. * Name: set_addrs
  541. *
  542. * Purpose: Set address fields
  543. *
  544. * Input: pp - Packet object.
  545. *
  546. * addrs - Array of addresses. Same order as in frame.
  547. *
  548. * num_addr - Number of addresses, range 2 .. 10.
  549. *
  550. * cr - cr_cmd command frame, cr_res for a response frame.
  551. *
  552. * Output: pp->frame_data - 7 bytes for each address.
  553. *
  554. * pp->frame_len - num_addr * 7
  555. *
  556. * p->num_addr - num_addr
  557. *
  558. * Returns: 1 for success. 0 for failure.
  559. *
  560. *------------------------------------------------------------------------------*/
  561. static int set_addrs (packet_t pp, char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr)
  562. {
  563. int n;
  564. assert (pp->frame_len == 0);
  565. assert (cr == cr_cmd || cr == cr_res);
  566. if (num_addr < AX25_MIN_ADDRS || num_addr > AX25_MAX_ADDRS) {
  567. printf ("INTERNAL ERROR: %s %s %d, num_addr = %d\n", __FILE__, __func__, __LINE__, num_addr);
  568. return (0);
  569. }
  570. for (n = 0; n < num_addr; n++) {
  571. unsigned char *pa = pp->frame_data + n * 7;
  572. int ok;
  573. int strict = 1;
  574. char oaddr[AX25_MAX_ADDR_LEN];
  575. int ssid;
  576. int heard;
  577. int j;
  578. ok = ax25_parse_addr (n, addrs[n], strict, oaddr, &ssid, &heard);
  579. if (! ok) return (0);
  580. // Fill in address.
  581. memset (pa, ' ' << 1, 6);
  582. for (j = 0; oaddr[j]; j++) {
  583. pa[j] = oaddr[j] << 1;
  584. }
  585. pa += 6;
  586. // Fill in SSID.
  587. *pa = 0x60 | ((ssid & 0xf) << 1);
  588. // Command / response flag.
  589. switch (n) {
  590. case AX25_DESTINATION:
  591. if (cr == cr_cmd) *pa |= 0x80;
  592. break;
  593. case AX25_SOURCE:
  594. if (cr == cr_res) *pa |= 0x80;
  595. break;
  596. default:
  597. break;
  598. }
  599. // Is this the end of address field?
  600. if (n == num_addr - 1) {
  601. *pa |= 1;
  602. }
  603. pp->frame_len += 7;
  604. }
  605. pp->num_addr = num_addr;
  606. return (1);
  607. } /* end set_addrs */
  608. /*------------------------------------------------------------------------------
  609. *
  610. * Name: main
  611. *
  612. * Purpose: Quick unit test for this file.
  613. *
  614. * Description: Generate a variety of frames.
  615. * Each function calls ax25_frame_type to verify results.
  616. *
  617. * $ gcc -DPAD2TEST -DUSE_REGEX_STATIC -Iregex ax25_pad.c ax25_pad2.c fcs_calc.o textcolor.o regex.a misc.a
  618. *
  619. *------------------------------------------------------------------------------*/
  620. #define PAD2TEST 1
  621. #if PAD2TEST
  622. void test_ax25_pad2 (void)
  623. {
  624. char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN];
  625. int num_addr = 2;
  626. cmdres_t cr;
  627. ax25_frame_type_t ftype;
  628. int pf = 0;
  629. int pid = 0xf0;
  630. int modulo;
  631. int nr, ns;
  632. unsigned char *pinfo = NULL;
  633. int info_len = 0;
  634. packet_t pp;
  635. strcpy (addrs[0], "W2UB");
  636. strcpy (addrs[1], "WB2OSZ-15");
  637. num_addr = 2;
  638. /* U frame */
  639. for (ftype = frame_type_U_SABME; ftype <= frame_type_U_TEST; ftype++) {
  640. for (pf = 0; pf <= 1; pf++) {
  641. int cmin=0, cmax=0;
  642. switch (ftype) {
  643. // 0 = response, 1 = command
  644. case frame_type_U_SABME: cmin = 1; cmax = 1; break;
  645. case frame_type_U_SABM: cmin = 1; cmax = 1; break;
  646. case frame_type_U_DISC: cmin = 1; cmax = 1; break;
  647. case frame_type_U_DM: cmin = 0; cmax = 0; break;
  648. case frame_type_U_UA: cmin = 0; cmax = 0; break;
  649. case frame_type_U_FRMR: cmin = 0; cmax = 0; break;
  650. case frame_type_U_UI: cmin = 0; cmax = 1; break;
  651. case frame_type_U_XID: cmin = 0; cmax = 1; break;
  652. case frame_type_U_TEST: cmin = 0; cmax = 1; break;
  653. default: break; // avoid compiler warning.
  654. }
  655. for (cr = cmin; cr <= cmax; cr++) {
  656. printf ("\nConstruct U frame, cr=%d, ftype=%d, pid=0x%02x\n", cr, ftype, pid);
  657. pp = ax25_u_frame (addrs, num_addr, cr, ftype, pf, pid, pinfo, info_len);
  658. ax25_hex_dump (pp);
  659. ax25_delete (pp);
  660. }
  661. }
  662. }
  663. printf ("\n----------\n\n");
  664. /* S frame */
  665. strcpy (addrs[2], "DIGI1-1");
  666. num_addr = 3;
  667. for (ftype = frame_type_S_RR; ftype <= frame_type_S_SREJ; ftype++) {
  668. for (pf = 0; pf <= 1; pf++) {
  669. modulo = 8;
  670. nr = modulo / 2 + 1;
  671. for (cr = 0; cr <= 1; cr++) {
  672. printf ("\nConstruct S frame, cmd=%d, ftype=%d, pid=0x%02x\n", cr, ftype, pid);
  673. pp = ax25_s_frame (addrs, num_addr, cr, ftype, modulo, nr, pf, NULL, 0);
  674. ax25_hex_dump (pp);
  675. ax25_delete (pp);
  676. }
  677. modulo = 128;
  678. nr = modulo / 2 + 1;
  679. for (cr = 0; cr <= 1; cr++) {
  680. printf ("\nConstruct S frame, cmd=%d, ftype=%d, pid=0x%02x\n", cr, ftype, pid);
  681. pp = ax25_s_frame (addrs, num_addr, cr, ftype, modulo, nr, pf, NULL, 0);
  682. ax25_hex_dump (pp);
  683. ax25_delete (pp);
  684. }
  685. }
  686. }
  687. /* SREJ is only S frame which can have information part. */
  688. static unsigned char srej_info[] = { 1<<1, 2<<1, 3<<1, 4<<1 };
  689. ftype = frame_type_S_SREJ;
  690. for (pf = 0; pf <= 1; pf++) {
  691. modulo = 128;
  692. nr = 127;
  693. cr = cr_res;
  694. printf ("\nConstruct Multi-SREJ S frame, cmd=%d, ftype=%d, pid=0x%02x\n", cr, ftype, pid);
  695. pp = ax25_s_frame (addrs, num_addr, cr, ftype, modulo, nr, pf, srej_info, (int)(sizeof(srej_info)));
  696. ax25_hex_dump (pp);
  697. ax25_delete (pp);
  698. }
  699. printf ("\n----------\n\n");
  700. /* I frame */
  701. pinfo = (unsigned char*)"The rain in Spain stays mainly on the plain.";
  702. info_len = strlen((char*)pinfo);
  703. for (pf = 0; pf <= 1; pf++) {
  704. modulo = 8;
  705. nr = 0x55 & (modulo - 1);
  706. ns = 0xaa & (modulo - 1);
  707. for (cr = 0; cr <= 1; cr++) {
  708. printf ("\nConstruct I frame, cmd=%d, ftype=%d, pid=0x%02x\n", cr, ftype, pid);
  709. pp = ax25_i_frame (addrs, num_addr, cr, modulo, nr, ns, pf, pid, pinfo, info_len);
  710. ax25_hex_dump (pp);
  711. ax25_delete (pp);
  712. }
  713. modulo = 128;
  714. nr = 0x55 & (modulo - 1);
  715. ns = 0xaa & (modulo - 1);
  716. for (cr = 0; cr <= 1; cr++) {
  717. printf ("\nConstruct I frame, cmd=%d, ftype=%d, pid=0x%02x\n", cr, ftype, pid);
  718. pp = ax25_i_frame (addrs, num_addr, cr, modulo, nr, ns, pf, pid, pinfo, info_len);
  719. ax25_hex_dump (pp);
  720. ax25_delete (pp);
  721. }
  722. }
  723. printf ("\n----------\n\n");
  724. printf ("\nSUCCESS!\n");
  725. //exit (EXIT_SUCCESS);
  726. } /* end main */
  727. #endif
  728. /* end ax25_pad2.c */