kernel: Sync ACPICA with Intel's version 20140424.
[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.6 2006/01/14 13:36:39 swildner 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 <netproto/atm/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 (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 *);
70
71
72 /*
73  * Local variables
74  */
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 }
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(struct usfmt *usf, struct unisig_msg *msg)
126 {
127         int                     i, len, rc;
128         u_char                  c;
129         u_char                  *lp0, *lp1;
130         struct ie_generic       *ie;
131
132         union {
133                 short   s;
134                 u_char  sb[sizeof(short)];
135         } su;
136
137         ATM_DEBUG2("usf_enc_msg: usf=%p, msg=%p\n",
138                         usf, msg);
139
140         /*
141          * Encode the protocol discriminator
142          */
143         c = UNI_MSG_DISC_Q93B;
144         rc = usf_byte(usf, &c);
145         if (rc)
146                 return(rc);
147
148         /*
149          * Encode the call reference length
150          */
151         c = 3;
152         rc = usf_byte(usf, &c);
153         if (rc)
154                 return(rc);
155
156         /*
157          * Encode the call reference
158          */
159         rc = usf_int3(usf, &msg->msg_call_ref);
160         if (rc)
161                 return(rc);
162
163         /*
164          * Encode the message type
165          */
166         rc = usf_byte(usf, &msg->msg_type);
167         if (rc)
168                 return(rc);
169
170         /*
171          * Encode the message type extension
172          */
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);
180
181         /*
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.
184          */
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);
192
193         /*
194          * Process information elements
195          */
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;
205                 }
206         }
207
208         /*
209          * Fix the message length in the encoded message
210          */
211         su.s = htons((u_short)len);
212         *lp0 = su.sb[sizeof(short)-2];
213         *lp1 = su.sb[sizeof(short)-1];
214
215         return(0);
216 }
217
218
219 /*
220  * Encode an information element
221  *
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
226  *
227  * Returns:
228  *      0       success
229  *      errno   error encountered
230  *
231  */
232 static int
233 usf_enc_ie(struct usfmt *usf, struct ie_generic *ie)
234 {
235         int                     i, rc;
236         u_char                  c;
237         u_char                  *lp0, *lp1;
238
239         union {
240                 short   s;
241                 u_char  sb[sizeof(short)];
242         } su;
243
244         ATM_DEBUG2("usf_enc_ie: usf=%p, ie=%p\n",
245                         usf, ie);
246
247         /*
248          * Encode the IE identifier
249          */
250         rc = usf_byte(usf, &ie->ie_ident);
251         if (rc)
252                 return(rc);
253
254         /*
255          * Encode the extended type
256          */
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);
265
266         /*
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.
270          */
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);
278
279         /*
280          * Look up the information element in the table
281          */
282         for (i=0; (ie->ie_ident != ie_table[i].ident) &&
283                         (ie_table[i].encode != NULL); i++) {
284         }
285         if (ie_table[i].encode == NULL) {
286                 /*
287                  * Unrecognized IE
288                  */
289                 return(EINVAL);
290         }
291
292         /*
293          * Process the IE by calling the function indicated
294          * in the IE table
295          */
296         rc = ie_table[i].encode(usf, ie);
297         if (rc)
298                 return(rc);
299
300         /*
301          * Set the length in the output stream
302          */
303         su.s = htons((u_short)ie->ie_length);
304         *lp0 = su.sb[sizeof(short)-2];
305         *lp1 = su.sb[sizeof(short)-1];
306
307         return(0);
308 }
309
310
311 /*
312  * Encode an AAL parameters information element
313  *
314  * Arguments:
315  *      usf     pointer to a unisig formatting structure
316  *      ie      pointer to an AAL parms IE structure
317  *
318  * Returns:
319  *      0       success
320  *      errno   error encountered
321  *
322  */
323 static int
324 usf_enc_ie_aalp(struct usfmt *usf, struct ie_generic *ie)
325 {
326         int             i, rc = 0;
327
328         ATM_DEBUG2("usf_enc_ie_aalp: usf=%p, ie=%p\n",
329                         usf, ie);
330
331         ie->ie_length = 0;
332
333         /*
334          * Encode the AAL type
335          */
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);
341
342         /*
343          * Process based on AAL type
344          */
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:
362                         /*
363                          * Encode the user data
364                          */
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++;
372                         }
373                         break;
374                 default:
375                         return(EINVAL);
376         }
377
378         ie->ie_length++;
379         return(rc);
380 }
381
382
383 /*
384  * Encode a user cell rate information element
385  *
386  * This routine just encodes the parameters required for best
387  * effort service.
388  *
389  * Arguments:
390  *      usf     pointer to a unisig formatting structure
391  *      ie      pointer to a cell rate IE structure
392  *
393  * Returns:
394  *      0       success
395  *      errno   error encountered
396  *
397  */
398 static int
399 usf_enc_ie_clrt(struct usfmt *usf, struct ie_generic *ie)
400 {
401         int     rc;
402
403         ATM_DEBUG2("usf_enc_ie_clrt: usf=%p, ie=%p\n",
404                         usf, ie);
405
406 #ifdef NOTDEF
407         /*
408          * Encode Peak Cell Rate Forward CLP = 0 + 1
409          */
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);
417
418         /*
419          * Encode Peak Cell Rate Backward CLP = 0 + 1
420          */
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);
428
429         /*
430          * Encode Best Effort Flag
431          */
432         c = UNI_IE_CLRT_BEST_EFFORT_ID;
433         rc = usf_byte(usf, &c);
434         if (rc)
435                 return(rc);
436
437         /*
438          * Set IE length
439          */
440         ie->ie_length = 9;
441 #endif
442
443         /*
444          * Encode the user cell rate IE using the table
445          */
446         ie->ie_length = 0;
447         rc = usf_enc_ie_ident(usf, ie, ie_clrt_tbl);
448
449         return(rc);
450 }
451
452
453 /*
454  * Encode a broadband bearer capability information element
455  *
456  * Arguments:
457  *      usf     pointer to a unisig formatting structure
458  *      ie      pointer to a cell rate IE structure
459  *
460  * Returns:
461  *      0       success
462  *      errno   error encountered
463  *
464  */
465 static int
466 usf_enc_ie_bbcp(struct usfmt *usf, struct ie_generic *ie)
467 {
468         int     rc;
469         u_char  c;
470
471         ATM_DEBUG2("usf_enc_ie_bbcp: usf=%p, ie=%p\n",
472                         usf, ie);
473
474         ie->ie_length = 0;
475
476         /*
477          * Encode the broadband bearer class
478          */
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++;
488
489         /*
490          * If the broadband bearer class was X, the next
491          * byte has the traffic type and timing requirements
492          */
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++;
503         }
504
505         /*
506          * Encode the clipping and user plane connection configuration
507          */
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++;
517
518         return(0);
519 }
520
521
522 /*
523  * Encode a broadband high layer information element
524  *
525  * Arguments:
526  *      usf     pointer to a unisig formatting structure
527  *      ie      pointer to a cell rate IE structure
528  *
529  * Returns:
530  *      0       success
531  *      errno   error encountered
532  *
533  */
534 static int
535 usf_enc_ie_bhli(struct usfmt *usf, struct ie_generic *ie)
536 {
537         int     i, rc;
538         u_int   type;
539
540         ATM_DEBUG2("usf_enc_ie_bhli: usf=%p, ie=%p\n",
541                         usf, ie);
542
543         ie->ie_length = 0;
544
545         /*
546          * Encode the high layer information type
547          */
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++;
555
556         /*
557          * What comes next depends on the type
558          */
559         switch (ie->ie_bhli_type) {
560         case UNI_IE_BHLI_TYPE_ISO:
561         case UNI_IE_BHLI_TYPE_USER:
562                 /*
563                  * ISO or user-specified parameters -- take the
564                  * length of information from the IE length
565                  */
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++;
571                 }
572                 break;
573         case UNI_IE_BHLI_TYPE_HLP:
574                 /*
575                  * Make sure the IE is long enough for the high
576                  * layer profile information, then get it
577                  */
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++;
585                 }
586                 break;
587         case UNI_IE_BHLI_TYPE_VSA:
588                 /*
589                  * Make sure the IE is long enough for the vendor-
590                  * specific application information, then get it
591                  */
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++;
597                 }
598                 break;
599         default:
600                 return(EINVAL);
601         }
602
603         return(0);
604 }
605
606
607 /*
608  * Encode a broadband low layer information element
609  *
610  * Arguments:
611  *      usf     pointer to a unisig formatting structure
612  *      ie      pointer to a cell rate IE structure
613  *
614  * Returns:
615  *      0       success
616  *      errno   error encountered
617  *
618  */
619 static int
620 usf_enc_ie_blli(struct usfmt *usf, struct ie_generic *ie)
621 {
622         u_char          c;
623         int             rc;
624         u_int           ipi;
625
626         ATM_DEBUG2("usf_enc_ie_blli: usf=%p, ie=%p\n",
627                         usf, ie);
628
629         ie->ie_length = 0;
630
631         /*
632          * Encode paramteters for whichever protocol layers the
633          * user specified
634          */
635
636         /*
637          * Layer 1 information
638          */
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++;
648         }
649
650         /*
651          * Layer 2 information
652          */
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);
657
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:
666                         /*
667                          * Write the Layer 2 type
668                          */
669                         rc = usf_byte(usf, &c);
670                         if (rc)
671                                 return(rc);
672                         ie->ie_length++;
673
674                         /*
675                          * Encode the Layer 2 mode
676                          */
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;
683
684                                 rc = usf_byte(usf, &c);
685                                 if (rc)
686                                         return(rc);
687                                 ie->ie_length++;
688                         }
689
690                         /*
691                          * Encode the Layer 2 window size
692                          */
693                         if (ie->ie_blli_l2_window) {
694                                 c = (ie->ie_blli_l2_window &
695                                                 UNI_IE_EXT_MASK) +
696                                                 UNI_IE_EXT_BIT;
697
698                                 rc = usf_byte(usf, &c);
699                                 if (rc)
700                                         return(rc);
701                                 ie->ie_length++;
702                         }
703                         break;
704                 case UNI_IE_BLLI_L2P_USER:
705                         /*
706                          * Write the Layer 2 type
707                          */
708                         rc = usf_byte(usf, &c);
709                         if (rc)
710                                 return(rc);
711                         ie->ie_length++;
712
713                         /*
714                          * Encode the user-specified layer 2 info
715                          */
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:
725                         /*
726                          * Write the Layer 2 type
727                          */
728                         c |= UNI_IE_EXT_BIT;
729                         rc = usf_byte(usf, &c);
730                         if (rc)
731                                 return(rc);
732                         ie->ie_length++;
733                         break;
734                 }
735         }
736
737         /*
738          * Layer 3 information
739          */
740         if (ie->ie_blli_l3_id && ie->ie_blli_l3_id != T_ATM_ABSENT) {
741                 /*
742                  * Encode the layer 3 protocol ID
743                  */
744                 c = (UNI_IE_BLLI_L3_ID << UNI_IE_BLLI_LID_SHIFT) +
745                                 (ie->ie_blli_l3_id &
746                                 UNI_IE_BLLI_LP_MASK);
747
748                 /*
749                  * Process other fields based on protocol ID
750                  */
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:
755                         /*
756                          * Write the protocol ID
757                          */
758                         rc = usf_byte(usf, &c);
759                         if (rc)
760                                 return(rc);
761                         ie->ie_length++;
762
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;
772
773                                 rc = usf_byte(usf, &c);
774                                 if (rc)
775                                         return(rc);
776                                 ie->ie_length++;
777                         }
778
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;
785
786                                 rc = usf_byte(usf, &c);
787                                 if (rc)
788                                         return(rc);
789                                 ie->ie_length++;
790                         }
791
792                         if (ie->ie_blli_l3_window) {
793                                 c = (ie->ie_blli_l3_window &
794                                                 UNI_IE_EXT_MASK) +
795                                                 UNI_IE_EXT_BIT;
796
797                                 rc = usf_byte(usf, &c);
798                                 if (rc)
799                                         return(rc);
800                                 ie->ie_length++;
801                         }
802                         break;
803                 case UNI_IE_BLLI_L3P_USER:
804                         /*
805                          * Write the protocol ID
806                          */
807                         rc = usf_byte(usf, &c);
808                         if (rc)
809                                 return(rc);
810                         ie->ie_length++;
811
812                         /*
813                          * Encode the user-specified protocol info
814                          */
815                         c = (ie->ie_blli_l3_user_proto &
816                                                 UNI_IE_EXT_MASK) +
817                                                 UNI_IE_EXT_BIT;
818
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:
825                         /*
826                          * Write the protocol ID
827                          */
828                         rc = usf_byte(usf, &c);
829                         if (rc)
830                                 return(rc);
831                         ie->ie_length++;
832
833                         /*
834                          * Encode the IPI
835                          */
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;
842
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);
849
850                                 rc = usf_byte(usf,
851                                                 &ie->ie_blli_l3_oui[0]);
852                                 if (rc)
853                                         return(rc);
854
855                                 rc = usf_byte(usf,
856                                                 &ie->ie_blli_l3_oui[1]);
857                                 if (rc)
858                                         return(rc);
859
860                                 rc = usf_byte(usf,
861                                                 &ie->ie_blli_l3_oui[2]);
862                                 if (rc)
863                                         return(rc);
864
865                                 rc = usf_byte(usf,
866                                                 &ie->ie_blli_l3_pid[0]);
867                                 if (rc)
868                                         return(rc);
869
870                                 rc = usf_byte(usf,
871                                                 &ie->ie_blli_l3_pid[1]);
872                                 if (rc)
873                                         return(rc);
874
875                                 ie->ie_length += 6;
876                         }
877                         break;
878                 default:
879                         /*
880                          * Write the layer 3 protocol ID
881                          */
882                         c |= UNI_IE_EXT_BIT;
883                         rc = usf_byte(usf, &c);
884                         if (rc)
885                                 return(rc);
886                         ie->ie_length++;
887                         break;
888                 }
889         }
890
891         return(0);
892 }
893
894
895 /*
896  * Encode a call state information element
897  *
898  * Arguments:
899  *      usf     pointer to a unisig formatting structure
900  *      ie      pointer to a cell rate IE structure
901  *
902  * Returns:
903  *      0       success
904  *      errno   error encountered
905  *
906  */
907 static int
908 usf_enc_ie_clst(struct usfmt *usf, struct ie_generic *ie)
909 {
910         int     rc;
911         u_char  c;
912
913         ATM_DEBUG2("usf_enc_ie_clst: usf=%p, ie=%p\n",
914                         usf, ie);
915
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;
921
922         return(0);
923 }
924
925
926 /*
927  * Encode a called party number information element
928  *
929  * Arguments:
930  *      usf     pointer to a unisig formatting structure
931  *      ie      pointer to a cell rate IE structure
932  *
933  * Returns:
934  *      0       success
935  *      errno   error encountered
936  *
937  */
938 static int
939 usf_enc_ie_cdad(struct usfmt *usf, struct ie_generic *ie)
940 {
941         u_char  c;
942         int     rc;
943
944         ATM_DEBUG2("usf_enc_ie_cdad: usf=%p, ie=%p\n",
945                         usf, ie);
946
947         /*
948          * Encode the numbering plan
949          */
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);
965         }
966         c |= UNI_IE_EXT_BIT;
967         rc = usf_byte(usf, &c);
968         if (rc)
969                 return(rc);
970
971         /*
972          * Encode the ATM address
973          */
974         rc = usf_enc_atm_addr(usf, &ie->ie_cdad_addr);
975
976         return(rc);
977 }
978
979
980 /*
981  * Encode a called party subaddress information element
982  *
983  * Arguments:
984  *      usf     pointer to a unisig formatting structure
985  *      ie      pointer to a cell rate IE structure
986  *
987  * Returns:
988  *      0       success
989  *      errno   error encountered
990  *
991  */
992 static int
993 usf_enc_ie_cdsa(struct usfmt *usf, struct ie_generic *ie)
994 {
995         u_char  c;
996         int     rc;
997
998         /*
999          * Encode the subaddress type
1000          */
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);
1008         }
1009         c |= UNI_IE_EXT_BIT;
1010         rc = usf_byte(usf, &c);
1011         if (rc)
1012                 return(rc);
1013
1014         /*
1015          * Encode the ATM address
1016          */
1017         rc = usf_enc_atm_addr(usf, &ie->ie_cdsa_addr);
1018
1019         return(rc);
1020 }
1021
1022
1023 /*
1024  * Encode a calling party number information element
1025  *
1026  * Arguments:
1027  *      usf     pointer to a unisig formatting structure
1028  *      ie      pointer to a cell rate IE structure
1029  *
1030  * Returns:
1031  *      0       success
1032  *      errno   error encountered
1033  *
1034  */
1035 static int
1036 usf_enc_ie_cgad(struct usfmt *usf, struct ie_generic *ie)
1037 {
1038         u_char  c;
1039         int     rc;
1040
1041         ATM_DEBUG2("usf_enc_ie_cgad: usf=%p, ie=%p\n",
1042                         usf, ie);
1043
1044         /*
1045          * Encode the numbering plan
1046          */
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);
1064         }
1065         rc = usf_byte(usf, &c);
1066         if (rc)
1067                 return(rc);
1068
1069         /*
1070          * Encode the presentation and screening indicators
1071          */
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
1082         
1083
1084         /*
1085          * Encode the ATM address
1086          */
1087         rc = usf_enc_atm_addr(usf, &ie->ie_cgad_addr);
1088
1089         return(rc);
1090 }
1091
1092
1093 /*
1094  * Encode a calling party subaddress information element
1095  *
1096  * Arguments:
1097  *      usf     pointer to a unisig formatting structure
1098  *      ie      pointer to a cell rate IE structure
1099  *
1100  * Returns:
1101  *      0       success
1102  *      errno   error encountered
1103  *
1104  */
1105 static int
1106 usf_enc_ie_cgsa(struct usfmt *usf, struct ie_generic *ie)
1107 {
1108         u_char  c;
1109         int     rc;
1110
1111         /*
1112          * Encode the subaddress type
1113          */
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);
1121         }
1122         c |= UNI_IE_EXT_BIT;
1123         rc = usf_byte(usf, &c);
1124         if (rc)
1125                 return(rc);
1126
1127         /*
1128          * Encode the ATM address
1129          */
1130         rc = usf_enc_atm_addr(usf, &ie->ie_cgsa_addr);
1131
1132         return(rc);
1133 }
1134
1135
1136 /*
1137  * Encode a cause information element
1138  *
1139  * Arguments:
1140  *      usf     pointer to a unisig formatting structure
1141  *      ie      pointer to a cell rate IE structure
1142  *
1143  * Returns:
1144  *      0       success
1145  *      errno   error encountered
1146  *
1147  */
1148 static int
1149 usf_enc_ie_caus(struct usfmt *usf, struct ie_generic *ie)
1150 {
1151         int                     i, rc;
1152         u_char                  c;
1153
1154         ATM_DEBUG2("usf_enc_ie_caus: usf=%p, ie=%p\n",
1155                         usf, ie);
1156
1157         ie->ie_length = 0;
1158
1159         /*
1160          * Encode the cause location
1161          */
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++;
1167
1168         /*
1169          * Encode the cause value
1170          */
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++;
1176
1177         /*
1178          * Encode any included diagnostics
1179          */
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++;
1187         }
1188
1189         return(0);
1190 }
1191
1192
1193 /*
1194  * Encode a conection identifier information element
1195  *
1196  * Arguments:
1197  *      usf     pointer to a unisig formatting structure
1198  *      ie      pointer to a cell rate IE structure
1199  *
1200  * Returns:
1201  *      0       success
1202  *      errno   error encountered
1203  *
1204  */
1205 static int
1206 usf_enc_ie_cnid(struct usfmt *usf, struct ie_generic *ie)
1207 {
1208         int     rc;
1209         u_char  c;
1210
1211         ATM_DEBUG2("usf_enc_ie_cnid: usf=%p, ie=%p\n",
1212                         usf, ie);
1213
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);
1221
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);
1228
1229         ie->ie_length = 5;
1230         return(0);
1231 }
1232
1233
1234 /*
1235  * Encode a quality of service parameters information element
1236  *
1237  * Arguments:
1238  *      usf     pointer to a unisig formatting structure
1239  *      ie      pointer to a cell rate IE structure
1240  *
1241  * Returns:
1242  *      0       success
1243  *      errno   error encountered
1244  *
1245  */
1246 static int
1247 usf_enc_ie_qosp(struct usfmt *usf, struct ie_generic *ie)
1248 {
1249         int             rc;
1250
1251         ATM_DEBUG2("usf_enc_ie_qosp: usf=%p, ie=%p\n",
1252                         usf, ie);
1253
1254         /*
1255          * Encode forward QoS class
1256          */
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);
1263
1264         /*
1265          * Encode backward QoS class
1266          */
1267         rc = usf_byte(usf, &ie->ie_qosp_bkwd_class);
1268
1269         ie->ie_length = 2;
1270         return(rc);
1271 }
1272
1273
1274 /*
1275  * Encode a broadband repeat indicator information element
1276  *
1277  * Arguments:
1278  *      usf     pointer to a unisig formatting structure
1279  *      ie      pointer to a cell rate IE structure
1280  *
1281  * Returns:
1282  *      0       success
1283  *      errno   error encountered
1284  *
1285  */
1286 static int
1287 usf_enc_ie_brpi(struct usfmt *usf, struct ie_generic *ie)
1288 {
1289         int     rc;
1290         u_char  c;
1291
1292         ATM_DEBUG2("usf_enc_ie_brpi: usf=%p, ie=%p\n",
1293                         usf, ie);
1294
1295         /*
1296          * Encode the repeat indicator
1297          */
1298         c = ie->ie_brpi_ind + UNI_IE_EXT_BIT;
1299         rc = usf_byte(usf, &c);
1300
1301         return(rc);
1302 }
1303
1304
1305 /*
1306  * Encode a restart indicator information element
1307  *
1308  * Arguments:
1309  *      usf     pointer to a unisig formatting structure
1310  *      ie      pointer to a cell rate IE structure
1311  *
1312  * Returns:
1313  *      0       success
1314  *      errno   error encountered
1315  *
1316  */
1317 static int
1318 usf_enc_ie_rsti(struct usfmt *usf, struct ie_generic *ie)
1319 {
1320         int     rc;
1321         u_char  c;
1322
1323         ATM_DEBUG2("usf_enc_ie_rsti: usf=%p, ie=%p\n",
1324                         usf, ie);
1325
1326         /*
1327          * Encode the restart class
1328          */
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;
1333
1334         return(rc);
1335 }
1336
1337
1338 /*
1339  * Encode a broadband sending complete information element
1340  *
1341  * Arguments:
1342  *      usf     pointer to a unisig formatting structure
1343  *      ie      pointer to a broadband sending complete IE structure
1344  *
1345  * Returns:
1346  *      0       success
1347  *      errno   error encountered
1348  *
1349  */
1350 static int
1351 usf_enc_ie_bsdc(struct usfmt *usf, struct ie_generic *ie)
1352 {
1353         int     rc;
1354         u_char  c;
1355
1356         ATM_DEBUG2("usf_enc_ie_bsdc: usf=%p, ie=%p\n",
1357                         usf, ie);
1358
1359         /*
1360          * Encode the sending complete indicator
1361          */
1362         c = UNI_IE_BSDC_IND | UNI_IE_EXT_BIT;
1363         rc = usf_byte(usf, &c);
1364         ie->ie_length = 1;
1365
1366         return(rc);
1367 }
1368
1369
1370 /*
1371  * Encode a transit network selection information element
1372  *
1373  * Arguments:
1374  *      usf     pointer to a unisig formatting structure
1375  *      ie      pointer to a transit network selection rate IE structure
1376  *
1377  * Returns:
1378  *      0       success
1379  *      errno   error encountered
1380  *
1381  */
1382 static int
1383 usf_enc_ie_trnt(struct usfmt *usf, struct ie_generic *ie)
1384 {
1385         int     i, rc;
1386         u_char  c;
1387
1388         ATM_DEBUG2("usf_enc_ie_trnt: usf=%p, ie=%p\n",
1389                         usf, ie);
1390
1391         /*
1392          * Encode the sending complete indicator
1393          */
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;
1402
1403         /*
1404          * Encode the network identification
1405          */
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++;
1411         }
1412
1413         return(rc);
1414 }
1415
1416
1417 /*
1418  * Encode an unsupported IE type
1419  *
1420  * Arguments:
1421  *      usf     pointer to a unisig formatting structure
1422  *      ie      pointer to an IE structure
1423  *
1424  * Returns:
1425  *      0       success
1426  *
1427  */
1428 static int
1429 usf_enc_ie_uimp(struct usfmt *usf, struct ie_generic *ie)
1430 {
1431         return(0);
1432 }
1433
1434
1435 /*
1436  * Encode an information element using field identifiers
1437  *
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.
1442  *
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
1447  *
1448  * Returns:
1449  *      0       success
1450  *      errno   error encountered
1451  *
1452  */
1453 static int
1454 usf_enc_ie_ident(struct usfmt *usf, struct ie_generic *ie,
1455                  struct ie_decode_tbl *tbl)
1456 {
1457         int     i, len, rc;
1458         char    *cp;
1459         u_int8_t        cv;
1460         u_int16_t       sv;
1461         u_int32_t       iv;
1462
1463         ATM_DEBUG3("usf_enc_ie_ident: usf=%p, ie=%p, tbl=%p\n",
1464                         usf, ie, tbl);
1465
1466         /*
1467          * Scan through the IE table
1468          */
1469         len = 0;
1470         for (i=0; tbl[i].ident; i++) {
1471                 /*
1472                  * Check whether to send the field
1473                  */
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);
1499                         }
1500                 }
1501
1502                 /*
1503                  * Encode the field identifier
1504                  */
1505                 rc = usf_byte(usf, &tbl[i].ident);
1506                 if (rc)
1507                         return(rc);
1508                 len++;
1509
1510                 /*
1511                  * Encode the field value
1512                  */
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;
1529                                 }
1530                                 rc = usf_byte(usf, &cv);
1531                                 break;
1532
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;
1543                                 }
1544                                 rc = usf_short(usf, &sv);
1545                                 break;
1546
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;
1554                                 }
1555                                 rc = usf_int3(usf, &iv);
1556                                 break;
1557
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;
1565                                 }
1566                                 rc = usf_int(usf, &iv);
1567                                 break;
1568
1569                         default:
1570                                 goto badtbl;
1571                 }
1572
1573                 len += tbl[i].len;
1574
1575                 if (rc)
1576                         return(rc);
1577         }
1578
1579         ie->ie_length = len;
1580         return(0);
1581 }
1582
1583
1584 /*
1585  * Encode an ATM address
1586  *
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.
1591  *
1592  * Returns:
1593  *      0       success
1594  *      errno   error encountered
1595  *
1596  */
1597 static int
1598 usf_enc_atm_addr(struct usfmt *usf, Atm_addr *addr)
1599 {
1600         int     len, rc;
1601         u_char  *cp;
1602
1603         /*
1604          * Check the address type
1605          */
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);
1617         }
1618
1619         /*
1620          * Get the address bytes
1621          */
1622         while (len) {
1623                 rc = usf_byte(usf, cp);
1624                 if (rc)
1625                         return(rc);
1626                 len--;
1627                 cp++;
1628         }
1629
1630         return(0);
1631 }