kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / unisig_encode.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
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.3 2003/08/07 21:17:35 dillon Exp $
28  */
29
30 /*
31  * ATM Forum UNI 3.0/3.1 Signalling Manager
32  * ----------------------------------------
33  *
34  * Message formatting module
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include "unisig_var.h"
41 #include "unisig_msg.h"
42 #include "unisig_mbuf.h"
43 #include "unisig_decode.h"
44
45 /*
46  * Local functions
47  */
48 static int      usf_enc_ie __P((struct usfmt *, struct ie_generic *));
49 static int      usf_enc_ie_aalp __P((struct usfmt *, struct ie_generic *));
50 static int      usf_enc_ie_clrt __P((struct usfmt *, struct ie_generic *));
51 static int      usf_enc_ie_bbcp __P((struct usfmt *, struct ie_generic *));
52 static int      usf_enc_ie_bhli __P((struct usfmt *, struct ie_generic *));
53 static int      usf_enc_ie_blli __P((struct usfmt *, struct ie_generic *));
54 static int      usf_enc_ie_clst __P((struct usfmt *, struct ie_generic *));
55 static int      usf_enc_ie_cdad __P((struct usfmt *, struct ie_generic *));
56 static int      usf_enc_ie_cdsa __P((struct usfmt *, struct ie_generic *));
57 static int      usf_enc_ie_cgad __P((struct usfmt *, struct ie_generic *));
58 static int      usf_enc_ie_cgsa __P((struct usfmt *, struct ie_generic *));
59 static int      usf_enc_ie_caus __P((struct usfmt *, struct ie_generic *));
60 static int      usf_enc_ie_cnid __P((struct usfmt *, struct ie_generic *));
61 static int      usf_enc_ie_qosp __P((struct usfmt *, struct ie_generic *));
62 static int      usf_enc_ie_brpi __P((struct usfmt *, struct ie_generic *));
63 static int      usf_enc_ie_rsti __P((struct usfmt *, struct ie_generic *));
64 static int      usf_enc_ie_bsdc __P((struct usfmt *, struct ie_generic *));
65 static int      usf_enc_ie_trnt __P((struct usfmt *, struct ie_generic *));
66 static int      usf_enc_ie_uimp __P((struct usfmt *, struct ie_generic *));
67 static int      usf_enc_ie_ident __P((struct usfmt *, struct ie_generic *,
68                         struct ie_decode_tbl *));
69 static int      usf_enc_atm_addr __P((struct usfmt *, Atm_addr *));
70
71
72 /*
73  * Local variables
74  */
75 static struct {
76         u_char  ident;                  /* IE identifier */
77         int     (*encode) __P((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 }
102 };
103
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[];
110
111
112 /*
113  * Encode a UNI signalling message
114  *
115  * Arguments:
116  *      usf     pointer to a unisig formatting structure
117  *      msg     pointer to a signalling message structure
118  *
119  * Returns:
120  *      0       success
121  *      errno   error encountered
122  *
123  */
124 int
125 usf_enc_msg(usf, msg)
126         struct usfmt            *usf;
127         struct unisig_msg       *msg;
128 {
129         int                     i, len, rc;
130         u_char                  c;
131         u_char                  *lp0, *lp1;
132         struct ie_generic       *ie;
133
134         union {
135                 short   s;
136                 u_char  sb[sizeof(short)];
137         } su;
138
139         ATM_DEBUG2("usf_enc_msg: usf=%p, msg=%p\n",
140                         usf, msg);
141
142         /*
143          * Encode the protocol discriminator
144          */
145         c = UNI_MSG_DISC_Q93B;
146         rc = usf_byte(usf, &c);
147         if (rc)
148                 return(rc);
149
150         /*
151          * Encode the call reference length
152          */
153         c = 3;
154         rc = usf_byte(usf, &c);
155         if (rc)
156                 return(rc);
157
158         /*
159          * Encode the call reference
160          */
161         rc = usf_int3(usf, &msg->msg_call_ref);
162         if (rc)
163                 return(rc);
164
165         /*
166          * Encode the message type
167          */
168         rc = usf_byte(usf, &msg->msg_type);
169         if (rc)
170                 return(rc);
171
172         /*
173          * Encode the message type extension
174          */
175         c = ((msg->msg_type_flag & UNI_MSG_TYPE_FLAG_MASK) <<
176                                 UNI_MSG_TYPE_FLAG_SHIFT) +
177                         (msg->msg_type_action & UNI_MSG_TYPE_ACT_MASK) +
178                         UNI_IE_EXT_BIT;
179         rc = usf_byte(usf, &c);
180         if (rc)
181                 return(rc);
182
183         /*
184          * Save the location of the message length and encode a length
185          * of zero for now.  We'll fix the length up at the end.
186          */
187         su.s = 0;
188         rc = usf_byte_mark(usf, &su.sb[sizeof(short)-2], &lp0);
189         if (rc)
190                 return(rc);
191         rc = usf_byte_mark(usf, &su.sb[sizeof(short)-1], &lp1);
192         if (rc)
193                 return(rc);
194
195         /*
196          * Process information elements
197          */
198         len = 0;
199         for (i=0; i<UNI_MSG_IE_CNT; i++) {
200                 ie = msg->msg_ie_vec[i];
201                 while (ie) {
202                         rc = usf_enc_ie(usf, ie);
203                         if (rc)
204                                 return(rc);
205                         len += (ie->ie_length + UNI_IE_HDR_LEN);
206                         ie = ie->ie_next;
207                 }
208         }
209
210         /*
211          * Fix the message length in the encoded message
212          */
213         su.s = htons((u_short)len);
214         *lp0 = su.sb[sizeof(short)-2];
215         *lp1 = su.sb[sizeof(short)-1];
216
217         return(0);
218 }
219
220
221 /*
222  * Encode an information element
223  *
224  * Arguments:
225  *      usf     pointer to a UNISIG formatting structure
226  *      msg     pointer to a UNISIG message structure
227  *      ie      pointer to a generic IE structure
228  *
229  * Returns:
230  *      0       success
231  *      errno   error encountered
232  *
233  */
234 static int
235 usf_enc_ie(usf, ie)
236         struct usfmt            *usf;
237         struct ie_generic       *ie;
238 {
239         int                     i, rc;
240         u_char                  c;
241         u_char                  *lp0, *lp1;
242
243         union {
244                 short   s;
245                 u_char  sb[sizeof(short)];
246         } su;
247
248         ATM_DEBUG2("usf_enc_ie: usf=%p, ie=%p\n",
249                         usf, ie);
250
251         /*
252          * Encode the IE identifier
253          */
254         rc = usf_byte(usf, &ie->ie_ident);
255         if (rc)
256                 return(rc);
257
258         /*
259          * Encode the extended type
260          */
261         c = ((ie->ie_coding & UNI_IE_CODE_MASK) << UNI_IE_CODE_SHIFT) +
262                         ((ie->ie_flag & UNI_IE_FLAG_MASK) <<
263                         UNI_IE_FLAG_SHIFT) +
264                         (ie->ie_action & UNI_IE_ACT_MASK) +
265                         UNI_IE_EXT_BIT;
266         rc = usf_byte(usf, &c);
267         if (rc)
268                 return(rc);
269
270         /*
271          * Mark the current location in the output stream.  Encode a
272          * length of zero for now;  we'll come back and fix it up at
273          * the end.
274          */
275         su.s = 0;
276         rc = usf_byte_mark(usf, &su.sb[sizeof(short)-2], &lp0);
277         if (rc)
278                 return(rc);
279         rc = usf_byte_mark(usf, &su.sb[sizeof(short)-1], &lp1);
280         if (rc)
281                 return(rc);
282
283         /*
284          * Look up the information element in the table
285          */
286         for (i=0; (ie->ie_ident != ie_table[i].ident) &&
287                         (ie_table[i].encode != NULL); i++) {
288         }
289         if (ie_table[i].encode == NULL) {
290                 /*
291                  * Unrecognized IE
292                  */
293                 return(EINVAL);
294         }
295
296         /*
297          * Process the IE by calling the function indicated
298          * in the IE table
299          */
300         rc = ie_table[i].encode(usf, ie);
301         if (rc)
302                 return(rc);
303
304         /*
305          * Set the length in the output stream
306          */
307         su.s = htons((u_short)ie->ie_length);
308         *lp0 = su.sb[sizeof(short)-2];
309         *lp1 = su.sb[sizeof(short)-1];
310
311         return(0);
312 }
313
314
315 /*
316  * Encode an AAL parameters information element
317  *
318  * Arguments:
319  *      usf     pointer to a unisig formatting structure
320  *      ie      pointer to an AAL parms IE structure
321  *
322  * Returns:
323  *      0       success
324  *      errno   error encountered
325  *
326  */
327 static int
328 usf_enc_ie_aalp(usf, ie)
329         struct usfmt            *usf;
330         struct ie_generic       *ie;
331 {
332         int             i, rc = 0;
333
334         ATM_DEBUG2("usf_enc_ie_aalp: usf=%p, ie=%p\n",
335                         usf, ie);
336
337         ie->ie_length = 0;
338
339         /*
340          * Encode the AAL type
341          */
342         if (ie->ie_aalp_aal_type == T_ATM_ABSENT)
343                 return(0);
344         rc = usf_byte(usf, &ie->ie_aalp_aal_type);
345         if (rc)
346                 return(rc);
347
348         /*
349          * Process based on AAL type
350          */
351         switch (ie->ie_aalp_aal_type) {
352                 case UNI_IE_AALP_AT_AAL1:
353                         rc = usf_enc_ie_ident(usf, ie, ie_aal1_tbl);
354                         break;
355                 case UNI_IE_AALP_AT_AAL3:
356                         if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
357                                 rc = usf_enc_ie_ident(usf, ie, ie_aal4_tbl_30);
358                         else
359                                 rc = usf_enc_ie_ident(usf, ie, ie_aal4_tbl_31);
360                         break;
361                 case UNI_IE_AALP_AT_AAL5:
362                         if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
363                                 rc = usf_enc_ie_ident(usf, ie, ie_aal5_tbl_30);
364                         else
365                                 rc = usf_enc_ie_ident(usf, ie, ie_aal5_tbl_31);
366                         break;
367                 case UNI_IE_AALP_AT_AALU:
368                         /*
369                          * Encode the user data
370                          */
371                         i = 0;
372                         while (i < sizeof(ie->ie_aalp_user_info)) {
373                                 rc = usf_byte(usf, &ie->ie_aalp_user_info[i]);
374                                 if (rc)
375                                         break;
376                                 i++;
377                                 ie->ie_length++;
378                         }
379                         break;
380                 default:
381                         return(EINVAL);
382         }
383
384         ie->ie_length++;
385         return(rc);
386 }
387
388
389 /*
390  * Encode a user cell rate information element
391  *
392  * This routine just encodes the parameters required for best
393  * effort service.
394  *
395  * Arguments:
396  *      usf     pointer to a unisig formatting structure
397  *      ie      pointer to a cell rate IE structure
398  *
399  * Returns:
400  *      0       success
401  *      errno   error encountered
402  *
403  */
404 static int
405 usf_enc_ie_clrt(usf, ie)
406         struct usfmt            *usf;
407         struct ie_generic       *ie;
408 {
409         int     rc;
410
411         ATM_DEBUG2("usf_enc_ie_clrt: usf=%p, ie=%p\n",
412                         usf, ie);
413
414 #ifdef NOTDEF
415         /*
416          * Encode Peak Cell Rate Forward CLP = 0 + 1
417          */
418         c = UNI_IE_CLRT_FWD_PEAK_01_ID;
419         rc = usf_byte(usf, &c);
420         if (rc)
421                 return(rc);
422         rc = usf_int3(usf, &ie->ie_clrt_fwd_peak_01);
423         if (rc)
424                 return(rc);
425
426         /*
427          * Encode Peak Cell Rate Backward CLP = 0 + 1
428          */
429         c = UNI_IE_CLRT_BKWD_PEAK_01_ID;
430         rc = usf_byte(usf, &c);
431         if (rc)
432                 return(rc);
433         rc = usf_int3(usf, &ie->ie_clrt_bkwd_peak_01);
434         if (rc)
435                 return(rc);
436
437         /*
438          * Encode Best Effort Flag
439          */
440         c = UNI_IE_CLRT_BEST_EFFORT_ID;
441         rc = usf_byte(usf, &c);
442         if (rc)
443                 return(rc);
444
445         /*
446          * Set IE length
447          */
448         ie->ie_length = 9;
449 #endif
450
451         /*
452          * Encode the user cell rate IE using the table
453          */
454         ie->ie_length = 0;
455         rc = usf_enc_ie_ident(usf, ie, ie_clrt_tbl);
456
457         return(rc);
458 }
459
460
461 /*
462  * Encode a broadband bearer capability information element
463  *
464  * Arguments:
465  *      usf     pointer to a unisig formatting structure
466  *      ie      pointer to a cell rate IE structure
467  *
468  * Returns:
469  *      0       success
470  *      errno   error encountered
471  *
472  */
473 static int
474 usf_enc_ie_bbcp(usf, ie)
475         struct usfmt            *usf;
476         struct ie_generic       *ie;
477 {
478         int     rc;
479         u_char  c;
480
481         ATM_DEBUG2("usf_enc_ie_bbcp: usf=%p, ie=%p\n",
482                         usf, ie);
483
484         ie->ie_length = 0;
485
486         /*
487          * Encode the broadband bearer class
488          */
489         if (ie->ie_bbcp_bearer_class == T_ATM_ABSENT)
490                 return(0);
491         c = ie->ie_bbcp_bearer_class & UNI_IE_BBCP_BC_MASK;
492         if (ie->ie_bbcp_bearer_class != UNI_IE_BBCP_BC_BCOB_X)
493                 c |= UNI_IE_EXT_BIT;
494         rc = usf_byte(usf, &c);
495         if (rc)
496                 return(rc);
497         ie->ie_length++;
498
499         /*
500          * If the broadband bearer class was X, the next
501          * byte has the traffic type and timing requirements
502          */
503         if (ie->ie_bbcp_bearer_class == UNI_IE_BBCP_BC_BCOB_X) {
504                 c = ((ie->ie_bbcp_traffic_type & UNI_IE_BBCP_TT_MASK) <<
505                                 UNI_IE_BBCP_TT_SHIFT) +
506                                 (ie->ie_bbcp_timing_req &
507                                 UNI_IE_BBCP_TR_MASK) +
508                                 UNI_IE_EXT_BIT;
509                 rc = usf_byte(usf, &c);
510                 if (rc)
511                         return(rc);
512                 ie->ie_length++;
513         }
514
515         /*
516          * Encode the clipping and user plane connection configuration
517          */
518         c = ((ie->ie_bbcp_clipping & UNI_IE_BBCP_SC_MASK) <<
519                         UNI_IE_BBCP_SC_SHIFT) +
520                         (ie->ie_bbcp_conn_config &
521                         UNI_IE_BBCP_CC_MASK) +
522                         UNI_IE_EXT_BIT;
523         rc = usf_byte(usf, &c);
524         if (rc)
525                 return(rc);
526         ie->ie_length++;
527
528         return(0);
529 }
530
531
532 /*
533  * Encode a broadband high layer information element
534  *
535  * Arguments:
536  *      usf     pointer to a unisig formatting structure
537  *      ie      pointer to a cell rate IE structure
538  *
539  * Returns:
540  *      0       success
541  *      errno   error encountered
542  *
543  */
544 static int
545 usf_enc_ie_bhli(usf, ie)
546         struct usfmt            *usf;
547         struct ie_generic       *ie;
548 {
549         int     i, rc;
550         u_int   type;
551
552         ATM_DEBUG2("usf_enc_ie_bhli: usf=%p, ie=%p\n",
553                         usf, ie);
554
555         ie->ie_length = 0;
556
557         /*
558          * Encode the high layer information type
559          */
560         if (ie->ie_bhli_type == T_ATM_ABSENT)
561                 return(0);
562         type = ie->ie_bhli_type | UNI_IE_EXT_BIT;
563         rc = usf_ext(usf, &type);
564         if (rc)
565                 return(rc);
566         ie->ie_length++;
567
568         /*
569          * What comes next depends on the type
570          */
571         switch (ie->ie_bhli_type) {
572         case UNI_IE_BHLI_TYPE_ISO:
573         case UNI_IE_BHLI_TYPE_USER:
574                 /*
575                  * ISO or user-specified parameters -- take the
576                  * length of information from the IE length
577                  */
578                 for (i=0; i<ie->ie_length-1; i++) {
579                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
580                         if (rc)
581                                 return(rc);
582                         ie->ie_length++;
583                 }
584                 break;
585         case UNI_IE_BHLI_TYPE_HLP:
586                 /*
587                  * Make sure the IE is long enough for the high
588                  * layer profile information, then get it
589                  */
590                 if (usf->usf_sig->us_proto != ATM_SIG_UNI30)
591                         return (EINVAL);
592                 for (i=0; i<UNI_IE_BHLI_HLP_LEN; i++) {
593                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
594                         if (rc)
595                                 return(rc);
596                         ie->ie_length++;
597                 }
598                 break;
599         case UNI_IE_BHLI_TYPE_VSA:
600                 /*
601                  * Make sure the IE is long enough for the vendor-
602                  * specific application information, then get it
603                  */
604                 for (i=0; i<UNI_IE_BHLI_VSA_LEN; i++) {
605                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
606                         if (rc)
607                                 return(rc);
608                         ie->ie_length++;
609                 }
610                 break;
611         default:
612                 return(EINVAL);
613         }
614
615         return(0);
616 }
617
618
619 /*
620  * Encode a broadband low layer information element
621  *
622  * Arguments:
623  *      usf     pointer to a unisig formatting structure
624  *      ie      pointer to a cell rate IE structure
625  *
626  * Returns:
627  *      0       success
628  *      errno   error encountered
629  *
630  */
631 static int
632 usf_enc_ie_blli(usf, ie)
633         struct usfmt            *usf;
634         struct ie_generic       *ie;
635 {
636         u_char          c;
637         int             rc;
638         u_int           ipi;
639
640         ATM_DEBUG2("usf_enc_ie_blli: usf=%p, ie=%p\n",
641                         usf, ie);
642
643         ie->ie_length = 0;
644
645         /*
646          * Encode paramteters for whichever protocol layers the
647          * user specified
648          */
649
650         /*
651          * Layer 1 information
652          */
653         if (ie->ie_blli_l1_id && ie->ie_blli_l1_id != T_ATM_ABSENT) {
654                 c = (UNI_IE_BLLI_L1_ID << UNI_IE_BLLI_LID_SHIFT) +
655                                 (ie->ie_blli_l1_id &
656                                 UNI_IE_BLLI_LP_MASK) +
657                                 UNI_IE_EXT_BIT;
658                 rc = usf_byte(usf, &c);
659                 if (rc)
660                         return(rc);
661                 ie->ie_length++;
662         }
663
664         /*
665          * Layer 2 information
666          */
667         if (ie->ie_blli_l2_id && ie->ie_blli_l2_id != T_ATM_ABSENT) {
668                 c = (UNI_IE_BLLI_L2_ID << UNI_IE_BLLI_LID_SHIFT) +
669                                 (ie->ie_blli_l2_id &
670                                 UNI_IE_BLLI_LP_MASK);
671
672                 switch (ie->ie_blli_l2_id) {
673                 case UNI_IE_BLLI_L2P_X25L:
674                 case UNI_IE_BLLI_L2P_X25M:
675                 case UNI_IE_BLLI_L2P_HDLC1:
676                 case UNI_IE_BLLI_L2P_HDLC2:
677                 case UNI_IE_BLLI_L2P_HDLC3:
678                 case UNI_IE_BLLI_L2P_Q922:
679                 case UNI_IE_BLLI_L2P_ISO7776:
680                         /*
681                          * Write the Layer 2 type
682                          */
683                         rc = usf_byte(usf, &c);
684                         if (rc)
685                                 return(rc);
686                         ie->ie_length++;
687
688                         /*
689                          * Encode the Layer 2 mode
690                          */
691                         if (ie->ie_blli_l2_mode) {
692                                 c = (ie->ie_blli_l2_mode &
693                                         UNI_IE_BLLI_L2MODE_MASK) <<
694                                         UNI_IE_BLLI_L2MODE_SHIFT;
695                                 if (!ie->ie_blli_l2_window)
696                                         c |= UNI_IE_EXT_BIT;
697
698                                 rc = usf_byte(usf, &c);
699                                 if (rc)
700                                         return(rc);
701                                 ie->ie_length++;
702                         }
703
704                         /*
705                          * Encode the Layer 2 window size
706                          */
707                         if (ie->ie_blli_l2_window) {
708                                 c = (ie->ie_blli_l2_window &
709                                                 UNI_IE_EXT_MASK) +
710                                                 UNI_IE_EXT_BIT;
711
712                                 rc = usf_byte(usf, &c);
713                                 if (rc)
714                                         return(rc);
715                                 ie->ie_length++;
716                         }
717                         break;
718                 case UNI_IE_BLLI_L2P_USER:
719                         /*
720                          * Write the Layer 2 type
721                          */
722                         rc = usf_byte(usf, &c);
723                         if (rc)
724                                 return(rc);
725                         ie->ie_length++;
726
727                         /*
728                          * Encode the user-specified layer 2 info
729                          */
730                         c = (ie->ie_blli_l2_user_proto &
731                                         UNI_IE_EXT_MASK) +
732                                         UNI_IE_EXT_BIT;
733                         rc = usf_byte(usf, &c);
734                         if (rc)
735                                 return(rc);
736                         ie->ie_length++;
737                         break;
738                 default:
739                         /*
740                          * Write the Layer 2 type
741                          */
742                         c |= UNI_IE_EXT_BIT;
743                         rc = usf_byte(usf, &c);
744                         if (rc)
745                                 return(rc);
746                         ie->ie_length++;
747                         break;
748                 }
749         }
750
751         /*
752          * Layer 3 information
753          */
754         if (ie->ie_blli_l3_id && ie->ie_blli_l3_id != T_ATM_ABSENT) {
755                 /*
756                  * Encode the layer 3 protocol ID
757                  */
758                 c = (UNI_IE_BLLI_L3_ID << UNI_IE_BLLI_LID_SHIFT) +
759                                 (ie->ie_blli_l3_id &
760                                 UNI_IE_BLLI_LP_MASK);
761
762                 /*
763                  * Process other fields based on protocol ID
764                  */
765                 switch(ie->ie_blli_l3_id) {
766                 case UNI_IE_BLLI_L3P_X25:
767                 case UNI_IE_BLLI_L3P_ISO8208:
768                 case UNI_IE_BLLI_L3P_ISO8878:
769                         /*
770                          * Write the protocol ID
771                          */
772                         rc = usf_byte(usf, &c);
773                         if (rc)
774                                 return(rc);
775                         ie->ie_length++;
776
777                         if (ie->ie_blli_l3_mode ||
778                                         ie->ie_blli_l3_packet_size ||
779                                         ie->ie_blli_l3_window) {
780                                 c = (ie->ie_blli_l3_mode &
781                                         UNI_IE_BLLI_L3MODE_MASK) <<
782                                         UNI_IE_BLLI_L3MODE_SHIFT;
783                                 if (!ie->ie_blli_l3_packet_size &&
784                                                 !ie->ie_blli_l3_window)
785                                         c |= UNI_IE_EXT_BIT;
786
787                                 rc = usf_byte(usf, &c);
788                                 if (rc)
789                                         return(rc);
790                                 ie->ie_length++;
791                         }
792
793                         if (ie->ie_blli_l3_packet_size ||
794                                         ie->ie_blli_l3_window) {
795                                 c = ie->ie_blli_l3_packet_size &
796                                                 UNI_IE_BLLI_L3PS_MASK;
797                                 if (!ie->ie_blli_l3_window)
798                                         c |= UNI_IE_EXT_BIT;
799
800                                 rc = usf_byte(usf, &c);
801                                 if (rc)
802                                         return(rc);
803                                 ie->ie_length++;
804                         }
805
806                         if (ie->ie_blli_l3_window) {
807                                 c = (ie->ie_blli_l3_window &
808                                                 UNI_IE_EXT_MASK) +
809                                                 UNI_IE_EXT_BIT;
810
811                                 rc = usf_byte(usf, &c);
812                                 if (rc)
813                                         return(rc);
814                                 ie->ie_length++;
815                         }
816                         break;
817                 case UNI_IE_BLLI_L3P_USER:
818                         /*
819                          * Write the protocol ID
820                          */
821                         rc = usf_byte(usf, &c);
822                         if (rc)
823                                 return(rc);
824                         ie->ie_length++;
825
826                         /*
827                          * Encode the user-specified protocol info
828                          */
829                         c = (ie->ie_blli_l3_user_proto &
830                                                 UNI_IE_EXT_MASK) +
831                                                 UNI_IE_EXT_BIT;
832
833                         rc = usf_byte(usf, &c);
834                         if (rc)
835                                 return(rc);
836                         ie->ie_length++;
837                         break;
838                 case UNI_IE_BLLI_L3P_ISO9577:
839                         /*
840                          * Write the protocol ID
841                          */
842                         rc = usf_byte(usf, &c);
843                         if (rc)
844                                 return(rc);
845                         ie->ie_length++;
846
847                         /*
848                          * Encode the IPI
849                          */
850                         ipi = ie->ie_blli_l3_ipi <<
851                                         UNI_IE_BLLI_L3IPI_SHIFT;
852                         rc = usf_ext(usf, &ipi);
853                         if (rc)
854                                 return(rc);
855                         ie->ie_length += 2;
856
857                         if (ie->ie_blli_l3_ipi ==
858                                         UNI_IE_BLLI_L3IPI_SNAP) {
859                                 c = UNI_IE_EXT_BIT;
860                                 rc = usf_byte(usf, &c);
861                                 if (rc)
862                                         return(rc);
863
864                                 rc = usf_byte(usf,
865                                                 &ie->ie_blli_l3_oui[0]);
866                                 if (rc)
867                                         return(rc);
868
869                                 rc = usf_byte(usf,
870                                                 &ie->ie_blli_l3_oui[1]);
871                                 if (rc)
872                                         return(rc);
873
874                                 rc = usf_byte(usf,
875                                                 &ie->ie_blli_l3_oui[2]);
876                                 if (rc)
877                                         return(rc);
878
879                                 rc = usf_byte(usf,
880                                                 &ie->ie_blli_l3_pid[0]);
881                                 if (rc)
882                                         return(rc);
883
884                                 rc = usf_byte(usf,
885                                                 &ie->ie_blli_l3_pid[1]);
886                                 if (rc)
887                                         return(rc);
888
889                                 ie->ie_length += 6;
890                         }
891                         break;
892                 default:
893                         /*
894                          * Write the layer 3 protocol ID
895                          */
896                         c |= UNI_IE_EXT_BIT;
897                         rc = usf_byte(usf, &c);
898                         if (rc)
899                                 return(rc);
900                         ie->ie_length++;
901                         break;
902                 }
903         }
904
905         return(0);
906 }
907
908
909 /*
910  * Encode a call state information element
911  *
912  * Arguments:
913  *      usf     pointer to a unisig formatting structure
914  *      ie      pointer to a cell rate IE structure
915  *
916  * Returns:
917  *      0       success
918  *      errno   error encountered
919  *
920  */
921 static int
922 usf_enc_ie_clst(usf, ie)
923         struct usfmt            *usf;
924         struct ie_generic       *ie;
925 {
926         int     rc;
927         u_char  c;
928
929         ATM_DEBUG2("usf_enc_ie_clst: usf=%p, ie=%p\n",
930                         usf, ie);
931
932         c = ie->ie_clst_state & UNI_IE_CLST_STATE_MASK;
933         rc = usf_byte(usf, &c);
934         if (rc)
935                 return(rc);
936         ie->ie_length = 1;
937
938         return(0);
939 }
940
941
942 /*
943  * Encode a called party number information element
944  *
945  * Arguments:
946  *      usf     pointer to a unisig formatting structure
947  *      ie      pointer to a cell rate IE structure
948  *
949  * Returns:
950  *      0       success
951  *      errno   error encountered
952  *
953  */
954 static int
955 usf_enc_ie_cdad(usf, ie)
956         struct usfmt            *usf;
957         struct ie_generic       *ie;
958 {
959         u_char  c;
960         int     rc;
961
962         ATM_DEBUG2("usf_enc_ie_cdad: usf=%p, ie=%p\n",
963                         usf, ie);
964
965         /*
966          * Encode the numbering plan
967          */
968         switch(ie->ie_cdad_addr.address_format) {
969         case T_ATM_E164_ADDR:
970                 c = UNI_IE_CDAD_PLAN_E164 +
971                                 (UNI_IE_CDAD_TYPE_INTL
972                                         << UNI_IE_CDAD_TYPE_SHIFT);
973                 ie->ie_length = sizeof(Atm_addr_e164) + 1;
974                 break;
975         case T_ATM_ENDSYS_ADDR:
976                 c = UNI_IE_CDAD_PLAN_NSAP +
977                                 (UNI_IE_CDAD_TYPE_UNK
978                                         << UNI_IE_CDAD_TYPE_SHIFT);
979                 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
980                 break;
981         default:
982                 return(EINVAL);
983         }
984         c |= UNI_IE_EXT_BIT;
985         rc = usf_byte(usf, &c);
986         if (rc)
987                 return(rc);
988
989         /*
990          * Encode the ATM address
991          */
992         rc = usf_enc_atm_addr(usf, &ie->ie_cdad_addr);
993
994         return(rc);
995 }
996
997
998 /*
999  * Encode a called party subaddress information element
1000  *
1001  * Arguments:
1002  *      usf     pointer to a unisig formatting structure
1003  *      ie      pointer to a cell rate IE structure
1004  *
1005  * Returns:
1006  *      0       success
1007  *      errno   error encountered
1008  *
1009  */
1010 static int
1011 usf_enc_ie_cdsa(usf, ie)
1012         struct usfmt            *usf;
1013         struct ie_generic       *ie;
1014 {
1015         u_char  c;
1016         int     rc;
1017
1018         /*
1019          * Encode the subaddress type
1020          */
1021         switch(ie->ie_cdsa_addr.address_format) {
1022         case T_ATM_ENDSYS_ADDR:
1023                 c = UNI_IE_CDSA_TYPE_AESA << UNI_IE_CDSA_TYPE_SHIFT;
1024                 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
1025                 break;
1026         default:
1027                 return(EINVAL);
1028         }
1029         c |= UNI_IE_EXT_BIT;
1030         rc = usf_byte(usf, &c);
1031         if (rc)
1032                 return(rc);
1033
1034         /*
1035          * Encode the ATM address
1036          */
1037         rc = usf_enc_atm_addr(usf, &ie->ie_cdsa_addr);
1038
1039         return(rc);
1040 }
1041
1042
1043 /*
1044  * Encode a calling party number information element
1045  *
1046  * Arguments:
1047  *      usf     pointer to a unisig formatting structure
1048  *      ie      pointer to a cell rate IE structure
1049  *
1050  * Returns:
1051  *      0       success
1052  *      errno   error encountered
1053  *
1054  */
1055 static int
1056 usf_enc_ie_cgad(usf, ie)
1057         struct usfmt            *usf;
1058         struct ie_generic       *ie;
1059 {
1060         u_char  c;
1061         int     rc;
1062
1063         ATM_DEBUG2("usf_enc_ie_cgad: usf=%p, ie=%p\n",
1064                         usf, ie);
1065
1066         /*
1067          * Encode the numbering plan
1068          */
1069         switch(ie->ie_cgad_addr.address_format) {
1070         case T_ATM_E164_ADDR:
1071                 c = UNI_IE_CGAD_PLAN_E164 +
1072                                 (UNI_IE_CGAD_TYPE_INTL
1073                                         << UNI_IE_CGAD_TYPE_SHIFT) +
1074                                 UNI_IE_EXT_BIT;
1075                 ie->ie_length = sizeof(Atm_addr_e164) + 1;
1076                 break;
1077         case T_ATM_ENDSYS_ADDR:
1078                 c = UNI_IE_CGAD_PLAN_NSAP +
1079                                 (UNI_IE_CGAD_TYPE_UNK
1080                                         << UNI_IE_CGAD_TYPE_SHIFT) +
1081                                 UNI_IE_EXT_BIT;
1082                 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
1083                 break;
1084         default:
1085                 return(EINVAL);
1086         }
1087         rc = usf_byte(usf, &c);
1088         if (rc)
1089                 return(rc);
1090
1091         /*
1092          * Encode the presentation and screening indicators
1093          */
1094 #ifdef NOTDEF
1095         c = ((ie->ie_cgad_pres_ind & UNI_IE_CGAD_PRES_MASK)
1096                                 << UNI_IE_CGAD_PRES_SHIFT) +
1097                         (ie->ie_cgad_screen_ind &
1098                                 UNI_IE_CGAD_SCR_MASK) +
1099                         UNI_IE_EXT_BIT;
1100         rc = usf_byte(usf, &c);
1101         if (rc)
1102                 return(rc);
1103 #endif
1104         
1105
1106         /*
1107          * Encode the ATM address
1108          */
1109         rc = usf_enc_atm_addr(usf, &ie->ie_cgad_addr);
1110
1111         return(rc);
1112 }
1113
1114
1115 /*
1116  * Encode a calling party subaddress information element
1117  *
1118  * Arguments:
1119  *      usf     pointer to a unisig formatting structure
1120  *      ie      pointer to a cell rate IE structure
1121  *
1122  * Returns:
1123  *      0       success
1124  *      errno   error encountered
1125  *
1126  */
1127 static int
1128 usf_enc_ie_cgsa(usf, ie)
1129         struct usfmt            *usf;
1130         struct ie_generic       *ie;
1131 {
1132         u_char  c;
1133         int     rc;
1134
1135         /*
1136          * Encode the subaddress type
1137          */
1138         switch(ie->ie_cgsa_addr.address_format) {
1139         case T_ATM_ENDSYS_ADDR:
1140                 c = UNI_IE_CGSA_TYPE_AESA << UNI_IE_CGSA_TYPE_SHIFT;
1141                 ie->ie_length = sizeof(Atm_addr_nsap) + 1;
1142                 break;
1143         default:
1144                 return(EINVAL);
1145         }
1146         c |= UNI_IE_EXT_BIT;
1147         rc = usf_byte(usf, &c);
1148         if (rc)
1149                 return(rc);
1150
1151         /*
1152          * Encode the ATM address
1153          */
1154         rc = usf_enc_atm_addr(usf, &ie->ie_cgsa_addr);
1155
1156         return(rc);
1157 }
1158
1159
1160 /*
1161  * Encode a cause information element
1162  *
1163  * Arguments:
1164  *      usf     pointer to a unisig formatting structure
1165  *      ie      pointer to a cell rate IE structure
1166  *
1167  * Returns:
1168  *      0       success
1169  *      errno   error encountered
1170  *
1171  */
1172 static int
1173 usf_enc_ie_caus(usf, ie)
1174         struct usfmt            *usf;
1175         struct ie_generic       *ie;
1176 {
1177         int                     i, rc;
1178         u_char                  c;
1179
1180         ATM_DEBUG2("usf_enc_ie_caus: usf=%p, ie=%p\n",
1181                         usf, ie);
1182
1183         ie->ie_length = 0;
1184
1185         /*
1186          * Encode the cause location
1187          */
1188         c = (ie->ie_caus_loc & UNI_IE_CAUS_LOC_MASK) | UNI_IE_EXT_BIT;
1189         rc = usf_byte(usf, &c);
1190         if (rc)
1191                 return(rc);
1192         ie->ie_length++;
1193
1194         /*
1195          * Encode the cause value
1196          */
1197         c = ie->ie_caus_cause | UNI_IE_EXT_BIT;
1198         rc = usf_byte(usf, &c);
1199         if (rc)
1200                 return(rc);
1201         ie->ie_length++;
1202
1203         /*
1204          * Encode any included diagnostics
1205          */
1206         for (i = 0; i < ie->ie_caus_diag_len &&
1207                         i < sizeof(ie->ie_caus_diagnostic);
1208                         i++) {
1209                 rc = usf_byte(usf, &ie->ie_caus_diagnostic[i]);
1210                 if (rc)
1211                         return(rc);
1212                 ie->ie_length++;
1213         }
1214
1215         return(0);
1216 }
1217
1218
1219 /*
1220  * Encode a conection identifier information element
1221  *
1222  * Arguments:
1223  *      usf     pointer to a unisig formatting structure
1224  *      ie      pointer to a cell rate IE structure
1225  *
1226  * Returns:
1227  *      0       success
1228  *      errno   error encountered
1229  *
1230  */
1231 static int
1232 usf_enc_ie_cnid(usf, ie)
1233         struct usfmt            *usf;
1234         struct ie_generic       *ie;
1235 {
1236         int     rc;
1237         u_char  c;
1238
1239         ATM_DEBUG2("usf_enc_ie_cnid: usf=%p, ie=%p\n",
1240                         usf, ie);
1241
1242         c = ((ie->ie_cnid_vp_sig & UNI_IE_CNID_VPSIG_MASK)
1243                                 << UNI_IE_CNID_VPSIG_SHIFT) +
1244                         (ie->ie_cnid_pref_excl & UNI_IE_CNID_PREX_MASK) +
1245                         UNI_IE_EXT_BIT;
1246         rc = usf_byte(usf, &c);
1247         if (rc)
1248                 return(rc);
1249
1250         rc = usf_short(usf, &ie->ie_cnid_vpci);
1251         if (rc)
1252                 return(rc);
1253         rc = usf_short(usf, &ie->ie_cnid_vci);
1254         if (rc)
1255                 return(rc);
1256
1257         ie->ie_length = 5;
1258         return(0);
1259 }
1260
1261
1262 /*
1263  * Encode a quality of service parameters information element
1264  *
1265  * Arguments:
1266  *      usf     pointer to a unisig formatting structure
1267  *      ie      pointer to a cell rate IE structure
1268  *
1269  * Returns:
1270  *      0       success
1271  *      errno   error encountered
1272  *
1273  */
1274 static int
1275 usf_enc_ie_qosp(usf, ie)
1276         struct usfmt            *usf;
1277         struct ie_generic       *ie;
1278 {
1279         int             rc;
1280
1281         ATM_DEBUG2("usf_enc_ie_qosp: usf=%p, ie=%p\n",
1282                         usf, ie);
1283
1284         /*
1285          * Encode forward QoS class
1286          */
1287         if (ie->ie_qosp_fwd_class == T_ATM_ABSENT ||
1288                         ie->ie_qosp_bkwd_class == T_ATM_ABSENT)
1289                 return(0);
1290         rc = usf_byte(usf, &ie->ie_qosp_fwd_class);
1291         if (rc)
1292                 return(rc);
1293
1294         /*
1295          * Encode backward QoS class
1296          */
1297         rc = usf_byte(usf, &ie->ie_qosp_bkwd_class);
1298
1299         ie->ie_length = 2;
1300         return(rc);
1301 }
1302
1303
1304 /*
1305  * Encode a broadband repeat indicator information element
1306  *
1307  * Arguments:
1308  *      usf     pointer to a unisig formatting structure
1309  *      ie      pointer to a cell rate IE structure
1310  *
1311  * Returns:
1312  *      0       success
1313  *      errno   error encountered
1314  *
1315  */
1316 static int
1317 usf_enc_ie_brpi(usf, ie)
1318         struct usfmt            *usf;
1319         struct ie_generic       *ie;
1320 {
1321         int     rc;
1322         u_char  c;
1323
1324         ATM_DEBUG2("usf_enc_ie_brpi: usf=%p, ie=%p\n",
1325                         usf, ie);
1326
1327         /*
1328          * Encode the repeat indicator
1329          */
1330         c = ie->ie_brpi_ind + UNI_IE_EXT_BIT;
1331         rc = usf_byte(usf, &c);
1332
1333         return(rc);
1334 }
1335
1336
1337 /*
1338  * Encode a restart indicator information element
1339  *
1340  * Arguments:
1341  *      usf     pointer to a unisig formatting structure
1342  *      ie      pointer to a cell rate IE structure
1343  *
1344  * Returns:
1345  *      0       success
1346  *      errno   error encountered
1347  *
1348  */
1349 static int
1350 usf_enc_ie_rsti(usf, ie)
1351         struct usfmt            *usf;
1352         struct ie_generic       *ie;
1353 {
1354         int     rc;
1355         u_char  c;
1356
1357         ATM_DEBUG2("usf_enc_ie_rsti: usf=%p, ie=%p\n",
1358                         usf, ie);
1359
1360         /*
1361          * Encode the restart class
1362          */
1363         c = (ie->ie_rsti_class & UNI_IE_RSTI_CLASS_MASK) |
1364                         UNI_IE_EXT_BIT;
1365         rc = usf_byte(usf, &c);
1366         ie->ie_length = 1;
1367
1368         return(rc);
1369 }
1370
1371
1372 /*
1373  * Encode a broadband sending complete information element
1374  *
1375  * Arguments:
1376  *      usf     pointer to a unisig formatting structure
1377  *      ie      pointer to a broadband sending complete IE structure
1378  *
1379  * Returns:
1380  *      0       success
1381  *      errno   error encountered
1382  *
1383  */
1384 static int
1385 usf_enc_ie_bsdc(usf, ie)
1386         struct usfmt            *usf;
1387         struct ie_generic       *ie;
1388 {
1389         int     rc;
1390         u_char  c;
1391
1392         ATM_DEBUG2("usf_enc_ie_bsdc: usf=%p, ie=%p\n",
1393                         usf, ie);
1394
1395         /*
1396          * Encode the sending complete indicator
1397          */
1398         c = UNI_IE_BSDC_IND | UNI_IE_EXT_BIT;
1399         rc = usf_byte(usf, &c);
1400         ie->ie_length = 1;
1401
1402         return(rc);
1403 }
1404
1405
1406 /*
1407  * Encode a transit network selection information element
1408  *
1409  * Arguments:
1410  *      usf     pointer to a unisig formatting structure
1411  *      ie      pointer to a transit network selection rate IE structure
1412  *
1413  * Returns:
1414  *      0       success
1415  *      errno   error encountered
1416  *
1417  */
1418 static int
1419 usf_enc_ie_trnt(usf, ie)
1420         struct usfmt            *usf;
1421         struct ie_generic       *ie;
1422 {
1423         int     i, rc;
1424         u_char  c;
1425
1426         ATM_DEBUG2("usf_enc_ie_trnt: usf=%p, ie=%p\n",
1427                         usf, ie);
1428
1429         /*
1430          * Encode the sending complete indicator
1431          */
1432         c = ((ie->ie_trnt_id_type & UNI_IE_TRNT_IDT_MASK) <<
1433                                 UNI_IE_TRNT_IDT_SHIFT) +
1434                         (ie->ie_trnt_id_plan & UNI_IE_TRNT_IDP_MASK) +
1435                         UNI_IE_EXT_BIT;
1436         rc = usf_byte(usf, &c);
1437         if (rc)
1438                 return(rc);
1439         ie->ie_length = 1;
1440
1441         /*
1442          * Encode the network identification
1443          */
1444         for (i=0; i<ie->ie_trnt_id_len; i++) {
1445                 rc = usf_byte(usf, &ie->ie_trnt_id[i]);
1446                 if (rc)
1447                         return(rc);
1448                 ie->ie_length++;
1449         }
1450
1451         return(rc);
1452 }
1453
1454
1455 /*
1456  * Encode an unsupported IE type
1457  *
1458  * Arguments:
1459  *      usf     pointer to a unisig formatting structure
1460  *      ie      pointer to an IE structure
1461  *
1462  * Returns:
1463  *      0       success
1464  *
1465  */
1466 static int
1467 usf_enc_ie_uimp(usf, ie)
1468         struct usfmt            *usf;
1469         struct ie_generic       *ie;
1470 {
1471         return(0);
1472 }
1473
1474
1475 /*
1476  * Encode an information element using field identifiers
1477  *
1478  * The AAL parameters and ATM user cell rate IEs are formatted
1479  * with a one-byte identifier preceeding each field.  The routine
1480  * encodes these IEs by using a table which relates the field
1481  * identifiers with the fields in the appropriate IE structure.
1482  *
1483  * Arguments:
1484  *      usf     pointer to a unisig formatting structure
1485  *      ie      pointer to a cell rate IE structure
1486  *      tbl     pointer to an IE decoding table
1487  *
1488  * Returns:
1489  *      0       success
1490  *      errno   error encountered
1491  *
1492  */
1493 static int
1494 usf_enc_ie_ident(usf, ie, tbl)
1495         struct usfmt            *usf;
1496         struct ie_generic       *ie;
1497         struct ie_decode_tbl    *tbl;
1498 {
1499         int     i, len, rc;
1500         char    *cp;
1501         u_int8_t        cv;
1502         u_int16_t       sv;
1503         u_int32_t       iv;
1504
1505         ATM_DEBUG3("usf_enc_ie_ident: usf=%p, ie=%p, tbl=%p\n",
1506                         usf, ie, tbl);
1507
1508         /*
1509          * Scan through the IE table
1510          */
1511         len = 0;
1512         for (i=0; tbl[i].ident; i++) {
1513                 /*
1514                  * Check whether to send the field
1515                  */
1516                 cp = (char *) ((int)ie + tbl[i].f_offs);
1517                 if (tbl[i].len == 0) {
1518                         if ((*cp == T_NO || *cp == T_ATM_ABSENT))
1519                                 continue;
1520                 } else {
1521                         switch (tbl[i].f_size) {
1522                         case 1:
1523                                 if (*(int8_t *)cp == T_ATM_ABSENT)
1524                                         continue;
1525                                 break;
1526                         case 2:
1527                                 if (*(int16_t *)cp == T_ATM_ABSENT)
1528                                         continue;
1529                                 break;
1530                         case 4:
1531                                 if (*(int32_t *)cp == T_ATM_ABSENT)
1532                                         continue;
1533                                 break;
1534                         default:
1535 badtbl:
1536                                 log(LOG_ERR,
1537                                     "uni encode: id=%d,len=%d,off=%d,size=%d\n",
1538                                         tbl[i].ident, tbl[i].len,
1539                                         tbl[i].f_offs, tbl[i].f_size);
1540                                 return (EFAULT);
1541                         }
1542                 }
1543
1544                 /*
1545                  * Encode the field identifier
1546                  */
1547                 rc = usf_byte(usf, &tbl[i].ident);
1548                 if (rc)
1549                         return(rc);
1550                 len++;
1551
1552                 /*
1553                  * Encode the field value
1554                  */
1555                 switch (tbl[i].len) {
1556                         case 0:
1557                                 break;
1558                         case 1:
1559                                 switch (tbl[i].f_size) {
1560                                 case 1:
1561                                         cv = *(u_int8_t *)cp;
1562                                         break;
1563                                 case 2:
1564                                         cv = *(u_int16_t *)cp;
1565                                         break;
1566                                 case 4:
1567                                         cv = *(u_int32_t *)cp;
1568                                         break;
1569                                 default:
1570                                         goto badtbl;
1571                                 }
1572                                 rc = usf_byte(usf, &cv);
1573                                 break;
1574
1575                         case 2:
1576                                 switch (tbl[i].f_size) {
1577                                 case 2:
1578                                         sv = *(u_int16_t *)cp;
1579                                         break;
1580                                 case 4:
1581                                         sv = *(u_int32_t *)cp;
1582                                         break;
1583                                 default:
1584                                         goto badtbl;
1585                                 }
1586                                 rc = usf_short(usf, &sv);
1587                                 break;
1588
1589                         case 3:
1590                                 switch (tbl[i].f_size) {
1591                                 case 4:
1592                                         iv = *(u_int32_t *)cp;
1593                                         break;
1594                                 default:
1595                                         goto badtbl;
1596                                 }
1597                                 rc = usf_int3(usf, &iv);
1598                                 break;
1599
1600                         case 4:
1601                                 switch (tbl[i].f_size) {
1602                                 case 4:
1603                                         iv = *(u_int32_t *)cp;
1604                                         break;
1605                                 default:
1606                                         goto badtbl;
1607                                 }
1608                                 rc = usf_int(usf, &iv);
1609                                 break;
1610
1611                         default:
1612                                 goto badtbl;
1613                 }
1614
1615                 len += tbl[i].len;
1616
1617                 if (rc)
1618                         return(rc);
1619         }
1620
1621         ie->ie_length = len;
1622         return(0);
1623 }
1624
1625
1626 /*
1627  * Encode an ATM address
1628  *
1629  * Arguments:
1630  *      usf     pointer to a unisig formatting structure
1631  *      addr    pointer to an ATM address structure.  The address
1632  *              type must already be set correctly.
1633  *
1634  * Returns:
1635  *      0       success
1636  *      errno   error encountered
1637  *
1638  */
1639 static int
1640 usf_enc_atm_addr(usf, addr)
1641         struct usfmt    *usf;
1642         Atm_addr        *addr;
1643 {
1644         int     len, rc;
1645         u_char  *cp;
1646
1647         /*
1648          * Check the address type
1649          */
1650         switch (addr->address_format) {
1651         case T_ATM_E164_ADDR:
1652                 cp = (u_char *) addr->address;
1653                 len = sizeof(Atm_addr_e164);
1654                 break;
1655         case T_ATM_ENDSYS_ADDR:
1656                 cp = (u_char *) addr->address;
1657                 len = sizeof(Atm_addr_nsap);
1658                 break;
1659         default:
1660                 return(EINVAL);
1661         }
1662
1663         /*
1664          * Get the address bytes
1665          */
1666         while (len) {
1667                 rc = usf_byte(usf, cp);
1668                 if (rc)
1669                         return(rc);
1670                 len--;
1671                 cp++;
1672         }
1673
1674         return(0);
1675 }