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