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