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