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