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