kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / unisig_mbuf.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_mbuf.c,v 1.5 1999/08/28 00:49:05 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_mbuf.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  * Message buffer handling routines
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include "unisig_var.h"
41 #include "unisig_mbuf.h"
42 #include "unisig_msg.h"
43
44 /*
45  * Initialize a unisig formatting structure
46  *
47  * Arguments:
48  *      usf     pointer to a unisig formatting structure
49  *      usp     pointer to a unisig protocol instance
50  *      buf     pointer to a buffer chain (decode only)
51  *      op      operation code (encode or decode)
52  *      headroom headroom to leave in first buffer
53  *
54  * Returns:
55  *      0       success
56  *      errno   error encountered
57  *
58  */
59 int
60 usf_init(usf, usp, buf, op, headroom)
61         struct usfmt    *usf;
62         struct unisig   *usp;
63         KBuffer         *buf;
64         int             op;
65         int             headroom;
66 {
67         KBuffer         *m;
68
69         ATM_DEBUG3("usf_init: usf=%p, buf=%p, op=%d\n",
70                         usf, buf, op);
71
72         /*
73          * Check parameters
74          */
75         if (!usf)
76                 return(EINVAL);
77
78         switch(op) {
79
80         case USF_ENCODE:
81                 /*
82                  * Get a buffer
83                  */
84                 KB_ALLOCPKT(m, USF_MIN_ALLOC, KB_F_NOWAIT, KB_T_DATA);
85                 if (m == NULL)
86                         return(ENOMEM);
87                 KB_LEN(m) = 0;
88                 if (headroom < KB_BFRLEN(m)) {
89                         KB_HEADSET(m, headroom);
90                 }
91                 break;
92
93         case USF_DECODE:
94                 /*
95                  * Verify buffer address
96                  */
97                 if (!buf)
98                         return(EINVAL);
99                 m = buf;
100                 break;
101
102         default:
103                 return(EINVAL);
104         }
105
106         /*
107          * Save parameters in formatting structure
108          */
109         usf->usf_m_addr = m;
110         usf->usf_m_base = m;
111         usf->usf_loc = 0;
112         usf->usf_op = op;
113         usf->usf_sig = usp;
114
115         return(0);
116 }
117
118
119 /*
120  * Get or put the next byte of a signalling message
121  *
122  * Arguments:
123  *      usf     pointer to a unisig formatting structure
124  *      c       pointer to the byte to send from or receive into
125  *
126  * Returns:
127  *      0       success
128  *      errno   error encountered
129  *
130  */
131 int
132 usf_byte(usf, c)
133         struct usfmt    *usf;
134         u_char          *c;
135 {
136         u_char          *mp;
137         KBuffer         *m = usf->usf_m_addr, *m1;
138         int             space;
139
140         switch (usf->usf_op) {
141
142         case USF_DECODE:
143                 /*
144                  * Make sure we're not past the end of the buffer
145                  * (allowing for zero-length buffers)
146                  */
147                 while (usf->usf_loc >= KB_LEN(m)) {
148                         if (KB_NEXT(usf->usf_m_addr)) {
149                                 usf->usf_m_addr = m = KB_NEXT(usf->usf_m_addr);
150                                 usf->usf_loc = 0;
151                         } else {
152                                 return(EMSGSIZE);
153                         }
154                 }
155
156                 /*
157                  * Get the data from the buffer
158                  */
159                 KB_DATASTART(m, mp, u_char *);
160                 *c = mp[usf->usf_loc];
161                 usf->usf_loc++;
162                 break;
163
164         case USF_ENCODE:
165                 /*
166                  * If the current buffer is full, get another
167                  */
168                 KB_TAILROOM(m, space);
169                 if (space == 0) {
170                         KB_ALLOC(m1, USF_MIN_ALLOC, KB_F_NOWAIT, KB_T_DATA);
171                         if (m1 == NULL)
172                                 return(ENOMEM);
173                         KB_LEN(m1) = 0;
174                         KB_LINK(m1, m);
175                         usf->usf_m_addr = m = m1;
176                         usf->usf_loc = 0;
177                 }
178
179                 /*
180                  * Put the data into the buffer
181                  */
182                 KB_DATASTART(m, mp, u_char *);
183                 mp[usf->usf_loc] = *c;
184                 KB_TAILADJ(m, 1);
185                 usf->usf_loc++;
186                 break;
187
188         default:
189                 /*
190                  * Invalid operation code
191                  */
192                 return(EINVAL);
193         }
194
195         return(0);
196
197 }
198
199 /*
200  * Get or put a short integer
201  *
202  * Arguments:
203  *      usf     pointer to a unisig formatting structure
204  *      s       pointer to a short to send from or receive into
205  *
206  * Returns:
207  *      0       success
208  *      errno   error encountered
209  *
210  */
211 int
212 usf_short(usf, s)
213         struct usfmt    *usf;
214         u_short         *s;
215
216 {
217         int     rc;
218         union {
219                 u_short value;
220                 u_char  b[sizeof(u_short)];
221         } tval;
222
223         tval.value = 0;
224         if (usf->usf_op == USF_ENCODE)
225                 tval.value = htons(*s);
226
227         if ((rc = usf_byte(usf, &tval.b[0])) != 0)
228                 return(rc);
229         if ((rc = usf_byte(usf, &tval.b[1])) != 0)
230                 return(rc);
231
232         if (usf->usf_op == USF_DECODE)
233                 *s = ntohs(tval.value);
234
235         return(0);
236 }
237
238
239 /*
240  * Get or put a 3-byte integer
241  *
242  * Arguments:
243  *      usf     pointer to a unisig formatting structure
244  *      i       pointer to an integer to send from or receive into
245  *
246  * Returns:
247  *      0       success
248  *      errno   error encountered
249  *
250  */
251 int
252 usf_int3(usf, i)
253         struct usfmt    *usf;
254         u_int           *i;
255
256 {
257         int     j, rc;
258         union {
259                 u_int   value;
260                 u_char  b[sizeof(u_int)];
261         } tval;
262
263         tval.value = 0;
264
265         if (usf->usf_op == USF_ENCODE)
266                 tval.value = htonl(*i);
267
268         for (j=0; j<3; j++) {
269                 rc = usf_byte(usf, &tval.b[j+sizeof(u_int)-3]);
270                 if (rc)
271                         return(rc);
272         }
273
274         if (usf->usf_op == USF_DECODE)
275                 *i = ntohl(tval.value);
276
277         return(rc);
278 }
279
280
281 /*
282  * Get or put an integer
283  *
284  * Arguments:
285  *      usf     pointer to a unisig formatting structure
286  *      i       pointer to an integer to send from or receive into
287  *
288  * Returns:
289  *      0       success
290  *      errno   error encountered
291  *
292  */
293 int
294 usf_int(usf, i)
295         struct usfmt    *usf;
296         u_int           *i;
297
298 {
299         int     j, rc;
300         union {
301                 u_int   value;
302                 u_char  b[sizeof(u_int)];
303         } tval;
304
305         if (usf->usf_op == USF_ENCODE)
306                 tval.value = htonl(*i);
307
308         for (j=0; j<4; j++) {
309                 rc = usf_byte(usf, &tval.b[j+sizeof(u_int)-4]);
310                 if (rc)
311                         return(rc);
312         }
313
314         if (usf->usf_op == USF_DECODE)
315                 *i = ntohl(tval.value);
316
317         return(rc);
318 }
319
320
321 /*
322  * Get or put an extented field
323  *
324  * An extented field consists of a string of bytes.  All but the last
325  * byte of the field has the high-order bit set to zero.  When decoding,
326  * this routine will read bytes until either the input is exhausted or
327  * a byte with a high-order one is found.  Whe encoding, it will take an
328  * unsigned integer and write until the highest-order one bit has been
329  * written.
330  *
331  * Arguments:
332  *      usf     pointer to a unisig formatting structure
333  *      i       pointer to an integer to send from or receive into
334  *
335  * Returns:
336  *      0       success
337  *      errno   error encountered
338  *
339  */
340 int
341 usf_ext(usf, i)
342         struct usfmt    *usf;
343         u_int           *i;
344
345 {
346         int     j, rc;
347         u_char  c, buff[sizeof(u_int)+1];
348         u_int   val;
349         union {
350                 u_int   value;
351                 u_char  b[sizeof(u_int)];
352         } tval;
353
354         switch(usf->usf_op) {
355
356         case USF_ENCODE:
357                 val = *i;
358                 j = 0;
359                 while (val) {
360                         tval.value = htonl(val);
361                         buff[j] = tval.b[sizeof(u_int)-1] & UNI_IE_EXT_MASK;
362                         val >>= 7;
363                         j++;
364                 }
365                 j--;
366                 buff[0] |= UNI_IE_EXT_BIT;
367                 for (; j>=0; j--) {
368                         rc = usf_byte(usf, &buff[j]);
369                         if (rc)
370                                 return(rc);
371                 }
372                 break;
373
374         case USF_DECODE:
375                 c = 0;
376                 val = 0;
377                 while (!(c & UNI_IE_EXT_BIT)) {
378                         rc = usf_byte(usf, &c);
379                         if (rc)
380                                 return(rc);
381                         val = (val << 7) + (c & UNI_IE_EXT_MASK);
382                 }
383                 *i = val;
384                 break;
385
386         default:
387                 return(EINVAL);
388         }
389
390         return(0);
391 }
392
393
394 /*
395  * Count the bytes remaining to be decoded
396  *
397  * Arguments:
398  *      usf     pointer to a unisig formatting structure
399  *
400  * Returns:
401  *      int     the number of bytes in the buffer chain remaining to
402  *              be decoded
403  *
404  */
405 int
406 usf_count(usf)
407         struct usfmt    *usf;
408 {
409         int             count;
410         KBuffer         *m = usf->usf_m_addr;
411
412         /*
413          * Return zero if we're not decoding
414          */
415         if (usf->usf_op != USF_DECODE)
416                 return (0);
417
418         /*
419          * Calculate the length of data remaining in the current buffer
420          */
421         count = KB_LEN(m) - usf->usf_loc;
422
423         /*
424          * Loop through any remaining buffers, adding in their lengths
425          */
426         while (KB_NEXT(m)) {
427                 m = KB_NEXT(m);
428                 count += KB_LEN(m);
429         }
430
431         return(count);
432
433 }
434
435
436 /*
437  * Get or put the next byte of a signalling message and return
438  * the byte's buffer address 
439  *
440  * Arguments:
441  *      usf     pointer to a unisig formatting structure
442  *      c       pointer to the byte to send from or receive into
443  *      bp      address to store the byte's buffer address
444  *
445  * Returns:
446  *      0       success
447  *      errno   error encountered
448  *
449  */
450 int
451 usf_byte_mark(usf, c, bp)
452         struct usfmt    *usf;
453         u_char          *c;
454         u_char          **bp;
455 {
456         u_char          *mp;
457         int             rc;
458
459         /*
460          * First, get/put the data byte
461          */
462         rc = usf_byte(usf, c);
463         if (rc) {
464
465                 /*
466                  * Error encountered
467                  */
468                 *bp = NULL;
469                 return (rc);
470         }
471
472         /*
473          * Now return the buffer address of that byte
474          */
475         KB_DATASTART(usf->usf_m_addr, mp, u_char *);
476         *bp = &mp[usf->usf_loc - 1];
477
478         return (0);
479 }
480