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