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