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