]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/netatm/uni/unisig_mbuf.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / sys / netatm / uni / unisig_mbuf.c
1 /*-
2  * ===================================
3  * HARP  |  Host ATM Research Platform
4  * ===================================
5  *
6  *
7  * This Host ATM Research Platform ("HARP") file (the "Software") is
8  * made available by Network Computing Services, Inc. ("NetworkCS")
9  * "AS IS".  NetworkCS does not provide maintenance, improvements or
10  * support of any kind.
11  *
12  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16  * In no event shall NetworkCS be responsible for any damages, including
17  * but not limited to consequential damages, arising from or relating to
18  * any use of the Software or related support.
19  *
20  * Copyright 1994-1998 Network Computing Services, Inc.
21  *
22  * Copies of this Software may be made, however, the above copyright
23  * notice must be reproduced on all copies.
24  */
25
26 /*
27  * ATM Forum UNI 3.0/3.1 Signalling Manager
28  * ----------------------------------------
29  *
30  * Message buffer handling routines
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/systm.h>
39 #include <sys/errno.h>
40 #include <sys/time.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <net/if.h>
44 #include <netatm/port.h>
45 #include <netatm/queue.h>
46 #include <netatm/atm.h>
47 #include <netatm/atm_sys.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_cm.h>
50 #include <netatm/atm_if.h>
51 #include <netatm/atm_vc.h>
52 #include <netatm/atm_sigmgr.h>
53 #include <netatm/atm_stack.h>
54 #include <netatm/atm_pcb.h>
55 #include <netatm/atm_var.h>
56
57 #include <netatm/uni/unisig_var.h>
58 #include <netatm/uni/unisig_mbuf.h>
59 #include <netatm/uni/unisig_msg.h>
60
61 /*
62  * Initialize a unisig formatting structure
63  *
64  * Arguments:
65  *      usf     pointer to a unisig formatting structure
66  *      usp     pointer to a unisig protocol instance
67  *      buf     pointer to a buffer chain (decode only)
68  *      op      operation code (encode or decode)
69  *      headroom headroom to leave in first buffer
70  *
71  * Returns:
72  *      0       success
73  *      errno   error encountered
74  *
75  */
76 int
77 usf_init(usf, usp, buf, op, headroom)
78         struct usfmt    *usf;
79         struct unisig   *usp;
80         KBuffer         *buf;
81         int             op;
82         int             headroom;
83 {
84         KBuffer         *m;
85
86         ATM_DEBUG3("usf_init: usf=%p, buf=%p, op=%d\n",
87                         usf, buf, op);
88
89         /*
90          * Check parameters
91          */
92         if (!usf)
93                 return(EINVAL);
94
95         switch(op) {
96
97         case USF_ENCODE:
98                 /*
99                  * Get a buffer
100                  */
101                 KB_ALLOCPKT(m, USF_MIN_ALLOC, KB_F_NOWAIT, KB_T_DATA);
102                 if (m == NULL)
103                         return(ENOMEM);
104                 KB_LEN(m) = 0;
105                 if (headroom < KB_BFRLEN(m)) {
106                         KB_HEADSET(m, headroom);
107                 }
108                 break;
109
110         case USF_DECODE:
111                 /*
112                  * Verify buffer address
113                  */
114                 if (!buf)
115                         return(EINVAL);
116                 m = buf;
117                 break;
118
119         default:
120                 return(EINVAL);
121         }
122
123         /*
124          * Save parameters in formatting structure
125          */
126         usf->usf_m_addr = m;
127         usf->usf_m_base = m;
128         usf->usf_loc = 0;
129         usf->usf_op = op;
130         usf->usf_sig = usp;
131
132         return(0);
133 }
134
135
136 /*
137  * Get or put the next byte of a signalling message
138  *
139  * Arguments:
140  *      usf     pointer to a unisig formatting structure
141  *      c       pointer to the byte to send from or receive into
142  *
143  * Returns:
144  *      0       success
145  *      errno   error encountered
146  *
147  */
148 int
149 usf_byte(usf, c)
150         struct usfmt    *usf;
151         u_char          *c;
152 {
153         u_char          *mp;
154         KBuffer         *m = usf->usf_m_addr, *m1;
155         int             space;
156
157         switch (usf->usf_op) {
158
159         case USF_DECODE:
160                 /*
161                  * Make sure we're not past the end of the buffer
162                  * (allowing for zero-length buffers)
163                  */
164                 while (usf->usf_loc >= KB_LEN(m)) {
165                         if (KB_NEXT(usf->usf_m_addr)) {
166                                 usf->usf_m_addr = m = KB_NEXT(usf->usf_m_addr);
167                                 usf->usf_loc = 0;
168                         } else {
169                                 return(EMSGSIZE);
170                         }
171                 }
172
173                 /*
174                  * Get the data from the buffer
175                  */
176                 KB_DATASTART(m, mp, u_char *);
177                 *c = mp[usf->usf_loc];
178                 usf->usf_loc++;
179                 break;
180
181         case USF_ENCODE:
182                 /*
183                  * If the current buffer is full, get another
184                  */
185                 KB_TAILROOM(m, space);
186                 if (space == 0) {
187                         KB_ALLOC(m1, USF_MIN_ALLOC, KB_F_NOWAIT, KB_T_DATA);
188                         if (m1 == NULL)
189                                 return(ENOMEM);
190                         KB_LEN(m1) = 0;
191                         KB_LINK(m1, m);
192                         usf->usf_m_addr = m = m1;
193                         usf->usf_loc = 0;
194                 }
195
196                 /*
197                  * Put the data into the buffer
198                  */
199                 KB_DATASTART(m, mp, u_char *);
200                 mp[usf->usf_loc] = *c;
201                 KB_TAILADJ(m, 1);
202                 usf->usf_loc++;
203                 break;
204
205         default:
206                 /*
207                  * Invalid operation code
208                  */
209                 return(EINVAL);
210         }
211
212         return(0);
213
214 }
215
216 /*
217  * Get or put a short integer
218  *
219  * Arguments:
220  *      usf     pointer to a unisig formatting structure
221  *      s       pointer to a short to send from or receive into
222  *
223  * Returns:
224  *      0       success
225  *      errno   error encountered
226  *
227  */
228 int
229 usf_short(usf, s)
230         struct usfmt    *usf;
231         u_short         *s;
232
233 {
234         int     rc;
235         union {
236                 u_short value;
237                 u_char  b[sizeof(u_short)];
238         } tval;
239
240         tval.value = 0;
241         if (usf->usf_op == USF_ENCODE)
242                 tval.value = htons(*s);
243
244         if ((rc = usf_byte(usf, &tval.b[0])) != 0)
245                 return(rc);
246         if ((rc = usf_byte(usf, &tval.b[1])) != 0)
247                 return(rc);
248
249         if (usf->usf_op == USF_DECODE)
250                 *s = ntohs(tval.value);
251
252         return(0);
253 }
254
255
256 /*
257  * Get or put a 3-byte integer
258  *
259  * Arguments:
260  *      usf     pointer to a unisig formatting structure
261  *      i       pointer to an integer to send from or receive into
262  *
263  * Returns:
264  *      0       success
265  *      errno   error encountered
266  *
267  */
268 int
269 usf_int3(usf, i)
270         struct usfmt    *usf;
271         u_int           *i;
272
273 {
274         int     j, rc;
275         union {
276                 u_int   value;
277                 u_char  b[sizeof(u_int)];
278         } tval;
279
280         tval.value = 0;
281
282         if (usf->usf_op == USF_ENCODE)
283                 tval.value = htonl(*i);
284
285         for (j=0; j<3; j++) {
286                 rc = usf_byte(usf, &tval.b[j+sizeof(u_int)-3]);
287                 if (rc)
288                         return(rc);
289         }
290
291         if (usf->usf_op == USF_DECODE)
292                 *i = ntohl(tval.value);
293
294         return(rc);
295 }
296
297
298 /*
299  * Get or put an integer
300  *
301  * Arguments:
302  *      usf     pointer to a unisig formatting structure
303  *      i       pointer to an integer to send from or receive into
304  *
305  * Returns:
306  *      0       success
307  *      errno   error encountered
308  *
309  */
310 int
311 usf_int(usf, i)
312         struct usfmt    *usf;
313         u_int           *i;
314
315 {
316         int     j, rc;
317         union {
318                 u_int   value;
319                 u_char  b[sizeof(u_int)];
320         } tval;
321
322         if (usf->usf_op == USF_ENCODE)
323                 tval.value = htonl(*i);
324
325         for (j=0; j<4; j++) {
326                 rc = usf_byte(usf, &tval.b[j+sizeof(u_int)-4]);
327                 if (rc)
328                         return(rc);
329         }
330
331         if (usf->usf_op == USF_DECODE)
332                 *i = ntohl(tval.value);
333
334         return(rc);
335 }
336
337
338 /*
339  * Get or put an extented field
340  *
341  * An extented field consists of a string of bytes.  All but the last
342  * byte of the field has the high-order bit set to zero.  When decoding,
343  * this routine will read bytes until either the input is exhausted or
344  * a byte with a high-order one is found.  Whe encoding, it will take an
345  * unsigned integer and write until the highest-order one bit has been
346  * written.
347  *
348  * Arguments:
349  *      usf     pointer to a unisig formatting structure
350  *      i       pointer to an integer to send from or receive into
351  *
352  * Returns:
353  *      0       success
354  *      errno   error encountered
355  *
356  */
357 int
358 usf_ext(usf, i)
359         struct usfmt    *usf;
360         u_int           *i;
361
362 {
363         int     j, rc;
364         u_char  c, buff[sizeof(u_int)+1];
365         u_int   val;
366         union {
367                 u_int   value;
368                 u_char  b[sizeof(u_int)];
369         } tval;
370
371         switch(usf->usf_op) {
372
373         case USF_ENCODE:
374                 val = *i;
375                 j = 0;
376                 while (val) {
377                         tval.value = htonl(val);
378                         buff[j] = tval.b[sizeof(u_int)-1] & UNI_IE_EXT_MASK;
379                         val >>= 7;
380                         j++;
381                 }
382                 j--;
383                 buff[0] |= UNI_IE_EXT_BIT;
384                 for (; j>=0; j--) {
385                         rc = usf_byte(usf, &buff[j]);
386                         if (rc)
387                                 return(rc);
388                 }
389                 break;
390
391         case USF_DECODE:
392                 c = 0;
393                 val = 0;
394                 while (!(c & UNI_IE_EXT_BIT)) {
395                         rc = usf_byte(usf, &c);
396                         if (rc)
397                                 return(rc);
398                         val = (val << 7) + (c & UNI_IE_EXT_MASK);
399                 }
400                 *i = val;
401                 break;
402
403         default:
404                 return(EINVAL);
405         }
406
407         return(0);
408 }
409
410
411 /*
412  * Count the bytes remaining to be decoded
413  *
414  * Arguments:
415  *      usf     pointer to a unisig formatting structure
416  *
417  * Returns:
418  *      int     the number of bytes in the buffer chain remaining to
419  *              be decoded
420  *
421  */
422 int
423 usf_count(usf)
424         struct usfmt    *usf;
425 {
426         int             count;
427         KBuffer         *m = usf->usf_m_addr;
428
429         /*
430          * Return zero if we're not decoding
431          */
432         if (usf->usf_op != USF_DECODE)
433                 return (0);
434
435         /*
436          * Calculate the length of data remaining in the current buffer
437          */
438         count = KB_LEN(m) - usf->usf_loc;
439
440         /*
441          * Loop through any remaining buffers, adding in their lengths
442          */
443         while (KB_NEXT(m)) {
444                 m = KB_NEXT(m);
445                 count += KB_LEN(m);
446         }
447
448         return(count);
449
450 }
451
452
453 /*
454  * Get or put the next byte of a signalling message and return
455  * the byte's buffer address 
456  *
457  * Arguments:
458  *      usf     pointer to a unisig formatting structure
459  *      c       pointer to the byte to send from or receive into
460  *      bp      address to store the byte's buffer address
461  *
462  * Returns:
463  *      0       success
464  *      errno   error encountered
465  *
466  */
467 int
468 usf_byte_mark(usf, c, bp)
469         struct usfmt    *usf;
470         u_char          *c;
471         u_char          **bp;
472 {
473         u_char          *mp;
474         int             rc;
475
476         /*
477          * First, get/put the data byte
478          */
479         rc = usf_byte(usf, c);
480         if (rc) {
481
482                 /*
483                  * Error encountered
484                  */
485                 *bp = NULL;
486                 return (rc);
487         }
488
489         /*
490          * Now return the buffer address of that byte
491          */
492         KB_DATASTART(usf->usf_m_addr, mp, u_char *);
493         *bp = &mp[usf->usf_loc - 1];
494
495         return (0);
496 }
497