kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / unisig_subr.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_subr.c,v 1.7 2000/01/17 20:49:58 mks Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_subr.c,v 1.3 2003/08/07 21:17:36 dillon Exp $
28  */
29
30 /*
31  * ATM Forum UNI 3.0/3.1 Signalling Manager
32  * ----------------------------------------
33  *
34  * Subroutines
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include "unisig_var.h"
41 #include "unisig_msg.h"
42
43 /*
44  * External variables
45  */
46 extern struct ie_aalp  ie_aalp_absent;
47 extern struct ie_clrt  ie_clrt_absent;
48 extern struct ie_bbcp  ie_bbcp_absent;
49 extern struct ie_bhli  ie_bhli_absent;
50 extern struct ie_blli  ie_blli_absent;
51 extern struct ie_clst  ie_clst_absent;
52 extern struct ie_cdad  ie_cdad_absent;
53 extern struct ie_cdsa  ie_cdsa_absent;
54 extern struct ie_cgad  ie_cgad_absent;
55 extern struct ie_cgsa  ie_cgsa_absent;
56 extern struct ie_caus  ie_caus_absent;
57 extern struct ie_cnid  ie_cnid_absent;
58 extern struct ie_qosp  ie_qosp_absent;
59 extern struct ie_brpi  ie_brpi_absent;
60 extern struct ie_rsti  ie_rsti_absent;
61 extern struct ie_blsh  ie_blsh_absent;
62 extern struct ie_bnsh  ie_bnsh_absent;
63 extern struct ie_bsdc  ie_bsdc_absent;
64 extern struct ie_trnt  ie_trnt_absent;
65 extern struct ie_eprf  ie_eprf_absent;
66 extern struct ie_epst  ie_epst_absent;
67
68
69 /*
70  * Set a User Location cause code in an ATM attribute block
71  *
72  * Arguments:
73  *      aap     pointer to attribute block
74  *      cause   cause code
75  *
76  * Returns:
77  *      none
78  *
79  */
80 void
81 unisig_cause_attr_from_user(aap, cause)
82         Atm_attributes  *aap;
83         int             cause;
84 {
85         if (cause == T_ATM_ABSENT)
86                 return;
87
88         /*
89          * Set the fields in the attribute block
90          */
91         aap->cause.tag = T_ATM_PRESENT;
92         aap->cause.v.coding_standard = T_ATM_ITU_CODING;
93         aap->cause.v.location = T_ATM_LOC_USER;
94         aap->cause.v.cause_value = cause;
95         KM_ZERO(aap->cause.v.diagnostics,
96                         sizeof(aap->cause.v.diagnostics));
97 }
98
99
100 /*
101  * Set a cause code in an ATM attribute block from a Cause IE
102  *
103  * Arguments:
104  *      aap     pointer to attribute block
105  *      iep     pointer to Cause IE
106  *
107  * Returns:
108  *      none
109  *
110  */
111 void
112 unisig_cause_attr_from_ie(aap, iep)
113         Atm_attributes          *aap;
114         struct ie_generic       *iep;
115 {
116         /*
117          * Set the fields in the attribute block
118          */
119         aap->cause.tag = T_ATM_PRESENT;
120         aap->cause.v.coding_standard = iep->ie_coding;
121         aap->cause.v.location = iep->ie_caus_loc;
122         aap->cause.v.cause_value = iep->ie_caus_cause;
123         KM_ZERO(aap->cause.v.diagnostics, sizeof(aap->cause.v.diagnostics));
124         KM_COPY(iep->ie_caus_diagnostic, aap->cause.v.diagnostics,
125                 MIN(sizeof(aap->cause.v.diagnostics), iep->ie_caus_diag_len));
126 }
127
128
129 /*
130  * Open a UNI VCC
131  *
132  * Called when a user wants to open a VC.  This function will construct
133  * a VCCB and, if we are opening an SVC, call the Q.2931 VC state
134  * machine.  The user will have to wait for a notify event to be sure
135  * the SVC is fully open.
136  *
137  * Must be called at splnet.
138  *
139  * Arguments:
140  *      usp     pointer to UNISIG protocol instance
141  *      cvp     pointer to connection parameters for the VCC
142  *
143  * Returns:
144  *      0       VCC creation successful
145  *      errno   VCC setup failed - reason indicated
146  *
147  */
148 int
149 unisig_open_vcc(usp, cvp)
150         struct unisig   *usp;
151         Atm_connvc      *cvp;
152 {
153         struct atm_pif          *pip = usp->us_pif;
154         struct unisig_vccb      *uvp;
155         Atm_addr_pvc            *pvp;
156         int                     err, pvc;
157
158         ATM_DEBUG2("unisig_open_vcc: usp=%p, cvp=%p\n", usp, cvp);
159
160         /*
161          * Validate user parameters.  AAL and encapsulation are
162          * checked by the connection manager
163          */
164
165         /*
166          * Check called party address(es)
167          */
168         if(cvp->cvc_attr.called.tag != T_ATM_PRESENT ||
169                         cvp->cvc_attr.called.addr.address_format ==
170                                 T_ATM_ABSENT) {
171                 return(EINVAL);
172         }
173         switch (cvp->cvc_attr.called.addr.address_format) {
174         case T_ATM_PVC_ADDR:
175                 /*
176                  * Make sure VPI/VCI is valid
177                  */
178                 pvc = 1;
179                 pvp = (Atm_addr_pvc *)cvp->cvc_attr.called.addr.address;
180                 if ((ATM_PVC_GET_VPI(pvp) > pip->pif_maxvpi) ||
181                                 (ATM_PVC_GET_VCI(pvp) == 0) ||
182                                 (ATM_PVC_GET_VCI(pvp) > pip->pif_maxvci)) {
183                         return(ERANGE);
184                 }
185
186                 /*
187                  * Make sure VPI/VCI is not already in use
188                  */
189                 if (unisig_find_vpvc(usp,
190                                 ATM_PVC_GET_VPI(pvp),
191                                 ATM_PVC_GET_VCI(pvp), 0)) {
192                         return(EEXIST);
193                 }
194                 ATM_DEBUG2("unisig_open_vcc: VPI.VCI=%d.%d\n",
195                                 ATM_PVC_GET_VPI(pvp),
196                                 ATM_PVC_GET_VCI(pvp));
197                 break;
198
199         case T_ATM_ENDSYS_ADDR:
200                 /*
201                  * Check signalling state
202                  */
203                 pvc = 0;
204                 pvp = NULL;
205                 if (usp->us_state != UNISIG_ACTIVE) {
206                         return(ENETDOWN);
207                 }
208
209                 /*
210                  * Make sure there's no subaddress
211                  */
212                 if (cvp->cvc_attr.called.subaddr.address_format !=
213                                 T_ATM_ABSENT) {
214                         return(EINVAL);
215                 }
216                 break;
217
218         case T_ATM_E164_ADDR:
219                 /*
220                  * Check signalling state
221                  */
222                 pvc = 0;
223                 pvp = NULL;
224                 if (usp->us_state != UNISIG_ACTIVE) {
225                         return(ENETDOWN);
226                 }
227
228                 /*
229                  * Check destination address format
230                  */
231                 if (cvp->cvc_attr.called.subaddr.address_format !=
232                                         T_ATM_ENDSYS_ADDR &&
233                                 cvp->cvc_attr.called.subaddr.address_format !=
234                                         T_ATM_ABSENT) {
235                         return(EINVAL);
236                 }
237                 break;
238
239         default:
240                 return(EPROTONOSUPPORT);
241         }
242
243         /*
244          * Check that this is for the same interface UNISIG uses
245          */
246         if (!cvp->cvc_attr.nif ||
247                         cvp->cvc_attr.nif->nif_pif != usp->us_pif) {
248                 return(EINVAL);
249         }
250
251         /*
252          * Allocate control block for VCC
253          */
254         uvp = (struct unisig_vccb *)atm_allocate(&unisig_vcpool);
255         if (uvp == NULL) {
256                 return(ENOMEM);
257         }
258
259         /*
260          * Fill in VCCB
261          */
262         if (pvc) {
263                 uvp->uv_type = VCC_PVC | VCC_IN | VCC_OUT;
264                 uvp->uv_vpi = ATM_PVC_GET_VPI(pvp);
265                 uvp->uv_vci = ATM_PVC_GET_VCI(pvp);
266                 uvp->uv_sstate = (usp->us_state == UNISIG_ACTIVE ?
267                                 UNI_PVC_ACTIVE : UNI_PVC_ACT_DOWN);
268                 uvp->uv_ustate = VCCU_OPEN;
269         } else {
270                 uvp->uv_type = VCC_SVC | VCC_IN | VCC_OUT;
271                 uvp->uv_sstate = UNI_NULL;
272                 uvp->uv_ustate = VCCU_POPEN;
273         }
274         uvp->uv_proto = usp->us_pif->pif_sigmgr->sm_proto;
275         uvp->uv_pif = usp->us_pif;
276         uvp->uv_nif = cvp->cvc_attr.nif;
277         uvp->uv_connvc = cvp;
278         uvp->uv_tstamp = time_second;
279
280         /*
281          * Put VCCB on UNISIG queue
282          */
283         ENQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
284
285         /*
286          * Call the VC state machine if this is an SVC
287          */
288         if (!pvc) {
289                 err = unisig_vc_state(usp, uvp, UNI_VC_SETUP_CALL,
290                                 (struct unisig_msg *) 0);
291                 if (err) {
292                         /*
293                          * On error, delete the VCCB
294                          */
295                         DEQUEUE(uvp, struct unisig_vccb, uv_sigelem,
296                                         usp->us_vccq);
297                         atm_free((caddr_t)uvp);
298                         return(err);
299                 }
300         }
301
302         /*
303          * Link VCCB to VCC connection block
304          */
305         cvp->cvc_vcc = (struct vccb *) uvp;
306
307         return(0);
308 }
309
310
311 /*
312  * Close a UNISIG VCC
313  *
314  * Called when a user wants to close a VCC.  This function will clean
315  * up the VCCB and, for an SVC, send a close request.
316  *
317  * Must be called at splnet.
318  *
319  * Arguments:
320  *      usp     pointer to UNISIG protocol instance
321  *      uvp     pointer to VCCB for the VCC to be closed
322  *
323  * Returns:
324  *      0       VCC is now closed
325  *      errno   error encountered
326  */
327 int
328 unisig_close_vcc(usp, uvp)
329         struct unisig           *usp;
330         struct unisig_vccb      *uvp;
331 {
332         int             err = 0;
333
334         ATM_DEBUG2("unisig_close_vcc: uvp=%p, state=%d\n", uvp,
335                         uvp->uv_sstate);
336
337         /*
338          * Check that this is for the same interface UNISIG uses
339          */
340         if (uvp->uv_pif != usp->us_pif) {
341                 return (EINVAL);
342         }
343
344         /*
345          * Mark the close time.
346          */
347         uvp->uv_tstamp = time_second;
348
349         /*
350          * Process based on the connection type
351          */
352         if (uvp->uv_type & VCC_PVC) {
353                 uvp->uv_sstate = UNI_FREE;
354                 uvp->uv_ustate = VCCU_CLOSED;
355         } else if (uvp->uv_type & VCC_SVC) {
356                 /*
357                  * Call the VC state machine
358                  */
359                 uvp->uv_ustate = VCCU_CLOSED;
360                 err = unisig_vc_state(usp, uvp, UNI_VC_RELEASE_CALL,
361                                 (struct unisig_msg *) 0);
362         }
363
364         /*
365          * Wait for user to free resources
366          */
367         return(err);
368 }
369
370
371 /*
372  * Clear a UNISIG VCC
373  *
374  * Called to internally clear a VCC.  No external protocol is
375  * initiated, the VCC is just closed and the owner is notified.
376  *
377  * Must be called at splnet.
378  *
379  * Arguments:
380  *      usp     pointer to UNISIG protocol instance
381  *      uvp     pointer to VCCB for the VCC to be closed
382  *      cause   cause code giving the reason for the close
383  *
384  * Returns:
385  *      0       VCC is closed
386  *      errno   error encountered
387  */
388 int
389 unisig_clear_vcc(usp, uvp, cause)
390         struct unisig           *usp;
391         struct unisig_vccb      *uvp;
392         int                     cause;
393 {
394         u_char  outstate;
395
396         ATM_DEBUG3("unisig_clear_vcc: uvp=%p, state=%d, cause=%d\n",
397                         uvp, uvp->uv_sstate, cause);
398
399         /*
400          * Check that this is for the same interface UNISIG uses
401          */
402         if (uvp->uv_pif != usp->us_pif) {
403                 return (EINVAL);
404         }
405
406         /*
407          * Kill any possible timer
408          */
409         UNISIG_VC_CANCEL((struct vccb *) uvp);
410
411         /*
412          * Mark the close time.
413          */
414         uvp->uv_tstamp = time_second;
415
416         /*
417          * Close the VCC and notify the user
418          */
419         outstate = uvp->uv_sstate;
420         uvp->uv_sstate = UNI_FREE;
421         uvp->uv_ustate = VCCU_CLOSED;
422         if (outstate == UNI_ACTIVE ||
423                         outstate == UNI_CALL_INITIATED ||
424                         outstate == UNI_CALL_OUT_PROC ||
425                         outstate == UNI_CONNECT_REQUEST ||
426                         outstate == UNI_RELEASE_REQUEST ||
427                         outstate == UNI_RELEASE_IND ||
428                         outstate == UNI_SSCF_RECOV ||
429                         outstate == UNI_PVC_ACT_DOWN ||
430                         outstate == UNI_PVC_ACTIVE) {
431                 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr, cause);
432                 atm_cm_cleared(uvp->uv_connvc);
433         }
434
435         /*
436          * Wait for user to free resources
437          */
438         return(0);
439 }
440
441
442 #ifdef NOTDEF
443 /*
444  * Reset the switch state
445  *
446  * Arguments:
447  *      usp     pointer to UNISIG protocol instance
448  *
449  * Returns:
450  *      none
451  *
452  */
453 void
454 unisig_switch_reset(usp, cause)
455         struct unisig   *usp;
456         int             cause;
457 {
458         int                     s;
459         struct unisig_vccb      *uvp, *vnext;
460
461         ATM_DEBUG2("unisig_switch_reset: usp=%p, cause=%d\n",
462                         usp, cause);
463
464         /*
465          * Terminate all of our VCCs
466          */
467         s = splnet();
468         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
469                         uvp = vnext) {
470                 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
471
472                 if (uvp->uv_type & VCC_SVC) {
473                         /*
474                          * Close the SVC and notify the owner
475                          */
476                         (void)unisig_clear_vcc(usp, uvp,
477                                         T_ATM_CAUSE_NORMAL_CALL_CLEARING);
478                 } else if (uvp->uv_type & VCC_PVC) {
479                         /*
480                          * Notify PVC owner of the state change
481                          */
482                         switch(cause) {
483                         case UNI_DOWN:
484                                 uvp->uv_sstate = UNI_PVC_ACT_DOWN;
485                                 break;
486                         case UNI_UP:
487                                 uvp->uv_sstate = UNI_PVC_ACTIVE;
488                                 break;
489                         }
490                         atm_cm_cleared(uvp->uv_connvc, cause);
491                 } else {
492                         log(LOG_ERR, "unisig: invalid VCC type: vccb=%p, type=%d\n",
493                                         uvp, uvp->uv_type);
494                 }
495         }
496         (void) splx(s);
497 }
498 #endif
499
500
501 /*
502  * Copy connection parameters from UNI 3.0 message IEs into
503  * an attribute block
504  *
505  * Arguments:
506  *      usp     pointer to UNISIG protocol instance
507  *      msg     pointer to the SETUP message
508  *      ap      pointer to the attribute block
509  *
510  * Returns:
511  *      none
512  *
513  */
514 void
515 unisig_save_attrs(usp, msg, ap)
516         struct unisig           *usp;
517         struct unisig_msg       *msg;
518         Atm_attributes          *ap;
519 {
520         /*
521          * Sanity check
522          */
523         if (!msg || !ap)
524                 return;
525
526         /*
527          * Save the AAL parameters (AAL 3/4 and AAL 5 only)
528          */
529         if (msg->msg_ie_aalp) {
530                 struct ie_generic       *aalp = msg->msg_ie_aalp;
531
532                 switch(msg->msg_ie_aalp->ie_aalp_aal_type) {
533                 case UNI_IE_AALP_AT_AAL3:
534                         ap->aal.tag = T_ATM_PRESENT;
535                         ap->aal.type =
536                                 msg->msg_ie_aalp->ie_aalp_aal_type;
537                         ap->aal.v.aal4.forward_max_SDU_size =
538                                 msg->msg_ie_aalp->ie_aalp_4_fwd_max_sdu;
539                         ap->aal.v.aal4.backward_max_SDU_size =
540                                 msg->msg_ie_aalp->ie_aalp_4_bkwd_max_sdu;
541                         ap->aal.v.aal4.SSCS_type =
542                                 msg->msg_ie_aalp->ie_aalp_4_sscs_type;
543                         if (aalp->ie_aalp_4_mid_range == T_ATM_ABSENT) {
544                                 ap->aal.v.aal4.mid_low = T_ATM_ABSENT;
545                                 ap->aal.v.aal4.mid_high = T_ATM_ABSENT;
546                         } else {
547                                 if (usp->us_proto == ATM_SIG_UNI30) {
548                                         ap->aal.v.aal4.mid_low = 0;
549                                         ap->aal.v.aal4.mid_high =
550                                                 aalp->ie_aalp_4_mid_range
551                                                         & UNI_IE_AALP_A3_R_MASK;
552                                 } else {
553                                         ap->aal.v.aal4.mid_low =
554                                                 (aalp->ie_aalp_4_mid_range >>
555                                                         UNI_IE_AALP_A3_R_SHIFT)
556                                                         & UNI_IE_AALP_A3_R_MASK;
557                                         ap->aal.v.aal4.mid_high =
558                                                 aalp->ie_aalp_4_mid_range
559                                                         & UNI_IE_AALP_A3_R_MASK;
560                                 }
561                         }
562                         break;
563                 case UNI_IE_AALP_AT_AAL5:
564                         ap->aal.tag = T_ATM_PRESENT;
565                         ap->aal.type =
566                                 msg->msg_ie_aalp->ie_aalp_aal_type;
567                         ap->aal.v.aal5.forward_max_SDU_size =
568                                 msg->msg_ie_aalp->ie_aalp_5_fwd_max_sdu;
569                         ap->aal.v.aal5.backward_max_SDU_size =
570                                 msg->msg_ie_aalp->ie_aalp_5_bkwd_max_sdu;
571                         ap->aal.v.aal5.SSCS_type =
572                                 msg->msg_ie_aalp->ie_aalp_5_sscs_type;
573                         break;
574                 }
575         }
576
577         /*
578          * Save traffic descriptor attributes
579          */
580         if (msg->msg_ie_clrt) {
581                 ap->traffic.tag = T_ATM_PRESENT;
582                 ap->traffic.v.forward.PCR_high_priority =
583                                 msg->msg_ie_clrt->ie_clrt_fwd_peak;
584                 ap->traffic.v.forward.PCR_all_traffic =
585                                 msg->msg_ie_clrt->ie_clrt_fwd_peak_01;
586                 ap->traffic.v.forward.SCR_high_priority =
587                                 msg->msg_ie_clrt->ie_clrt_fwd_sust;
588                 ap->traffic.v.forward.SCR_all_traffic =
589                                 msg->msg_ie_clrt->ie_clrt_fwd_sust_01;
590                 ap->traffic.v.forward.MBS_high_priority =
591                                 msg->msg_ie_clrt->ie_clrt_fwd_burst;
592                 ap->traffic.v.forward.MBS_all_traffic =
593                                 msg->msg_ie_clrt->ie_clrt_fwd_burst_01;
594                 ap->traffic.v.backward.PCR_high_priority =
595                                 msg->msg_ie_clrt->ie_clrt_bkwd_peak;
596                 ap->traffic.v.backward.PCR_all_traffic =
597                                 msg->msg_ie_clrt->ie_clrt_bkwd_peak_01;
598                 ap->traffic.v.backward.SCR_high_priority =
599                                 msg->msg_ie_clrt->ie_clrt_bkwd_sust;
600                 ap->traffic.v.backward.SCR_all_traffic =
601                                 msg->msg_ie_clrt->ie_clrt_bkwd_sust_01;
602                 ap->traffic.v.backward.MBS_high_priority =
603                                 msg->msg_ie_clrt->ie_clrt_bkwd_burst;
604                 ap->traffic.v.backward.MBS_all_traffic =
605                                 msg->msg_ie_clrt->ie_clrt_bkwd_burst_01;
606                 ap->traffic.v.best_effort =
607                                 msg->msg_ie_clrt->ie_clrt_best_effort;
608                 if (msg->msg_ie_clrt->ie_clrt_tm_options ==
609                                 T_ATM_ABSENT) {
610                         ap->traffic.v.forward.tagging = T_NO;
611                         ap->traffic.v.backward.tagging = T_NO;
612                 } else {
613                         ap->traffic.v.forward.tagging =
614                                         (msg->msg_ie_clrt->ie_clrt_tm_options &
615                                         UNI_IE_CLRT_TM_FWD_TAG) != 0;
616                         ap->traffic.v.backward.tagging =
617                                         (msg->msg_ie_clrt->ie_clrt_tm_options &
618                                         UNI_IE_CLRT_TM_BKWD_TAG) != 0;
619                 }
620         }
621
622         /*
623          * Save broadband bearer attributes
624          */
625         if (msg->msg_ie_bbcp) {
626                 ap->bearer.tag = T_ATM_PRESENT;
627                 ap->bearer.v.bearer_class =
628                                 msg->msg_ie_bbcp->ie_bbcp_bearer_class;
629                 ap->bearer.v.traffic_type =
630                                 msg->msg_ie_bbcp->ie_bbcp_traffic_type;
631                 ap->bearer.v.timing_requirements =
632                                 msg->msg_ie_bbcp->ie_bbcp_timing_req;
633                 ap->bearer.v.clipping_susceptibility =
634                                 msg->msg_ie_bbcp->ie_bbcp_clipping;
635                 ap->bearer.v.connection_configuration =
636                                 msg->msg_ie_bbcp->ie_bbcp_conn_config;
637         }
638
639         /*
640          * Save broadband high layer attributes
641          */
642         if (msg->msg_ie_bhli) {
643                 ap->bhli.tag = T_ATM_PRESENT;
644                 ap->bhli.v.ID_type = msg->msg_ie_bhli->ie_bhli_type;
645                 switch(ap->bhli.v.ID_type) {
646                 case T_ATM_ISO_APP_ID:
647                         KM_COPY(msg->msg_ie_bhli->ie_bhli_info,
648                                         ap->bhli.v.ID.ISO_ID,
649                                         sizeof(ap->bhli.v.ID.ISO_ID));
650                         break;
651                 case T_ATM_USER_APP_ID:
652                         KM_COPY(msg->msg_ie_bhli->ie_bhli_info,
653                                         ap->bhli.v.ID.user_defined_ID,
654                                         sizeof(ap->bhli.v.ID.user_defined_ID));
655                         break;
656                 case T_ATM_VENDOR_APP_ID:
657                         KM_COPY(msg->msg_ie_bhli->ie_bhli_info,
658                                         ap->bhli.v.ID.vendor_ID.OUI,
659                                         sizeof(ap->bhli.v.ID.vendor_ID.OUI));
660                         KM_COPY(&msg->msg_ie_bhli->ie_bhli_info[sizeof(ap->bhli.v.ID.vendor_ID.OUI)-1],
661                                         ap->bhli.v.ID.vendor_ID.app_ID,
662                                         sizeof(ap->bhli.v.ID.vendor_ID.app_ID));
663                         break;
664                 }
665         }
666
667         /*
668          * Save Broadband low layer, user layer 2 and 3 attributes
669          */
670         if (msg->msg_ie_blli) {
671                 /*
672                  * Layer 2 parameters
673                  */
674                 switch(msg->msg_ie_blli->ie_blli_l2_id) {
675                 case UNI_IE_BLLI_L2P_ISO1745:
676                 case UNI_IE_BLLI_L2P_Q921:
677                 case UNI_IE_BLLI_L2P_X25L:
678                 case UNI_IE_BLLI_L2P_X25M:
679                 case UNI_IE_BLLI_L2P_LAPB:
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_LLC:
684                 case UNI_IE_BLLI_L2P_X75:
685                 case UNI_IE_BLLI_L2P_Q922:
686                 case UNI_IE_BLLI_L2P_ISO7776:
687                         ap->blli.tag_l2 = T_ATM_PRESENT;
688                         ap->blli.v.layer_2_protocol.ID_type =
689                                         T_ATM_SIMPLE_ID;
690                         ap->blli.v.layer_2_protocol.ID.simple_ID =
691                                         msg->msg_ie_blli->ie_blli_l2_id;
692                         break;
693                 case UNI_IE_BLLI_L2P_USER:
694                         ap->blli.tag_l2 = T_ATM_PRESENT;
695                         ap->blli.v.layer_2_protocol.ID_type =
696                                         T_ATM_USER_ID;
697                         ap->blli.v.layer_2_protocol.ID.user_defined_ID =
698                                         msg->msg_ie_blli->ie_blli_l2_user_proto;
699                         break;
700                 default:
701                         ap->blli.tag_l2 = T_ATM_ABSENT;
702                 }
703                 if (ap->blli.tag_l2 == T_ATM_PRESENT) {
704                         ap->blli.v.layer_2_protocol.mode =
705                                         msg->msg_ie_blli->ie_blli_l2_mode;
706                         ap->blli.v.layer_2_protocol.window_size =
707                                         msg->msg_ie_blli->ie_blli_l2_window;
708                 }
709
710                 /*
711                  * Layer 3 parameters
712                  */
713                 switch(msg->msg_ie_blli->ie_blli_l3_id) {
714                 case UNI_IE_BLLI_L3P_X25:
715                 case UNI_IE_BLLI_L3P_ISO8208:
716                 case UNI_IE_BLLI_L3P_ISO8878:
717                 case UNI_IE_BLLI_L3P_ISO8473:
718                 case UNI_IE_BLLI_L3P_T70:
719                         ap->blli.tag_l3 = T_ATM_PRESENT;
720                         ap->blli.v.layer_3_protocol.ID_type =
721                                         T_ATM_SIMPLE_ID;
722                         ap->blli.v.layer_3_protocol.ID.simple_ID =
723                                         msg->msg_ie_blli->ie_blli_l3_id;
724                         break;
725                 case UNI_IE_BLLI_L3P_ISO9577:
726                         ap->blli.tag_l3 = T_ATM_PRESENT;
727                         ap->blli.v.layer_3_protocol.ID_type =
728                                         T_ATM_SIMPLE_ID;
729                         ap->blli.v.layer_3_protocol.ID.simple_ID =
730                                         msg->msg_ie_blli->ie_blli_l3_id;
731                         if (msg->msg_ie_blli->ie_blli_l3_ipi ==
732                                         UNI_IE_BLLI_L3IPI_SNAP) {
733                                 KM_COPY(msg->msg_ie_blli->ie_blli_l3_oui,
734                                                 ap->blli.v.layer_3_protocol.ID.SNAP_ID.OUI,
735                                                 sizeof(ap->blli.v.layer_3_protocol.ID.SNAP_ID.OUI));
736                                 KM_COPY(msg->msg_ie_blli->ie_blli_l3_pid,
737                                                 ap->blli.v.layer_3_protocol.ID.SNAP_ID.PID,
738                                                 sizeof(ap->blli.v.layer_3_protocol.ID.SNAP_ID.PID));
739                         } else {
740                                 ap->blli.v.layer_3_protocol.ID.IPI_ID =
741                                                 msg->msg_ie_blli->ie_blli_l3_ipi;
742                         }
743                         break;
744                 case UNI_IE_BLLI_L3P_USER:
745                         ap->blli.tag_l3 = T_ATM_PRESENT;
746                         ap->blli.v.layer_3_protocol.ID_type =
747                                         T_ATM_USER_ID;
748                         ap->blli.v.layer_3_protocol.ID.user_defined_ID =
749                                         msg->msg_ie_blli->ie_blli_l3_user_proto;
750                         break;
751                 default:
752                         ap->blli.tag_l3 = T_ATM_ABSENT;
753                 }
754                 if (ap->blli.tag_l3 == T_ATM_PRESENT) {
755                         ap->blli.v.layer_3_protocol.mode =
756                                         msg->msg_ie_blli->ie_blli_l3_mode;
757                         ap->blli.v.layer_3_protocol.packet_size =
758                                         msg->msg_ie_blli->ie_blli_l3_packet_size;
759                         ap->blli.v.layer_3_protocol.window_size =
760                                         msg->msg_ie_blli->ie_blli_l3_window;
761                 }
762         }
763
764         /*
765          * Save the called party address and subaddress
766          */
767         if (msg->msg_ie_cdad) {
768                 ap->called.tag = T_ATM_PRESENT;
769                 ATM_ADDR_COPY(&msg->msg_ie_cdad->ie_cdad_addr,
770                                 &ap->called.addr);
771                 ap->called.subaddr.address_format = T_ATM_ABSENT;
772                 ap->called.subaddr.address_length = 0;
773         }
774         if (msg->msg_ie_cdsa) {
775                 ATM_ADDR_COPY(&msg->msg_ie_cdsa->ie_cdsa_addr,
776                                 &ap->called.subaddr);
777         }
778
779         /*
780          * Save the calling party address and subaddress
781          */
782         if (msg->msg_ie_cgad) {
783                 ap->calling.tag = T_ATM_PRESENT;
784                 ATM_ADDR_COPY(&msg->msg_ie_cgad->ie_cgad_addr,
785                                 &ap->calling.addr);
786                 ap->calling.subaddr.address_format = T_ATM_ABSENT;
787                 ap->calling.subaddr.address_length = 0;
788         }
789
790         if (msg->msg_ie_cgsa) {
791                 ATM_ADDR_COPY(&msg->msg_ie_cgsa->ie_cgsa_addr,
792                                 &ap->calling.subaddr);
793         }
794
795         /*
796          * Save quality of service attributes
797          */
798         if (msg->msg_ie_qosp) {
799                 ap->qos.tag = T_ATM_PRESENT;
800                 ap->qos.v.coding_standard = msg->msg_ie_qosp->ie_coding;
801                 ap->qos.v.forward.qos_class = msg->msg_ie_qosp->ie_qosp_fwd_class;
802                 ap->qos.v.forward.qos_class =
803                                 msg->msg_ie_qosp->ie_qosp_bkwd_class;
804         }
805
806         /*
807          * Save transit network attributes
808          */
809         if (msg->msg_ie_trnt) {
810                 ap->transit.tag = T_ATM_PRESENT;
811                 ap->transit.v.length = 
812                                 MIN(msg->msg_ie_trnt->ie_trnt_id_len,
813                                 sizeof(ap->transit.v.network_id));
814                 KM_COPY(msg->msg_ie_trnt->ie_trnt_id,
815                                 ap->transit.v.network_id,
816                                 ap->transit.v.length);
817         }
818
819         /*
820          * Save cause code
821          */
822         if (msg->msg_ie_caus) {
823                 ap->cause.tag = T_ATM_PRESENT;
824                 ap->cause.v.coding_standard =
825                                 msg->msg_ie_caus->ie_coding;
826                 ap->cause.v.location = 
827                                 msg->msg_ie_caus->ie_caus_loc;
828                 ap->cause.v.cause_value = 
829                                 msg->msg_ie_caus->ie_caus_cause;
830                 KM_ZERO(ap->cause.v.diagnostics,
831                                 sizeof(ap->cause.v.diagnostics));
832 #ifdef NOTDEF
833                 KM_COPY(msg->msg_ie_caus->ie_caus_diagnostic,
834                                 ap->transit.v.diagnostics,
835                                 MIN(sizeof(ap->transit.v.diagnostics),
836                                 msg->msg_ie_caus->ie_caus_diag_len));
837 #endif
838         }
839 }
840
841
842 /*
843  * Copy connection parameters from an attribute block into
844  * UNI 3.0 message IEs
845  *
846  * Arguments:
847  *      usp     pointer to UNISIG protocol instance
848  *      msg     pointer to the SETUP message
849  *      ap      pointer to the attribute block
850  *
851  * Returns:
852  *      0       everything OK
853  *      else    error encountered
854  *
855  */
856 int
857 unisig_set_attrs(usp, msg, ap)
858         struct unisig           *usp;
859         struct unisig_msg       *msg;
860         Atm_attributes          *ap;
861 {
862         int                     err = 0;
863
864         /*
865          * Sanity check
866          */
867         if (!msg || !ap)
868                 return(EINVAL);
869
870         /*
871          * Set the AAL parameters (AAL 3/4 and AAL 5 only)
872          */
873         if (ap->aal.tag == T_ATM_PRESENT) {
874                 if (!msg->msg_ie_aalp) {
875                         msg->msg_ie_aalp = (struct ie_generic *)
876                                         atm_allocate(&unisig_iepool);
877                         if (msg->msg_ie_aalp == NULL) {
878                                 err = ENOMEM;
879                                 goto done;
880                         }
881                 }
882                 KM_COPY(&ie_aalp_absent,
883                                 &msg->msg_ie_aalp->ie_u.ie_aalp,
884                                 sizeof(ie_aalp_absent));
885                 msg->msg_ie_aalp->ie_ident = UNI_IE_AALP;
886                 msg->msg_ie_aalp->ie_aalp_aal_type = ap->aal.type;
887                 switch(ap->aal.type) {
888                 case ATM_AAL3_4:
889                         msg->msg_ie_aalp->ie_aalp_4_fwd_max_sdu =
890                                         ap->aal.v.aal4.forward_max_SDU_size;
891                         msg->msg_ie_aalp->ie_aalp_4_bkwd_max_sdu =
892                                         ap->aal.v.aal4.backward_max_SDU_size;
893                         msg->msg_ie_aalp->ie_aalp_4_mode = UNI_IE_AALP_A5_M_MSG;
894                         msg->msg_ie_aalp->ie_aalp_4_sscs_type =
895                                         ap->aal.v.aal4.SSCS_type;
896                         if (ap->aal.v.aal4.mid_low == T_ATM_ABSENT) {
897                                 msg->msg_ie_aalp->ie_aalp_4_mid_range =
898                                         T_ATM_ABSENT;
899                         } else {
900                                 if (usp->us_proto == ATM_SIG_UNI30) {
901                                         msg->msg_ie_aalp->ie_aalp_4_mid_range =
902                                                 ap->aal.v.aal4.mid_high &
903                                                         UNI_IE_AALP_A3_R_MASK;
904                                 } else {
905                                         msg->msg_ie_aalp->ie_aalp_4_mid_range =
906                                                 ((ap->aal.v.aal4.mid_low &
907                                                         UNI_IE_AALP_A3_R_MASK)
908                                                     << UNI_IE_AALP_A3_R_SHIFT)
909                                                   |
910                                                  (ap->aal.v.aal4.mid_high &
911                                                         UNI_IE_AALP_A3_R_MASK);
912                                 }
913                         }
914                         break;
915                 case ATM_AAL5:
916                         msg->msg_ie_aalp->ie_aalp_5_fwd_max_sdu =
917                                         ap->aal.v.aal5.forward_max_SDU_size;
918                         msg->msg_ie_aalp->ie_aalp_5_bkwd_max_sdu =
919                                         ap->aal.v.aal5.backward_max_SDU_size;
920                         msg->msg_ie_aalp->ie_aalp_5_mode =
921                                         UNI_IE_AALP_A5_M_MSG;
922                         msg->msg_ie_aalp->ie_aalp_5_sscs_type =
923                                         ap->aal.v.aal5.SSCS_type;
924                         break;
925                 }
926         }
927
928         /*
929          * Set traffic descriptor attributes
930          */
931         if (ap->traffic.tag == T_ATM_PRESENT) {
932                 if (!msg->msg_ie_clrt) {
933                         msg->msg_ie_clrt = (struct ie_generic *)
934                                         atm_allocate(&unisig_iepool);
935                         if (msg->msg_ie_clrt == NULL) {
936                                 err = ENOMEM;
937                                 goto done;
938                         }
939                 }
940                 KM_COPY(&ie_clrt_absent,
941                                 &msg->msg_ie_clrt->ie_u.ie_clrt,
942                                 sizeof(ie_clrt_absent));
943                 msg->msg_ie_clrt->ie_ident = UNI_IE_CLRT;
944                 msg->msg_ie_clrt->ie_clrt_fwd_peak =
945                                 ap->traffic.v.forward.PCR_high_priority;
946                 msg->msg_ie_clrt->ie_clrt_fwd_peak_01 =
947                                 ap->traffic.v.forward.PCR_all_traffic;
948                 msg->msg_ie_clrt->ie_clrt_fwd_sust =
949                                 ap->traffic.v.forward.SCR_high_priority;
950                 msg->msg_ie_clrt->ie_clrt_fwd_sust_01 =
951                                 ap->traffic.v.forward.SCR_all_traffic;
952                 msg->msg_ie_clrt->ie_clrt_fwd_burst =
953                                 ap->traffic.v.forward.MBS_high_priority;
954                 msg->msg_ie_clrt->ie_clrt_fwd_burst_01 =
955                                 ap->traffic.v.forward.MBS_all_traffic;
956                 msg->msg_ie_clrt->ie_clrt_bkwd_peak =
957                                 ap->traffic.v.backward.PCR_high_priority;
958                 msg->msg_ie_clrt->ie_clrt_bkwd_peak_01 =
959                                 ap->traffic.v.backward.PCR_all_traffic;
960                 msg->msg_ie_clrt->ie_clrt_bkwd_sust =
961                                 ap->traffic.v.backward.SCR_high_priority;
962                 msg->msg_ie_clrt->ie_clrt_bkwd_sust_01 =
963                                 ap->traffic.v.backward.SCR_all_traffic;
964                 msg->msg_ie_clrt->ie_clrt_bkwd_burst =
965                                 ap->traffic.v.backward.MBS_high_priority;
966                 msg->msg_ie_clrt->ie_clrt_bkwd_burst_01 =
967                                 ap->traffic.v.backward.MBS_all_traffic;
968                 msg->msg_ie_clrt->ie_clrt_best_effort =
969                                 ap->traffic.v.best_effort;
970                 msg->msg_ie_clrt->ie_clrt_tm_options = 0;
971                 if (ap->traffic.v.forward.tagging) {
972                         msg->msg_ie_clrt->ie_clrt_tm_options |=
973                                         UNI_IE_CLRT_TM_FWD_TAG;
974                 }
975                 if (ap->traffic.v.backward.tagging) {
976                         msg->msg_ie_clrt->ie_clrt_tm_options |=
977                                         UNI_IE_CLRT_TM_BKWD_TAG;
978                 }
979                 if (msg->msg_ie_clrt->ie_clrt_tm_options == 0) {
980                         msg->msg_ie_clrt->ie_clrt_tm_options =
981                                         T_ATM_ABSENT;
982                 }
983         }
984
985         /*
986          * Set broadband bearer attributes
987          */
988         if (ap->bearer.tag == T_ATM_PRESENT) {
989                 if (!msg->msg_ie_bbcp) {
990                         msg->msg_ie_bbcp = (struct ie_generic *)
991                                         atm_allocate(&unisig_iepool);
992                         if (msg->msg_ie_bbcp == NULL) {
993                                 err = ENOMEM;
994                                 goto done;
995                         }
996                 }
997                 KM_COPY(&ie_bbcp_absent,
998                                 &msg->msg_ie_bbcp->ie_u.ie_bbcp,
999                                 sizeof(ie_bbcp_absent));
1000                 msg->msg_ie_bbcp->ie_ident = UNI_IE_BBCP;
1001                 msg->msg_ie_bbcp->ie_bbcp_bearer_class =
1002                                 ap->bearer.v.bearer_class;
1003                 msg->msg_ie_bbcp->ie_bbcp_traffic_type =
1004                                 ap->bearer.v.traffic_type;
1005                 msg->msg_ie_bbcp->ie_bbcp_timing_req =
1006                                 ap->bearer.v.timing_requirements;
1007                 msg->msg_ie_bbcp->ie_bbcp_clipping =
1008                                 ap->bearer.v.clipping_susceptibility;
1009                 msg->msg_ie_bbcp->ie_bbcp_conn_config =
1010                                 ap->bearer.v.connection_configuration;
1011         }
1012
1013         /*
1014          * Set broadband high layer attributes
1015          */
1016         if (ap->bhli.tag == T_ATM_PRESENT) {
1017                 if (!msg->msg_ie_bhli) {
1018                         msg->msg_ie_bhli = (struct ie_generic *)
1019                                         atm_allocate(&unisig_iepool);
1020                         if (msg->msg_ie_bhli == NULL) {
1021                                 err = ENOMEM;
1022                                 goto done;
1023                         }
1024                 }
1025                 KM_COPY(&ie_bhli_absent,
1026                                 &msg->msg_ie_bhli->ie_u.ie_bhli,
1027                                 sizeof(ie_bhli_absent));
1028                 msg->msg_ie_bhli->ie_ident = UNI_IE_BHLI;
1029                 msg->msg_ie_bhli->ie_bhli_type = ap->bhli.v.ID_type;
1030                 switch (ap->bhli.v.ID_type) {
1031                 case T_ATM_ISO_APP_ID:
1032                         KM_COPY(ap->bhli.v.ID.ISO_ID,
1033                                         msg->msg_ie_bhli->ie_bhli_info,
1034                                         sizeof(ap->bhli.v.ID.ISO_ID));
1035                         break;
1036                 case T_ATM_USER_APP_ID:
1037                         KM_COPY(ap->bhli.v.ID.user_defined_ID,
1038                                         msg->msg_ie_bhli->ie_bhli_info,
1039                                         sizeof(ap->bhli.v.ID.user_defined_ID));
1040                         break;
1041                 case T_ATM_VENDOR_APP_ID:
1042                         KM_COPY(ap->bhli.v.ID.vendor_ID.OUI,
1043                                         msg->msg_ie_bhli->ie_bhli_info,
1044                                         sizeof(ap->bhli.v.ID.vendor_ID.OUI));
1045                         KM_COPY(ap->bhli.v.ID.vendor_ID.app_ID,
1046                                         &msg->msg_ie_bhli->ie_bhli_info[sizeof(ap->bhli.v.ID.vendor_ID.OUI)-1],
1047                                         sizeof(ap->bhli.v.ID.vendor_ID.app_ID));
1048                         break;
1049                 }
1050         }
1051
1052         /*
1053          * Set Broadband low layer, user layer 2 and 3 attributes
1054          */
1055         if (ap->blli.tag_l2 == T_ATM_PRESENT ||
1056                         ap->blli.tag_l3 == T_ATM_PRESENT) {
1057                 if (!msg->msg_ie_blli) {
1058                         msg->msg_ie_blli = (struct ie_generic *)
1059                                         atm_allocate(&unisig_iepool);
1060                         if (msg->msg_ie_blli == NULL) {
1061                                 err = ENOMEM;
1062                                 goto done;
1063                         }
1064                 }
1065                 KM_COPY(&ie_blli_absent,
1066                                 &msg->msg_ie_blli->ie_u.ie_blli,
1067                                 sizeof(ie_blli_absent));
1068                 msg->msg_ie_blli->ie_ident = UNI_IE_BLLI;
1069
1070                 if (ap->blli.tag_l2 == T_ATM_PRESENT) {
1071                         switch(ap->blli.v.layer_2_protocol.ID_type) {
1072                         case T_ATM_SIMPLE_ID:
1073                                 msg->msg_ie_blli->ie_blli_l2_id =
1074                                                 ap->blli.v.layer_2_protocol.ID.simple_ID;
1075                                 break;
1076                         case T_ATM_USER_ID:
1077                                 msg->msg_ie_blli->ie_blli_l2_id =
1078                                                 UNI_IE_BLLI_L2P_USER;
1079                                 msg->msg_ie_blli->ie_blli_l2_user_proto =
1080                                                 ap->blli.v.layer_2_protocol.ID.user_defined_ID;
1081                                 break;
1082                         }
1083                         if (ap->blli.v.layer_2_protocol.ID_type !=
1084                                         T_ATM_ABSENT) {
1085                                 msg->msg_ie_blli->ie_blli_l2_mode =
1086                                                 ap->blli.v.layer_2_protocol.mode;
1087                                 msg->msg_ie_blli->ie_blli_l2_window =
1088                                                 ap->blli.v.layer_2_protocol.window_size;
1089                         }
1090                 }
1091
1092                 if (ap->blli.tag_l3 == T_ATM_PRESENT) {
1093                         switch (ap->blli.v.layer_3_protocol.ID_type) {
1094                         case T_ATM_SIMPLE_ID:
1095                                 msg->msg_ie_blli->ie_blli_l3_id =
1096                                                 ap->blli.v.layer_3_protocol.ID.simple_ID;
1097                                 break;
1098
1099                         case T_ATM_IPI_ID:
1100                                 msg->msg_ie_blli->ie_blli_l3_id =
1101                                                 UNI_IE_BLLI_L3P_ISO9577;
1102                                 msg->msg_ie_blli->ie_blli_l3_ipi =
1103                                                 ap->blli.v.layer_3_protocol.ID.IPI_ID;
1104                                 break;
1105
1106                         case T_ATM_SNAP_ID:
1107                                 msg->msg_ie_blli->ie_blli_l3_id =
1108                                                 UNI_IE_BLLI_L3P_ISO9577;
1109                                 msg->msg_ie_blli->ie_blli_l3_ipi =
1110                                                 UNI_IE_BLLI_L3IPI_SNAP;
1111                                 KM_COPY(ap->blli.v.layer_3_protocol.ID.SNAP_ID.OUI,
1112                                                 msg->msg_ie_blli->ie_blli_l3_oui,
1113                                                 sizeof(msg->msg_ie_blli->ie_blli_l3_oui));
1114                                 KM_COPY(ap->blli.v.layer_3_protocol.ID.SNAP_ID.PID,
1115                                                 msg->msg_ie_blli->ie_blli_l3_pid,
1116                                                 sizeof(msg->msg_ie_blli->ie_blli_l3_pid));
1117                                 break;
1118
1119                         case T_ATM_USER_ID:
1120                                 msg->msg_ie_blli->ie_blli_l3_id =
1121                                                 UNI_IE_BLLI_L3P_USER;
1122                                 msg->msg_ie_blli->ie_blli_l3_user_proto =
1123                                                 ap->blli.v.layer_3_protocol.ID.user_defined_ID;
1124                                 break;
1125                         }
1126                         if (ap->blli.v.layer_3_protocol.ID_type
1127                                         != T_ATM_ABSENT) {
1128                                 msg->msg_ie_blli->ie_blli_l3_mode =
1129                                                 ap->blli.v.layer_3_protocol.mode;
1130                                 msg->msg_ie_blli->ie_blli_l3_packet_size =
1131                                                 ap->blli.v.layer_3_protocol.packet_size;
1132                                 msg->msg_ie_blli->ie_blli_l3_window =
1133                                                 ap->blli.v.layer_3_protocol.window_size;
1134                         }
1135                 }
1136         }
1137
1138         /*
1139          * Set the called party address and subaddress
1140          */
1141         if (ap->called.tag == T_ATM_PRESENT) {
1142                 if (!msg->msg_ie_cdad) {
1143                         msg->msg_ie_cdad = (struct ie_generic *)
1144                                         atm_allocate(&unisig_iepool);
1145                         if (msg->msg_ie_cdad == NULL) {
1146                                 err = ENOMEM;
1147                                 goto done;
1148                         }
1149                 }
1150                 KM_COPY(&ie_cdad_absent,
1151                                 &msg->msg_ie_cdad->ie_u.ie_cdad,
1152                                 sizeof(ie_cdad_absent));
1153                 msg->msg_ie_cdad->ie_ident = UNI_IE_CDAD;
1154                 ATM_ADDR_COPY(&ap->called.addr,
1155                                 &msg->msg_ie_cdad->ie_cdad_addr);
1156
1157                 if (ap->called.subaddr.address_format != T_ATM_ABSENT) {
1158                         if (!msg->msg_ie_cdsa) {
1159                                 msg->msg_ie_cdsa = (struct ie_generic *)
1160                                                 atm_allocate(&unisig_iepool);
1161                                 if (msg->msg_ie_cdsa == NULL) {
1162                                         err = ENOMEM;
1163                                         goto done;
1164                                 }
1165                         }
1166                         KM_COPY(&ie_cdsa_absent,
1167                                         &msg->msg_ie_cdsa->ie_u.ie_cdsa,
1168                                         sizeof(ie_cdsa_absent));
1169                         msg->msg_ie_cdsa->ie_ident = UNI_IE_CDSA;
1170                         ATM_ADDR_COPY(&ap->called.subaddr,
1171                                         &msg->msg_ie_cdsa->ie_cdsa_addr);
1172                 }
1173         }
1174
1175         /*
1176          * Set the calling party address and subaddress
1177          */
1178
1179         if (ap->calling.tag == T_ATM_PRESENT) {
1180                 if (!msg->msg_ie_cgad) {
1181                         msg->msg_ie_cgad = (struct ie_generic *)
1182                                         atm_allocate(&unisig_iepool);
1183                         if (msg->msg_ie_cgad == NULL) {
1184                                 err = ENOMEM;
1185                                 goto done;
1186                         }
1187                 }
1188                 KM_COPY(&ie_cgad_absent,
1189                                 &msg->msg_ie_cgad->ie_u.ie_cgad,
1190                                 sizeof(ie_cgad_absent));
1191                 msg->msg_ie_cgsa->ie_ident = UNI_IE_CGSA;
1192                 ATM_ADDR_COPY(&ap->calling.addr,
1193                                 &msg->msg_ie_cgad->ie_cgad_addr);
1194
1195                 if (ap->calling.subaddr.address_format !=
1196                                 T_ATM_ABSENT) {
1197                         if (!msg->msg_ie_cgsa) {
1198                                 msg->msg_ie_cgsa = (struct ie_generic *)
1199                                                 atm_allocate(&unisig_iepool);
1200                                 if (msg->msg_ie_cgsa == NULL) {
1201                                         err = ENOMEM;
1202                                         goto done;
1203                                 }
1204                         }
1205                         KM_COPY(&ie_cgsa_absent,
1206                                         &msg->msg_ie_cgsa->ie_u.ie_cgsa,
1207                                         sizeof(ie_cgsa_absent));
1208                         msg->msg_ie_cgsa->ie_ident = UNI_IE_CGSA;
1209                         ATM_ADDR_COPY(&ap->calling.subaddr,
1210                                         &msg->msg_ie_cgsa->ie_cgsa_addr);
1211                 }
1212         }
1213
1214         /*
1215          * Set quality of service attributes
1216          */
1217         if (ap->qos.tag == T_ATM_PRESENT) {
1218                 if (!msg->msg_ie_qosp) {
1219                         msg->msg_ie_qosp = (struct ie_generic *)
1220                                         atm_allocate(&unisig_iepool);
1221                         if (msg->msg_ie_qosp == NULL) {
1222                                 err = ENOMEM;
1223                                 goto done;
1224                         }
1225                 }
1226                 KM_COPY(&ie_qosp_absent,
1227                                 &msg->msg_ie_qosp->ie_u.ie_qosp,
1228                                 sizeof(ie_qosp_absent));
1229                 msg->msg_ie_qosp->ie_ident = UNI_IE_QOSP;
1230                 if (usp->us_proto == ATM_SIG_UNI30)
1231                         msg->msg_ie_qosp->ie_coding = UNI_IE_CODE_STD;
1232                 else if ((ap->qos.v.forward.qos_class == 
1233                                         T_ATM_QOS_CLASS_0) || 
1234                            (ap->qos.v.backward.qos_class == 
1235                                         T_ATM_QOS_CLASS_0))
1236                         msg->msg_ie_qosp->ie_coding = UNI_IE_CODE_CCITT;
1237                 else
1238                         msg->msg_ie_qosp->ie_coding = ap->qos.v.coding_standard;
1239                 msg->msg_ie_qosp->ie_qosp_fwd_class =
1240                                 ap->qos.v.forward.qos_class;
1241                 msg->msg_ie_qosp->ie_qosp_bkwd_class =
1242                                 ap->qos.v.backward.qos_class;
1243         }
1244
1245         /*
1246          * Set transit network attributes
1247          */
1248         if (ap->transit.tag == T_ATM_PRESENT &&
1249                                 ap->transit.v.length != 0) {
1250                 if (!msg->msg_ie_trnt) {
1251                         msg->msg_ie_trnt = (struct ie_generic *)
1252                                         atm_allocate(&unisig_iepool);
1253                         if (msg->msg_ie_trnt == NULL) {
1254                                 err = ENOMEM;
1255                                 goto done;
1256                         }
1257                 }
1258                 KM_COPY(&ie_trnt_absent,
1259                                 &msg->msg_ie_trnt->ie_u.ie_trnt,
1260                                 sizeof(ie_trnt_absent));
1261                 msg->msg_ie_trnt->ie_ident = UNI_IE_TRNT;
1262                 msg->msg_ie_trnt->ie_trnt_id_type =
1263                                 UNI_IE_TRNT_IDT_NATL;
1264                 msg->msg_ie_trnt->ie_trnt_id_plan =
1265                                 UNI_IE_TRNT_IDP_CIC;
1266                 KM_COPY(ap->transit.v.network_id,
1267                                 msg->msg_ie_trnt->ie_trnt_id,
1268                                 ap->transit.v.length);
1269         }
1270
1271         /*
1272          * Set cause code
1273          */
1274         if (ap->cause.tag == T_ATM_PRESENT) {
1275                 if (!msg->msg_ie_caus) {
1276                         msg->msg_ie_caus = (struct ie_generic *)
1277                                         atm_allocate(&unisig_iepool);
1278                         if (msg->msg_ie_caus == NULL) {
1279                                 err = ENOMEM;
1280                                 goto done;
1281                         }
1282                 }
1283                 KM_COPY(&ie_caus_absent,
1284                                 &msg->msg_ie_caus->ie_u.ie_caus,
1285                                 sizeof(ie_caus_absent));
1286                 msg->msg_ie_caus->ie_ident = UNI_IE_CAUS;
1287                 msg->msg_ie_caus->ie_coding =
1288                                 ap->cause.v.coding_standard;
1289                 msg->msg_ie_caus->ie_caus_loc =
1290                                 ap->cause.v.location;
1291                 msg->msg_ie_caus->ie_caus_cause =
1292                                 ap->cause.v.cause_value;
1293
1294                 /*
1295                  * Don't copy the diagnostics from the attribute
1296                  * block, as there's no way to tell how much of
1297                  * the diagnostic field is relevant
1298                  */
1299                 msg->msg_ie_caus->ie_caus_diag_len = 0;
1300         }
1301
1302 done:
1303         return(err);
1304 }