HAMMER Utilities: MFC work to date.
[dragonfly.git] / sys / netproto / atm / uni / unisig_encode.c
blob49835f8110448b6c6f17160dfe30f304a455e66b
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/unisig_encode.c,v 1.5 2000/01/17 20:49:56 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_encode.c,v 1.6 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * Message formatting module
38 #include <netproto/atm/kern_include.h>
40 #include "unisig_var.h"
41 #include "unisig_msg.h"
42 #include "unisig_mbuf.h"
43 #include "unisig_decode.h"
46 * Local functions
48 static int usf_enc_ie (struct usfmt *, struct ie_generic *);
49 static int usf_enc_ie_aalp (struct usfmt *, struct ie_generic *);
50 static int usf_enc_ie_clrt (struct usfmt *, struct ie_generic *);
51 static int usf_enc_ie_bbcp (struct usfmt *, struct ie_generic *);
52 static int usf_enc_ie_bhli (struct usfmt *, struct ie_generic *);
53 static int usf_enc_ie_blli (struct usfmt *, struct ie_generic *);
54 static int usf_enc_ie_clst (struct usfmt *, struct ie_generic *);
55 static int usf_enc_ie_cdad (struct usfmt *, struct ie_generic *);
56 static int usf_enc_ie_cdsa (struct usfmt *, struct ie_generic *);
57 static int usf_enc_ie_cgad (struct usfmt *, struct ie_generic *);
58 static int usf_enc_ie_cgsa (struct usfmt *, struct ie_generic *);
59 static int usf_enc_ie_caus (struct usfmt *, struct ie_generic *);
60 static int usf_enc_ie_cnid (struct usfmt *, struct ie_generic *);
61 static int usf_enc_ie_qosp (struct usfmt *, struct ie_generic *);
62 static int usf_enc_ie_brpi (struct usfmt *, struct ie_generic *);
63 static int usf_enc_ie_rsti (struct usfmt *, struct ie_generic *);
64 static int usf_enc_ie_bsdc (struct usfmt *, struct ie_generic *);
65 static int usf_enc_ie_trnt (struct usfmt *, struct ie_generic *);
66 static int usf_enc_ie_uimp (struct usfmt *, struct ie_generic *);
67 static int usf_enc_ie_ident (struct usfmt *, struct ie_generic *,
68 struct ie_decode_tbl *);
69 static int usf_enc_atm_addr (struct usfmt *, Atm_addr *);
73 * Local variables
75 static struct {
76 u_char ident; /* IE identifier */
77 int (*encode) (struct usfmt *, struct ie_generic *);
78 /* Encoding function */
79 } ie_table[] = {
80 { UNI_IE_AALP, usf_enc_ie_aalp },
81 { UNI_IE_CLRT, usf_enc_ie_clrt },
82 { UNI_IE_BBCP, usf_enc_ie_bbcp },
83 { UNI_IE_BHLI, usf_enc_ie_bhli },
84 { UNI_IE_BLLI, usf_enc_ie_blli },
85 { UNI_IE_CLST, usf_enc_ie_clst },
86 { UNI_IE_CDAD, usf_enc_ie_cdad },
87 { UNI_IE_CDSA, usf_enc_ie_cdsa },
88 { UNI_IE_CGAD, usf_enc_ie_cgad },
89 { UNI_IE_CGSA, usf_enc_ie_cgsa },
90 { UNI_IE_CAUS, usf_enc_ie_caus },
91 { UNI_IE_CNID, usf_enc_ie_cnid },
92 { UNI_IE_QOSP, usf_enc_ie_qosp },
93 { UNI_IE_BRPI, usf_enc_ie_brpi },
94 { UNI_IE_RSTI, usf_enc_ie_rsti },
95 { UNI_IE_BLSH, usf_enc_ie_uimp },
96 { UNI_IE_BNSH, usf_enc_ie_uimp },
97 { UNI_IE_BSDC, usf_enc_ie_bsdc },
98 { UNI_IE_TRNT, usf_enc_ie_trnt },
99 { UNI_IE_EPRF, usf_enc_ie_uimp },
100 { UNI_IE_EPST, usf_enc_ie_uimp },
101 { 0, 0 }
104 extern struct ie_decode_tbl ie_aal1_tbl[];
105 extern struct ie_decode_tbl ie_aal4_tbl_30[];
106 extern struct ie_decode_tbl ie_aal4_tbl_31[];
107 extern struct ie_decode_tbl ie_aal5_tbl_30[];
108 extern struct ie_decode_tbl ie_aal5_tbl_31[];
109 extern struct ie_decode_tbl ie_clrt_tbl[];
113 * Encode a UNI signalling message
115 * Arguments:
116 * usf pointer to a unisig formatting structure
117 * msg pointer to a signalling message structure
119 * Returns:
120 * 0 success
121 * errno error encountered
125 usf_enc_msg(struct usfmt *usf, struct unisig_msg *msg)
127 int i, len, rc;
128 u_char c;
129 u_char *lp0, *lp1;
130 struct ie_generic *ie;
132 union {
133 short s;
134 u_char sb[sizeof(short)];
135 } su;
137 ATM_DEBUG2("usf_enc_msg: usf=%p, msg=%p\n",
138 usf, msg);
141 * Encode the protocol discriminator
143 c = UNI_MSG_DISC_Q93B;
144 rc = usf_byte(usf, &c);
145 if (rc)
146 return(rc);
149 * Encode the call reference length
151 c = 3;
152 rc = usf_byte(usf, &c);
153 if (rc)
154 return(rc);
157 * Encode the call reference
159 rc = usf_int3(usf, &msg->msg_call_ref);
160 if (rc)
161 return(rc);
164 * Encode the message type
166 rc = usf_byte(usf, &msg->msg_type);
167 if (rc)
168 return(rc);
171 * Encode the message type extension
173 c = ((msg->msg_type_flag & UNI_MSG_TYPE_FLAG_MASK) <<
174 UNI_MSG_TYPE_FLAG_SHIFT) +
175 (msg->msg_type_action & UNI_MSG_TYPE_ACT_MASK) +
176 UNI_IE_EXT_BIT;
177 rc = usf_byte(usf, &c);
178 if (rc)
179 return(rc);
182 * Save the location of the message length and encode a length
183 * of zero for now. We'll fix the length up at the end.
185 su.s = 0;
186 rc = usf_byte_mark(usf, &su.sb[sizeof(short)-2], &lp0);
187 if (rc)
188 return(rc);
189 rc = usf_byte_mark(usf, &su.sb[sizeof(short)-1], &lp1);
190 if (rc)
191 return(rc);
194 * Process information elements
196 len = 0;
197 for (i=0; i<UNI_MSG_IE_CNT; i++) {
198 ie = msg->msg_ie_vec[i];
199 while (ie) {
200 rc = usf_enc_ie(usf, ie);
201 if (rc)
202 return(rc);
203 len += (ie->ie_length + UNI_IE_HDR_LEN);
204 ie = ie->ie_next;
209 * Fix the message length in the encoded message
211 su.s = htons((u_short)len);
212 *lp0 = su.sb[sizeof(short)-2];
213 *lp1 = su.sb[sizeof(short)-1];
215 return(0);
220 * Encode an information element
222 * Arguments:
223 * usf pointer to a UNISIG formatting structure
224 * msg pointer to a UNISIG message structure
225 * ie pointer to a generic IE structure
227 * Returns:
228 * 0 success
229 * errno error encountered
232 static int
233 usf_enc_ie(struct usfmt *usf, struct ie_generic *ie)
235 int i, rc;
236 u_char c;
237 u_char *lp0, *lp1;
239 union {
240 short s;
241 u_char sb[sizeof(short)];
242 } su;
244 ATM_DEBUG2("usf_enc_ie: usf=%p, ie=%p\n",
245 usf, ie);
248 * Encode the IE identifier
250 rc = usf_byte(usf, &ie->ie_ident);
251 if (rc)
252 return(rc);
255 * Encode the extended type
257 c = ((ie->ie_coding & UNI_IE_CODE_MASK) << UNI_IE_CODE_SHIFT) +
258 ((ie->ie_flag & UNI_IE_FLAG_MASK) <<
259 UNI_IE_FLAG_SHIFT) +
260 (ie->ie_action & UNI_IE_ACT_MASK) +
261 UNI_IE_EXT_BIT;
262 rc = usf_byte(usf, &c);
263 if (rc)
264 return(rc);
267 * Mark the current location in the output stream. Encode a
268 * length of zero for now; we'll come back and fix it up at
269 * the end.
271 su.s = 0;
272 rc = usf_byte_mark(usf, &su.sb[sizeof(short)-2], &lp0);
273 if (rc)
274 return(rc);
275 rc = usf_byte_mark(usf, &su.sb[sizeof(short)-1], &lp1);
276 if (rc)
277 return(rc);
280 * Look up the information element in the table
282 for (i=0; (ie->ie_ident != ie_table[i].ident) &&
283 (ie_table[i].encode != NULL); i++) {
285 if (ie_table[i].encode == NULL) {
287 * Unrecognized IE
289 return(EINVAL);
293 * Process the IE by calling the function indicated
294 * in the IE table
296 rc = ie_table[i].encode(usf, ie);
297 if (rc)
298 return(rc);
301 * Set the length in the output stream
303 su.s = htons((u_short)ie->ie_length);
304 *lp0 = su.sb[sizeof(short)-2];
305 *lp1 = su.sb[sizeof(short)-1];
307 return(0);
312 * Encode an AAL parameters information element
314 * Arguments:
315 * usf pointer to a unisig formatting structure
316 * ie pointer to an AAL parms IE structure
318 * Returns:
319 * 0 success
320 * errno error encountered
323 static int
324 usf_enc_ie_aalp(struct usfmt *usf, struct ie_generic *ie)
326 int i, rc = 0;
328 ATM_DEBUG2("usf_enc_ie_aalp: usf=%p, ie=%p\n",
329 usf, ie);
331 ie->ie_length = 0;
334 * Encode the AAL type
336 if (ie->ie_aalp_aal_type == T_ATM_ABSENT)
337 return(0);
338 rc = usf_byte(usf, &ie->ie_aalp_aal_type);
339 if (rc)
340 return(rc);
343 * Process based on AAL type
345 switch (ie->ie_aalp_aal_type) {
346 case UNI_IE_AALP_AT_AAL1:
347 rc = usf_enc_ie_ident(usf, ie, ie_aal1_tbl);
348 break;
349 case UNI_IE_AALP_AT_AAL3:
350 if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
351 rc = usf_enc_ie_ident(usf, ie, ie_aal4_tbl_30);
352 else
353 rc = usf_enc_ie_ident(usf, ie, ie_aal4_tbl_31);
354 break;
355 case UNI_IE_AALP_AT_AAL5:
356 if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
357 rc = usf_enc_ie_ident(usf, ie, ie_aal5_tbl_30);
358 else
359 rc = usf_enc_ie_ident(usf, ie, ie_aal5_tbl_31);
360 break;
361 case UNI_IE_AALP_AT_AALU:
363 * Encode the user data
365 i = 0;
366 while (i < sizeof(ie->ie_aalp_user_info)) {
367 rc = usf_byte(usf, &ie->ie_aalp_user_info[i]);
368 if (rc)
369 break;
370 i++;
371 ie->ie_length++;
373 break;
374 default:
375 return(EINVAL);
378 ie->ie_length++;
379 return(rc);
384 * Encode a user cell rate information element
386 * This routine just encodes the parameters required for best
387 * effort service.
389 * Arguments:
390 * usf pointer to a unisig formatting structure
391 * ie pointer to a cell rate IE structure
393 * Returns:
394 * 0 success
395 * errno error encountered
398 static int
399 usf_enc_ie_clrt(struct usfmt *usf, struct ie_generic *ie)
401 int rc;
403 ATM_DEBUG2("usf_enc_ie_clrt: usf=%p, ie=%p\n",
404 usf, ie);
406 #ifdef NOTDEF
408 * Encode Peak Cell Rate Forward CLP = 0 + 1
410 c = UNI_IE_CLRT_FWD_PEAK_01_ID;
411 rc = usf_byte(usf, &c);
412 if (rc)
413 return(rc);
414 rc = usf_int3(usf, &ie->ie_clrt_fwd_peak_01);
415 if (rc)
416 return(rc);
419 * Encode Peak Cell Rate Backward CLP = 0 + 1
421 c = UNI_IE_CLRT_BKWD_PEAK_01_ID;
422 rc = usf_byte(usf, &c);
423 if (rc)
424 return(rc);
425 rc = usf_int3(usf, &ie->ie_clrt_bkwd_peak_01);
426 if (rc)
427 return(rc);
430 * Encode Best Effort Flag
432 c = UNI_IE_CLRT_BEST_EFFORT_ID;
433 rc = usf_byte(usf, &c);
434 if (rc)
435 return(rc);
438 * Set IE length
440 ie->ie_length = 9;
441 #endif
444 * Encode the user cell rate IE using the table
446 ie->ie_length = 0;
447 rc = usf_enc_ie_ident(usf, ie, ie_clrt_tbl);
449 return(rc);
454 * Encode a broadband bearer capability information element
456 * Arguments:
457 * usf pointer to a unisig formatting structure
458 * ie pointer to a cell rate IE structure
460 * Returns:
461 * 0 success
462 * errno error encountered
465 static int
466 usf_enc_ie_bbcp(struct usfmt *usf, struct ie_generic *ie)
468 int rc;
469 u_char c;
471 ATM_DEBUG2("usf_enc_ie_bbcp: usf=%p, ie=%p\n",
472 usf, ie);
474 ie->ie_length = 0;
477 * Encode the broadband bearer class
479 if (ie->ie_bbcp_bearer_class == T_ATM_ABSENT)
480 return(0);
481 c = ie->ie_bbcp_bearer_class & UNI_IE_BBCP_BC_MASK;
482 if (ie->ie_bbcp_bearer_class != UNI_IE_BBCP_BC_BCOB_X)
483 c |= UNI_IE_EXT_BIT;
484 rc = usf_byte(usf, &c);
485 if (rc)
486 return(rc);
487 ie->ie_length++;
490 * If the broadband bearer class was X, the next
491 * byte has the traffic type and timing requirements
493 if (ie->ie_bbcp_bearer_class == UNI_IE_BBCP_BC_BCOB_X) {
494 c = ((ie->ie_bbcp_traffic_type & UNI_IE_BBCP_TT_MASK) <<
495 UNI_IE_BBCP_TT_SHIFT) +
496 (ie->ie_bbcp_timing_req &
497 UNI_IE_BBCP_TR_MASK) +
498 UNI_IE_EXT_BIT;
499 rc = usf_byte(usf, &c);
500 if (rc)
501 return(rc);
502 ie->ie_length++;
506 * Encode the clipping and user plane connection configuration
508 c = ((ie->ie_bbcp_clipping & UNI_IE_BBCP_SC_MASK) <<
509 UNI_IE_BBCP_SC_SHIFT) +
510 (ie->ie_bbcp_conn_config &
511 UNI_IE_BBCP_CC_MASK) +
512 UNI_IE_EXT_BIT;
513 rc = usf_byte(usf, &c);
514 if (rc)
515 return(rc);
516 ie->ie_length++;
518 return(0);
523 * Encode a broadband high layer information element
525 * Arguments:
526 * usf pointer to a unisig formatting structure
527 * ie pointer to a cell rate IE structure
529 * Returns:
530 * 0 success
531 * errno error encountered
534 static int
535 usf_enc_ie_bhli(struct usfmt *usf, struct ie_generic *ie)
537 int i, rc;
538 u_int type;
540 ATM_DEBUG2("usf_enc_ie_bhli: usf=%p, ie=%p\n",
541 usf, ie);
543 ie->ie_length = 0;
546 * Encode the high layer information type
548 if (ie->ie_bhli_type == T_ATM_ABSENT)
549 return(0);
550 type = ie->ie_bhli_type | UNI_IE_EXT_BIT;
551 rc = usf_ext(usf, &type);
552 if (rc)
553 return(rc);
554 ie->ie_length++;
557 * What comes next depends on the type
559 switch (ie->ie_bhli_type) {
560 case UNI_IE_BHLI_TYPE_ISO:
561 case UNI_IE_BHLI_TYPE_USER:
563 * ISO or user-specified parameters -- take the
564 * length of information from the IE length
566 for (i=0; i<ie->ie_length-1; i++) {
567 rc = usf_byte(usf, &ie->ie_bhli_info[i]);
568 if (rc)
569 return(rc);
570 ie->ie_length++;
572 break;
573 case UNI_IE_BHLI_TYPE_HLP:
575 * Make sure the IE is long enough for the high
576 * layer profile information, then get it
578 if (usf->usf_sig->us_proto != ATM_SIG_UNI30)
579 return (EINVAL);
580 for (i=0; i<UNI_IE_BHLI_HLP_LEN; i++) {
581 rc = usf_byte(usf, &ie->ie_bhli_info[i]);
582 if (rc)
583 return(rc);
584 ie->ie_length++;
586 break;
587 case UNI_IE_BHLI_TYPE_VSA:
589 * Make sure the IE is long enough for the vendor-
590 * specific application information, then get it
592 for (i=0; i<UNI_IE_BHLI_VSA_LEN; i++) {
593 rc = usf_byte(usf, &ie->ie_bhli_info[i]);
594 if (rc)
595 return(rc);
596 ie->ie_length++;
598 break;
599 default:
600 return(EINVAL);
603 return(0);
608 * Encode a broadband low layer information element
610 * Arguments:
611 * usf pointer to a unisig formatting structure
612 * ie pointer to a cell rate IE structure
614 * Returns:
615 * 0 success
616 * errno error encountered
619 static int
620 usf_enc_ie_blli(struct usfmt *usf, struct ie_generic *ie)
622 u_char c;
623 int rc;
624 u_int ipi;
626 ATM_DEBUG2("usf_enc_ie_blli: usf=%p, ie=%p\n",
627 usf, ie);
629 ie->ie_length = 0;
632 * Encode paramteters for whichever protocol layers the
633 * user specified
637 * Layer 1 information
639 if (ie->ie_blli_l1_id && ie->ie_blli_l1_id != T_ATM_ABSENT) {
640 c = (UNI_IE_BLLI_L1_ID << UNI_IE_BLLI_LID_SHIFT) +
641 (ie->ie_blli_l1_id &
642 UNI_IE_BLLI_LP_MASK) +
643 UNI_IE_EXT_BIT;
644 rc = usf_byte(usf, &c);
645 if (rc)
646 return(rc);
647 ie->ie_length++;
651 * Layer 2 information
653 if (ie->ie_blli_l2_id && ie->ie_blli_l2_id != T_ATM_ABSENT) {
654 c = (UNI_IE_BLLI_L2_ID << UNI_IE_BLLI_LID_SHIFT) +
655 (ie->ie_blli_l2_id &
656 UNI_IE_BLLI_LP_MASK);
658 switch (ie->ie_blli_l2_id) {
659 case UNI_IE_BLLI_L2P_X25L:
660 case UNI_IE_BLLI_L2P_X25M:
661 case UNI_IE_BLLI_L2P_HDLC1:
662 case UNI_IE_BLLI_L2P_HDLC2:
663 case UNI_IE_BLLI_L2P_HDLC3:
664 case UNI_IE_BLLI_L2P_Q922:
665 case UNI_IE_BLLI_L2P_ISO7776:
667 * Write the Layer 2 type
669 rc = usf_byte(usf, &c);
670 if (rc)
671 return(rc);
672 ie->ie_length++;
675 * Encode the Layer 2 mode
677 if (ie->ie_blli_l2_mode) {
678 c = (ie->ie_blli_l2_mode &
679 UNI_IE_BLLI_L2MODE_MASK) <<
680 UNI_IE_BLLI_L2MODE_SHIFT;
681 if (!ie->ie_blli_l2_window)
682 c |= UNI_IE_EXT_BIT;
684 rc = usf_byte(usf, &c);
685 if (rc)
686 return(rc);
687 ie->ie_length++;
691 * Encode the Layer 2 window size
693 if (ie->ie_blli_l2_window) {
694 c = (ie->ie_blli_l2_window &
695 UNI_IE_EXT_MASK) +
696 UNI_IE_EXT_BIT;
698 rc = usf_byte(usf, &c);
699 if (rc)
700 return(rc);
701 ie->ie_length++;
703 break;
704 case UNI_IE_BLLI_L2P_USER:
706 * Write the Layer 2 type
708 rc = usf_byte(usf, &c);
709 if (rc)
710 return(rc);
711 ie->ie_length++;
714 * Encode the user-specified layer 2 info
716 c = (ie->ie_blli_l2_user_proto &
717 UNI_IE_EXT_MASK) +
718 UNI_IE_EXT_BIT;
719 rc = usf_byte(usf, &c);
720 if (rc)
721 return(rc);
722 ie->ie_length++;
723 break;
724 default:
726 * Write the Layer 2 type
728 c |= UNI_IE_EXT_BIT;
729 rc = usf_byte(usf, &c);
730 if (rc)
731 return(rc);
732 ie->ie_length++;
733 break;
738 * Layer 3 information
740 if (ie->ie_blli_l3_id && ie->ie_blli_l3_id != T_ATM_ABSENT) {
742 * Encode the layer 3 protocol ID
744 c = (UNI_IE_BLLI_L3_ID << UNI_IE_BLLI_LID_SHIFT) +
745 (ie->ie_blli_l3_id &
746 UNI_IE_BLLI_LP_MASK);
749 * Process other fields based on protocol ID
751 switch(ie->ie_blli_l3_id) {
752 case UNI_IE_BLLI_L3P_X25:
753 case UNI_IE_BLLI_L3P_ISO8208:
754 case UNI_IE_BLLI_L3P_ISO8878:
756 * Write the protocol ID
758 rc = usf_byte(usf, &c);
759 if (rc)
760 return(rc);
761 ie->ie_length++;
763 if (ie->ie_blli_l3_mode ||
764 ie->ie_blli_l3_packet_size ||
765 ie->ie_blli_l3_window) {
766 c = (ie->ie_blli_l3_mode &
767 UNI_IE_BLLI_L3MODE_MASK) <<
768 UNI_IE_BLLI_L3MODE_SHIFT;
769 if (!ie->ie_blli_l3_packet_size &&
770 !ie->ie_blli_l3_window)
771 c |= UNI_IE_EXT_BIT;
773 rc = usf_byte(usf, &c);
774 if (rc)
775 return(rc);
776 ie->ie_length++;
779 if (ie->ie_blli_l3_packet_size ||
780 ie->ie_blli_l3_window) {
781 c = ie->ie_blli_l3_packet_size &
782 UNI_IE_BLLI_L3PS_MASK;
783 if (!ie->ie_blli_l3_window)
784 c |= UNI_IE_EXT_BIT;
786 rc = usf_byte(usf, &c);
787 if (rc)
788 return(rc);
789 ie->ie_length++;
792 if (ie->ie_blli_l3_window) {
793 c = (ie->ie_blli_l3_window &
794 UNI_IE_EXT_MASK) +
795 UNI_IE_EXT_BIT;
797 rc = usf_byte(usf, &c);
798 if (rc)
799 return(rc);
800 ie->ie_length++;
802 break;
803 case UNI_IE_BLLI_L3P_USER:
805 * Write the protocol ID
807 rc = usf_byte(usf, &c);
808 if (rc)
809 return(rc);
810 ie->ie_length++;
813 * Encode the user-specified protocol info
815 c = (ie->ie_blli_l3_user_proto &
816 UNI_IE_EXT_MASK) +
817 UNI_IE_EXT_BIT;
819 rc = usf_byte(usf, &c);
820 if (rc)
821 return(rc);
822 ie->ie_length++;
823 break;
824 case UNI_IE_BLLI_L3P_ISO9577:
826 * Write the protocol ID
828 rc = usf_byte(usf, &c);
829 if (rc)
830 return(rc);
831 ie->ie_length++;
834 * Encode the IPI
836 ipi = ie->ie_blli_l3_ipi <<
837 UNI_IE_BLLI_L3IPI_SHIFT;
838 rc = usf_ext(usf, &ipi);
839 if (rc)
840 return(rc);
841 ie->ie_length += 2;
843 if (ie->ie_blli_l3_ipi ==
844 UNI_IE_BLLI_L3IPI_SNAP) {
845 c = UNI_IE_EXT_BIT;
846 rc = usf_byte(usf, &c);
847 if (rc)
848 return(rc);
850 rc = usf_byte(usf,
851 &ie->ie_blli_l3_oui[0]);
852 if (rc)
853 return(rc);
855 rc = usf_byte(usf,
856 &ie->ie_blli_l3_oui[1]);
857 if (rc)
858 return(rc);
860 rc = usf_byte(usf,
861 &ie->ie_blli_l3_oui[2]);
862 if (rc)
863 return(rc);
865 rc = usf_byte(usf,
866 &ie->ie_blli_l3_pid[0]);
867 if (rc)
868 return(rc);
870 rc = usf_byte(usf,
871 &ie->ie_blli_l3_pid[1]);
872 if (rc)
873 return(rc);
875 ie->ie_length += 6;
877 break;
878 default:
880 * Write the layer 3 protocol ID
882 c |= UNI_IE_EXT_BIT;
883 rc = usf_byte(usf, &c);
884 if (rc)
885 return(rc);
886 ie->ie_length++;
887 break;
891 return(0);
896 * Encode a call state information element
898 * Arguments:
899 * usf pointer to a unisig formatting structure
900 * ie pointer to a cell rate IE structure
902 * Returns:
903 * 0 success
904 * errno error encountered
907 static int
908 usf_enc_ie_clst(struct usfmt *usf, struct ie_generic *ie)
910 int rc;
911 u_char c;
913 ATM_DEBUG2("usf_enc_ie_clst: usf=%p, ie=%p\n",
914 usf, ie);
916 c = ie->ie_clst_state & UNI_IE_CLST_STATE_MASK;
917 rc = usf_byte(usf, &c);
918 if (rc)
919 return(rc);
920 ie->ie_length = 1;
922 return(0);
927 * Encode a called party number information element
929 * Arguments:
930 * usf pointer to a unisig formatting structure
931 * ie pointer to a cell rate IE structure
933 * Returns:
934 * 0 success
935 * errno error encountered
938 static int
939 usf_enc_ie_cdad(struct usfmt *usf, struct ie_generic *ie)
941 u_char c;
942 int rc;
944 ATM_DEBUG2("usf_enc_ie_cdad: usf=%p, ie=%p\n",
945 usf, ie);
948 * Encode the numbering plan
950 switch(ie->ie_cdad_addr.address_format) {
951 case T_ATM_E164_ADDR:
952 c = UNI_IE_CDAD_PLAN_E164 +
953 (UNI_IE_CDAD_TYPE_INTL
954 << UNI_IE_CDAD_TYPE_SHIFT);
955 ie->ie_length = sizeof(Atm_addr_e164) + 1;
956 break;
957 case T_ATM_ENDSYS_ADDR:
958 c = UNI_IE_CDAD_PLAN_NSAP +
959 (UNI_IE_CDAD_TYPE_UNK
960 << UNI_IE_CDAD_TYPE_SHIFT);
961 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
962 break;
963 default:
964 return(EINVAL);
966 c |= UNI_IE_EXT_BIT;
967 rc = usf_byte(usf, &c);
968 if (rc)
969 return(rc);
972 * Encode the ATM address
974 rc = usf_enc_atm_addr(usf, &ie->ie_cdad_addr);
976 return(rc);
981 * Encode a called party subaddress information element
983 * Arguments:
984 * usf pointer to a unisig formatting structure
985 * ie pointer to a cell rate IE structure
987 * Returns:
988 * 0 success
989 * errno error encountered
992 static int
993 usf_enc_ie_cdsa(struct usfmt *usf, struct ie_generic *ie)
995 u_char c;
996 int rc;
999 * Encode the subaddress type
1001 switch(ie->ie_cdsa_addr.address_format) {
1002 case T_ATM_ENDSYS_ADDR:
1003 c = UNI_IE_CDSA_TYPE_AESA << UNI_IE_CDSA_TYPE_SHIFT;
1004 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
1005 break;
1006 default:
1007 return(EINVAL);
1009 c |= UNI_IE_EXT_BIT;
1010 rc = usf_byte(usf, &c);
1011 if (rc)
1012 return(rc);
1015 * Encode the ATM address
1017 rc = usf_enc_atm_addr(usf, &ie->ie_cdsa_addr);
1019 return(rc);
1024 * Encode a calling party number information element
1026 * Arguments:
1027 * usf pointer to a unisig formatting structure
1028 * ie pointer to a cell rate IE structure
1030 * Returns:
1031 * 0 success
1032 * errno error encountered
1035 static int
1036 usf_enc_ie_cgad(struct usfmt *usf, struct ie_generic *ie)
1038 u_char c;
1039 int rc;
1041 ATM_DEBUG2("usf_enc_ie_cgad: usf=%p, ie=%p\n",
1042 usf, ie);
1045 * Encode the numbering plan
1047 switch(ie->ie_cgad_addr.address_format) {
1048 case T_ATM_E164_ADDR:
1049 c = UNI_IE_CGAD_PLAN_E164 +
1050 (UNI_IE_CGAD_TYPE_INTL
1051 << UNI_IE_CGAD_TYPE_SHIFT) +
1052 UNI_IE_EXT_BIT;
1053 ie->ie_length = sizeof(Atm_addr_e164) + 1;
1054 break;
1055 case T_ATM_ENDSYS_ADDR:
1056 c = UNI_IE_CGAD_PLAN_NSAP +
1057 (UNI_IE_CGAD_TYPE_UNK
1058 << UNI_IE_CGAD_TYPE_SHIFT) +
1059 UNI_IE_EXT_BIT;
1060 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
1061 break;
1062 default:
1063 return(EINVAL);
1065 rc = usf_byte(usf, &c);
1066 if (rc)
1067 return(rc);
1070 * Encode the presentation and screening indicators
1072 #ifdef NOTDEF
1073 c = ((ie->ie_cgad_pres_ind & UNI_IE_CGAD_PRES_MASK)
1074 << UNI_IE_CGAD_PRES_SHIFT) +
1075 (ie->ie_cgad_screen_ind &
1076 UNI_IE_CGAD_SCR_MASK) +
1077 UNI_IE_EXT_BIT;
1078 rc = usf_byte(usf, &c);
1079 if (rc)
1080 return(rc);
1081 #endif
1085 * Encode the ATM address
1087 rc = usf_enc_atm_addr(usf, &ie->ie_cgad_addr);
1089 return(rc);
1094 * Encode a calling party subaddress information element
1096 * Arguments:
1097 * usf pointer to a unisig formatting structure
1098 * ie pointer to a cell rate IE structure
1100 * Returns:
1101 * 0 success
1102 * errno error encountered
1105 static int
1106 usf_enc_ie_cgsa(struct usfmt *usf, struct ie_generic *ie)
1108 u_char c;
1109 int rc;
1112 * Encode the subaddress type
1114 switch(ie->ie_cgsa_addr.address_format) {
1115 case T_ATM_ENDSYS_ADDR:
1116 c = UNI_IE_CGSA_TYPE_AESA << UNI_IE_CGSA_TYPE_SHIFT;
1117 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
1118 break;
1119 default:
1120 return(EINVAL);
1122 c |= UNI_IE_EXT_BIT;
1123 rc = usf_byte(usf, &c);
1124 if (rc)
1125 return(rc);
1128 * Encode the ATM address
1130 rc = usf_enc_atm_addr(usf, &ie->ie_cgsa_addr);
1132 return(rc);
1137 * Encode a cause information element
1139 * Arguments:
1140 * usf pointer to a unisig formatting structure
1141 * ie pointer to a cell rate IE structure
1143 * Returns:
1144 * 0 success
1145 * errno error encountered
1148 static int
1149 usf_enc_ie_caus(struct usfmt *usf, struct ie_generic *ie)
1151 int i, rc;
1152 u_char c;
1154 ATM_DEBUG2("usf_enc_ie_caus: usf=%p, ie=%p\n",
1155 usf, ie);
1157 ie->ie_length = 0;
1160 * Encode the cause location
1162 c = (ie->ie_caus_loc & UNI_IE_CAUS_LOC_MASK) | UNI_IE_EXT_BIT;
1163 rc = usf_byte(usf, &c);
1164 if (rc)
1165 return(rc);
1166 ie->ie_length++;
1169 * Encode the cause value
1171 c = ie->ie_caus_cause | UNI_IE_EXT_BIT;
1172 rc = usf_byte(usf, &c);
1173 if (rc)
1174 return(rc);
1175 ie->ie_length++;
1178 * Encode any included diagnostics
1180 for (i = 0; i < ie->ie_caus_diag_len &&
1181 i < sizeof(ie->ie_caus_diagnostic);
1182 i++) {
1183 rc = usf_byte(usf, &ie->ie_caus_diagnostic[i]);
1184 if (rc)
1185 return(rc);
1186 ie->ie_length++;
1189 return(0);
1194 * Encode a conection identifier information element
1196 * Arguments:
1197 * usf pointer to a unisig formatting structure
1198 * ie pointer to a cell rate IE structure
1200 * Returns:
1201 * 0 success
1202 * errno error encountered
1205 static int
1206 usf_enc_ie_cnid(struct usfmt *usf, struct ie_generic *ie)
1208 int rc;
1209 u_char c;
1211 ATM_DEBUG2("usf_enc_ie_cnid: usf=%p, ie=%p\n",
1212 usf, ie);
1214 c = ((ie->ie_cnid_vp_sig & UNI_IE_CNID_VPSIG_MASK)
1215 << UNI_IE_CNID_VPSIG_SHIFT) +
1216 (ie->ie_cnid_pref_excl & UNI_IE_CNID_PREX_MASK) +
1217 UNI_IE_EXT_BIT;
1218 rc = usf_byte(usf, &c);
1219 if (rc)
1220 return(rc);
1222 rc = usf_short(usf, &ie->ie_cnid_vpci);
1223 if (rc)
1224 return(rc);
1225 rc = usf_short(usf, &ie->ie_cnid_vci);
1226 if (rc)
1227 return(rc);
1229 ie->ie_length = 5;
1230 return(0);
1235 * Encode a quality of service parameters information element
1237 * Arguments:
1238 * usf pointer to a unisig formatting structure
1239 * ie pointer to a cell rate IE structure
1241 * Returns:
1242 * 0 success
1243 * errno error encountered
1246 static int
1247 usf_enc_ie_qosp(struct usfmt *usf, struct ie_generic *ie)
1249 int rc;
1251 ATM_DEBUG2("usf_enc_ie_qosp: usf=%p, ie=%p\n",
1252 usf, ie);
1255 * Encode forward QoS class
1257 if (ie->ie_qosp_fwd_class == T_ATM_ABSENT ||
1258 ie->ie_qosp_bkwd_class == T_ATM_ABSENT)
1259 return(0);
1260 rc = usf_byte(usf, &ie->ie_qosp_fwd_class);
1261 if (rc)
1262 return(rc);
1265 * Encode backward QoS class
1267 rc = usf_byte(usf, &ie->ie_qosp_bkwd_class);
1269 ie->ie_length = 2;
1270 return(rc);
1275 * Encode a broadband repeat indicator information element
1277 * Arguments:
1278 * usf pointer to a unisig formatting structure
1279 * ie pointer to a cell rate IE structure
1281 * Returns:
1282 * 0 success
1283 * errno error encountered
1286 static int
1287 usf_enc_ie_brpi(struct usfmt *usf, struct ie_generic *ie)
1289 int rc;
1290 u_char c;
1292 ATM_DEBUG2("usf_enc_ie_brpi: usf=%p, ie=%p\n",
1293 usf, ie);
1296 * Encode the repeat indicator
1298 c = ie->ie_brpi_ind + UNI_IE_EXT_BIT;
1299 rc = usf_byte(usf, &c);
1301 return(rc);
1306 * Encode a restart indicator information element
1308 * Arguments:
1309 * usf pointer to a unisig formatting structure
1310 * ie pointer to a cell rate IE structure
1312 * Returns:
1313 * 0 success
1314 * errno error encountered
1317 static int
1318 usf_enc_ie_rsti(struct usfmt *usf, struct ie_generic *ie)
1320 int rc;
1321 u_char c;
1323 ATM_DEBUG2("usf_enc_ie_rsti: usf=%p, ie=%p\n",
1324 usf, ie);
1327 * Encode the restart class
1329 c = (ie->ie_rsti_class & UNI_IE_RSTI_CLASS_MASK) |
1330 UNI_IE_EXT_BIT;
1331 rc = usf_byte(usf, &c);
1332 ie->ie_length = 1;
1334 return(rc);
1339 * Encode a broadband sending complete information element
1341 * Arguments:
1342 * usf pointer to a unisig formatting structure
1343 * ie pointer to a broadband sending complete IE structure
1345 * Returns:
1346 * 0 success
1347 * errno error encountered
1350 static int
1351 usf_enc_ie_bsdc(struct usfmt *usf, struct ie_generic *ie)
1353 int rc;
1354 u_char c;
1356 ATM_DEBUG2("usf_enc_ie_bsdc: usf=%p, ie=%p\n",
1357 usf, ie);
1360 * Encode the sending complete indicator
1362 c = UNI_IE_BSDC_IND | UNI_IE_EXT_BIT;
1363 rc = usf_byte(usf, &c);
1364 ie->ie_length = 1;
1366 return(rc);
1371 * Encode a transit network selection information element
1373 * Arguments:
1374 * usf pointer to a unisig formatting structure
1375 * ie pointer to a transit network selection rate IE structure
1377 * Returns:
1378 * 0 success
1379 * errno error encountered
1382 static int
1383 usf_enc_ie_trnt(struct usfmt *usf, struct ie_generic *ie)
1385 int i, rc;
1386 u_char c;
1388 ATM_DEBUG2("usf_enc_ie_trnt: usf=%p, ie=%p\n",
1389 usf, ie);
1392 * Encode the sending complete indicator
1394 c = ((ie->ie_trnt_id_type & UNI_IE_TRNT_IDT_MASK) <<
1395 UNI_IE_TRNT_IDT_SHIFT) +
1396 (ie->ie_trnt_id_plan & UNI_IE_TRNT_IDP_MASK) +
1397 UNI_IE_EXT_BIT;
1398 rc = usf_byte(usf, &c);
1399 if (rc)
1400 return(rc);
1401 ie->ie_length = 1;
1404 * Encode the network identification
1406 for (i=0; i<ie->ie_trnt_id_len; i++) {
1407 rc = usf_byte(usf, &ie->ie_trnt_id[i]);
1408 if (rc)
1409 return(rc);
1410 ie->ie_length++;
1413 return(rc);
1418 * Encode an unsupported IE type
1420 * Arguments:
1421 * usf pointer to a unisig formatting structure
1422 * ie pointer to an IE structure
1424 * Returns:
1425 * 0 success
1428 static int
1429 usf_enc_ie_uimp(struct usfmt *usf, struct ie_generic *ie)
1431 return(0);
1436 * Encode an information element using field identifiers
1438 * The AAL parameters and ATM user cell rate IEs are formatted
1439 * with a one-byte identifier preceeding each field. The routine
1440 * encodes these IEs by using a table which relates the field
1441 * identifiers with the fields in the appropriate IE structure.
1443 * Arguments:
1444 * usf pointer to a unisig formatting structure
1445 * ie pointer to a cell rate IE structure
1446 * tbl pointer to an IE decoding table
1448 * Returns:
1449 * 0 success
1450 * errno error encountered
1453 static int
1454 usf_enc_ie_ident(struct usfmt *usf, struct ie_generic *ie,
1455 struct ie_decode_tbl *tbl)
1457 int i, len, rc;
1458 char *cp;
1459 u_int8_t cv;
1460 u_int16_t sv;
1461 u_int32_t iv;
1463 ATM_DEBUG3("usf_enc_ie_ident: usf=%p, ie=%p, tbl=%p\n",
1464 usf, ie, tbl);
1467 * Scan through the IE table
1469 len = 0;
1470 for (i=0; tbl[i].ident; i++) {
1472 * Check whether to send the field
1474 cp = (char *) ((int)ie + tbl[i].f_offs);
1475 if (tbl[i].len == 0) {
1476 if ((*cp == T_NO || *cp == T_ATM_ABSENT))
1477 continue;
1478 } else {
1479 switch (tbl[i].f_size) {
1480 case 1:
1481 if (*(int8_t *)cp == T_ATM_ABSENT)
1482 continue;
1483 break;
1484 case 2:
1485 if (*(int16_t *)cp == T_ATM_ABSENT)
1486 continue;
1487 break;
1488 case 4:
1489 if (*(int32_t *)cp == T_ATM_ABSENT)
1490 continue;
1491 break;
1492 default:
1493 badtbl:
1494 log(LOG_ERR,
1495 "uni encode: id=%d,len=%d,off=%d,size=%d\n",
1496 tbl[i].ident, tbl[i].len,
1497 tbl[i].f_offs, tbl[i].f_size);
1498 return (EFAULT);
1503 * Encode the field identifier
1505 rc = usf_byte(usf, &tbl[i].ident);
1506 if (rc)
1507 return(rc);
1508 len++;
1511 * Encode the field value
1513 switch (tbl[i].len) {
1514 case 0:
1515 break;
1516 case 1:
1517 switch (tbl[i].f_size) {
1518 case 1:
1519 cv = *(u_int8_t *)cp;
1520 break;
1521 case 2:
1522 cv = *(u_int16_t *)cp;
1523 break;
1524 case 4:
1525 cv = *(u_int32_t *)cp;
1526 break;
1527 default:
1528 goto badtbl;
1530 rc = usf_byte(usf, &cv);
1531 break;
1533 case 2:
1534 switch (tbl[i].f_size) {
1535 case 2:
1536 sv = *(u_int16_t *)cp;
1537 break;
1538 case 4:
1539 sv = *(u_int32_t *)cp;
1540 break;
1541 default:
1542 goto badtbl;
1544 rc = usf_short(usf, &sv);
1545 break;
1547 case 3:
1548 switch (tbl[i].f_size) {
1549 case 4:
1550 iv = *(u_int32_t *)cp;
1551 break;
1552 default:
1553 goto badtbl;
1555 rc = usf_int3(usf, &iv);
1556 break;
1558 case 4:
1559 switch (tbl[i].f_size) {
1560 case 4:
1561 iv = *(u_int32_t *)cp;
1562 break;
1563 default:
1564 goto badtbl;
1566 rc = usf_int(usf, &iv);
1567 break;
1569 default:
1570 goto badtbl;
1573 len += tbl[i].len;
1575 if (rc)
1576 return(rc);
1579 ie->ie_length = len;
1580 return(0);
1585 * Encode an ATM address
1587 * Arguments:
1588 * usf pointer to a unisig formatting structure
1589 * addr pointer to an ATM address structure. The address
1590 * type must already be set correctly.
1592 * Returns:
1593 * 0 success
1594 * errno error encountered
1597 static int
1598 usf_enc_atm_addr(struct usfmt *usf, Atm_addr *addr)
1600 int len, rc;
1601 u_char *cp;
1604 * Check the address type
1606 switch (addr->address_format) {
1607 case T_ATM_E164_ADDR:
1608 cp = (u_char *) addr->address;
1609 len = sizeof(Atm_addr_e164);
1610 break;
1611 case T_ATM_ENDSYS_ADDR:
1612 cp = (u_char *) addr->address;
1613 len = sizeof(Atm_addr_nsap);
1614 break;
1615 default:
1616 return(EINVAL);
1620 * Get the address bytes
1622 while (len) {
1623 rc = usf_byte(usf, cp);
1624 if (rc)
1625 return(rc);
1626 len--;
1627 cp++;
1630 return(0);