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