Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / netproto / atm / uni / unisig_util.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_util.c,v 1.6 2000/01/17 20:49:58 mks Exp $
27  *
28  */
29
30 /*
31  * ATM Forum UNI 3.0/3.1 Signalling Manager
32  * ----------------------------------------
33  *
34  * Protocol processing module
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include <netatm/uni/unisig_var.h>
41 #include <netatm/uni/unisig_msg.h>
42
43 #ifndef lint
44 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/unisig_util.c,v 1.6 2000/01/17 20:49:58 mks Exp $");
45 #endif
46
47
48 /*
49  * Free a UNISIG signalling message
50  *
51  * Free the passed message and any IEs that are attached to it
52  *
53  * Arguments:
54  *      msg     pointer to UNISIG protocol instance
55  *
56  * Returns:
57  *      none
58  *
59  */
60 void
61 unisig_free_msg(msg)
62         struct unisig_msg       *msg;
63 {
64         int                     i;
65         struct ie_generic       *ie, *ienxt;
66
67         ATM_DEBUG1("unisig_free_msg: msg=%p\n", msg);
68
69         /*
70          * First free all the IEs
71          */
72         for (i=0; i<UNI_MSG_IE_CNT; i++) {
73                 ie = msg->msg_ie_vec[i];
74                 while (ie) {
75                         ienxt = ie->ie_next;
76                         atm_free(ie);
77                         ie = ienxt;
78                 }
79         }
80
81         /*
82          * Finally, free the message structure itself
83          */
84         atm_free(msg);
85 }
86
87
88 /*
89  * Verify a VCCB
90  *
91  * Search UNISIG's VCCB queue to verify that a VCCB belongs to UNISIG.
92  *
93  * Arguments:
94  *      usp     pointer to UNISIG protocol instance
95  *      svp     pointer to a VCCB
96  *
97  * Returns:
98  *      TRUE    the VCCB belongs to UNISIG
99  *      FALSE   the VCCB doesn't belong to UNISIG
100  *
101  */
102 int
103 unisig_verify_vccb(usp, uvp)
104         struct unisig           *usp;
105         struct unisig_vccb      *uvp;
106
107 {
108         struct unisig_vccb      *utp, *uvnext;
109
110         for (utp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
111                         utp; utp = uvnext){
112                 uvnext = Q_NEXT(utp, struct unisig_vccb, uv_sigelem);
113                 if (uvp == utp) {
114                         return(TRUE);
115                 }
116         }
117         return(FALSE);
118 }
119
120
121 /*
122  * Find a connection
123  *
124  * Find a VCCB given the call reference
125  *
126  * Arguments:
127  *      usp     pointer to UNISIG protocol instance
128  *      cref    the call reference to search for
129  *
130  * Returns:
131  *      0       there is no such VCCB
132  *      uvp     the address of the VCCB
133  *
134  */
135 struct unisig_vccb *
136 unisig_find_conn(usp, cref)
137         struct unisig   *usp;
138         u_int           cref;
139
140 {
141         struct unisig_vccb      *uvp, *uvnext;
142
143         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
144                         uvp = uvnext){
145                 uvnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
146                 if (uvp->uv_call_ref == cref)
147                         break;
148         }
149         return(uvp);
150 }
151
152
153 /*
154  * Find a VCCB
155  *
156  * Find a VCCB given the VPI and VCI.
157  *
158  * Arguments:
159  *      usp     pointer to UNISIG protocol instance
160  *      vpi     the VPI to search for
161  *      vci     the VCI to search for
162  *      dir     the direction of the VCC (VCC_IN, VCC_OUT, or both).
163  *              If dir is set to zero, return the address of any VCCB
164  *              with the given VPI/VCI, regardless of direction.
165  *
166  * Returns:
167  *      0       there is no such VCCB
168  *      uvp     the address of the VCCB
169  *
170  */
171 struct unisig_vccb *
172 unisig_find_vpvc(usp, vpi, vci, dir)
173         struct unisig   *usp;
174         int             vpi, vci;
175         u_char          dir;
176
177 {
178         struct unisig_vccb      *uvp, *uvnext;
179
180         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
181                         uvp = uvnext){
182                 uvnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
183                 if (uvp->uv_vpi == vpi &&
184                                 uvp->uv_vci == vci &&
185                                 (uvp->uv_type & dir) == dir)
186                         break;
187         }
188         return(uvp);
189 }
190
191
192 /*
193  * Allocate a call reference value
194  *
195  * Arguments:
196  *      usp     pointer to UNISIG protocol instance
197  *
198  * Returns:
199  *      0       call reference not available
200  *      cref    the call reference value
201  *
202  */
203 int
204 unisig_alloc_call_ref(usp)
205         struct unisig   *usp;
206
207 {
208         int     cref;
209
210         /*
211          * Get the next call reference value
212          */
213         cref = usp->us_cref;
214
215         /*
216          * Make sure it hasn't got too large
217          */
218         if (cref >= UNI_MSG_CALL_REF_DUMMY) {
219                 /* XXX */
220                 log(LOG_ERR, "uni: call reference limit reached\n");
221                 return(0);
222         }
223         
224         /*
225          * Bump the call reference value
226          */
227         usp->us_cref++;
228
229         return(cref);
230 }
231
232
233 /*
234  * Print an ATM address
235  *
236  * Convert an ATM address into an ASCII string suitable for printing.
237  *
238  * Arguments:
239  *      p       pointer to an ATM address
240  *
241  * Returns:
242  *      the address of a string with the ASCII representation of the
243  *      address.  This routine returns the address of a statically-
244  *      allocated buffer, so if repeated calls to this routine are made,
245  *      each call will destroy the result of the previous call.
246  *
247  */
248 char *
249 unisig_addr_print(p)
250         Atm_addr                *p;
251 {
252         int             i;
253         char            *fp, *op, t_buff[16];
254         u_char          *cp;
255         static char     strbuff[256];
256
257         static char     nf_DCC[] = "0xX.XX.X.XXX.XX.XX.XX.XXXXXX.X";
258         static char     nf_ICD[] = "0xX.XX.X.XXX.XX.XX.XX.XXXXXX.X";
259         static char     nf_E164[] = "0xX.XXXXXXXX.XX.XX.XXXXXX.X";
260
261         union {
262                 int     w;
263                 char    c[4];
264         } u1, u2;
265
266         /*
267          * Clear the print buffer
268          */
269         KM_ZERO(strbuff, sizeof(strbuff));
270
271         /*
272          * Select appropriate printing format
273          */
274         switch(p->address_format) {
275         case T_ATM_ENDSYS_ADDR:
276                 /*
277                  * Select format by NSAP type
278                  */
279                 switch(((Atm_addr_nsap *)p->address)->aan_afi) {
280                 default:
281                 case AFI_DCC:
282                         fp = nf_DCC;
283                         break;
284                 case AFI_ICD:
285                         fp = nf_ICD;
286                         break;
287                 case AFI_E164:
288                         fp = nf_E164;
289                         break;
290                 }
291
292                 /*
293                  * Loop through the format string, converting the NSAP
294                  * to ASCII
295                  */
296                 cp = (u_char *) p->address;
297                 op = strbuff;
298                 while (*fp) {
299                         if (*fp == 'X') {
300                                 /*
301                                  * If format character is an 'X', put a
302                                  * two-digit hex representation of the
303                                  * NSAP byte in the output buffer
304                                  */
305                                 snprintf(t_buff, sizeof(t_buff),
306                                         "%x", *cp + 512);
307                                 strcpy(op, &t_buff[strlen(t_buff)-2]);
308                                 op++; op++;
309                                 cp++;
310                         } else {
311                                 /*
312                                  * If format character isn't an 'X',
313                                  * just copy it to the output buffer
314                                  */
315                                 *op = *fp;
316                                 op++;
317                         }
318                         fp++;
319                 }
320
321                 break;
322
323         case T_ATM_E164_ADDR:
324                 /*
325                  * Print the IA5 characters of the E.164 address
326                  */
327                 for(i=0; i<p->address_length; i++) {
328                         snprintf(strbuff + strlen(strbuff),
329                             sizeof(strbuff) - strlen(strbuff), "%c",
330                                 ((Atm_addr_e164 *)p->address)->aae_addr[i]);
331                 }
332                 break;
333
334         case T_ATM_SPANS_ADDR:
335                 /*
336                  * Get address into integers
337                  */
338                 u1.c[0] = ((Atm_addr_spans *)p->address)->aas_addr[0];
339                 u1.c[1] = ((Atm_addr_spans *)p->address)->aas_addr[1];
340                 u1.c[2] = ((Atm_addr_spans *)p->address)->aas_addr[2];
341                 u1.c[3] = ((Atm_addr_spans *)p->address)->aas_addr[3];
342                 u2.c[0] = ((Atm_addr_spans *)p->address)->aas_addr[4];
343                 u2.c[1] = ((Atm_addr_spans *)p->address)->aas_addr[5];
344                 u2.c[2] = ((Atm_addr_spans *)p->address)->aas_addr[6];
345                 u2.c[3] = ((Atm_addr_spans *)p->address)->aas_addr[7];
346
347                 /*
348                  * Print the address as two words xxxxx.yyyyyyyy
349                  */
350                 snprintf(strbuff, sizeof(strbuff), "%x.%x", u1.w, u2.w);
351                 break;
352
353         case T_ATM_ABSENT:
354         default:
355                 strcpy(strbuff, "-");
356         }
357
358         return(strbuff);
359 }
360
361
362 /*
363  * Print the contents of a message buffer chain
364  *
365  * Arguments:
366  *      m       pointer to a buffer
367  *
368  * Returns:
369  *      none
370  *
371  */
372 void
373 unisig_print_mbuf(m)
374         KBuffer         *m;
375 {
376         int i;
377         caddr_t         cp;
378
379         printf("unisig_print_mbuf:\n");
380         while (m) { 
381                 KB_DATASTART(m, cp, caddr_t);
382                 for (i = 0; i < KB_LEN(m); i++) {
383                         if (i == 0)
384                                 printf("   bfr=%p: ", m);
385                         printf("%x ", (u_char)*cp++);
386                 }
387                 printf("<end_bfr>\n");
388                 m = KB_NEXT(m);
389         }
390 }