source: rtems/c/src/exec/libnetworking/net/pppcompress.c @ 0286b9f

4.104.114.84.95
Last change on this file since 0286b9f was 0286b9f, checked in by Joel Sherrill <joel.sherrill@…>, on 01/31/02 at 21:42:11

2001-01-31 Mike Siers <mikes@…>

  • Nice Update of PPPD support which eliminates the requiremetn that drivers be in the termios TASK_DRIVEN mode. Mike did significant testing and reports that it seems to be more stable and handle larger packets better. This patch replaces the termios tasks with more general pppd network driver tasks. The functions pppinput() and pppstart() get called from the interrupt service routine.
  • Makefile.am, configure.ac, net/Makefile.am, net/bpf.h, net/ethernet.h, net/if.c, net/if.h, net/if_arp.h, net/if_dl.h, net/if_ethersubr.c, net/if_llc.h, net/if_loop.c, net/if_ppp.h, net/if_pppvar.h, net/if_types.h, net/netisr.h, net/ppp-comp.h, net/ppp_defs.h, net/pppcompress.h, net/radix.c, net/radix.h, net/raw_cb.c, net/raw_cb.h, net/raw_usrreq.c, net/route.c, net/route.h, net/rtsock.c, pppd/Makefile.am, pppd/README, pppd/STATUS, pppd/auth.c, pppd/cbcp.c, pppd/ccp.c, pppd/ccp.h, pppd/chap.c, pppd/chap.h, pppd/chap_ms.c, pppd/chap_ms.h, pppd/chat.c, pppd/demand.c, pppd/fsm.c, pppd/fsm.h, pppd/ipcp.c, pppd/ipcp.h, pppd/ipxcp.c, pppd/ipxcp.h, pppd/lcp.c, pppd/lcp.h, pppd/magic.c, pppd/magic.h, pppd/options.c, pppd/patchlevel.h, pppd/pathnames.h, pppd/pppd.8, pppd/pppd.h, pppd/rtemsmain.c, pppd/rtemspppd.c, pppd/rtemspppd.h, pppd/sys-rtems.c, pppd/upap.c, pppd/upap.h, pppd/utils.c, pppd/example/README, pppd/example/netconfig.h, wrapup/Makefile.am: Modified.
  • net/bsd-comp.c, net/if_ppp.c, net/ppp-deflate.c, net/ppp.h, net/ppp_tty.c, net/pppcompress.c, net/zlib.c, net/zlib.h: New file.
  • modem/, modem/.cvsignore, modem/Makefile.am, modem/ppp.c, modem/ppp.h, modem/ppp_tty.c, modem/pppcompress.c: Subdirectory removed.
  • Property mode set to 100644
File size: 16.1 KB
Line 
1/*-
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *      @(#)slcompress.c        7.7 (Berkeley) 5/7/91
34 */
35
36/*
37 * Routines to compress and uncompess tcp packets (for transmission
38 * over low speed serial lines.
39 *
40 * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
41 *    - Initial distribution.
42 *
43 *      $Id$
44 */
45 
46#include <sys/types.h>
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/mbuf.h>
50#include <sys/socket.h>
51#include <sys/socketvar.h>
52
53#include <netinet/in.h>
54#include <netinet/in_systm.h>
55#include <netinet/ip.h>
56#include <netinet/tcp.h>
57
58#include <net/pppcompress.h>
59
60#ifndef SL_NO_STATS
61#define INCR(counter) ++comp->counter;
62#else
63#define INCR(counter)
64#endif
65
66#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
67#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
68#ifndef KERNEL
69#define ovbcopy bcopy
70#endif
71
72void
73vj_compress_init(comp, max_state)
74        struct vjcompress *comp;
75        int max_state;
76{
77        register u_int i;
78        register struct cstate *tstate = comp->tstate;
79
80        if ((unsigned) max_state > MAX_STATES - 1)
81                max_state = MAX_STATES - 1;
82        bzero((char *)comp, sizeof(*comp));
83        for (i = max_state; i > 0; --i) {
84                tstate[i].cs_id = i;
85                tstate[i].cs_next = &tstate[i - 1];
86        }
87        tstate[0].cs_next = &tstate[max_state];
88        tstate[0].cs_id = 0;
89        comp->last_cs = &tstate[0];
90        comp->last_recv = 255;
91        comp->last_xmit = 255;
92        comp->flags = SLF_TOSS;
93}
94
95
96/* ENCODE encodes a number that is known to be non-zero.  ENCODEZ
97 * checks for zero (since zero has to be encoded in the long, 3 byte
98 * form).
99 */
100#define ENCODE(n) { \
101        if ((u_short)(n) >= 256) { \
102                *cp++ = 0; \
103                cp[1] = (n); \
104                cp[0] = (n) >> 8; \
105                cp += 2; \
106        } else { \
107                *cp++ = (n); \
108        } \
109}
110#define ENCODEZ(n) { \
111        if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
112                *cp++ = 0; \
113                cp[1] = (n); \
114                cp[0] = (n) >> 8; \
115                cp += 2; \
116        } else { \
117                *cp++ = (n); \
118        } \
119}
120
121#define DECODEL(f) { \
122        if (*cp == 0) {\
123                (f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
124                cp += 3; \
125        } else { \
126                (f) = htonl(ntohl(f) + (u_long)*cp++); \
127        } \
128}
129
130#define DECODES(f) { \
131        if (*cp == 0) {\
132                (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
133                cp += 3; \
134        } else { \
135                (f) = htons(ntohs(f) + (u_long)*cp++); \
136        } \
137}
138
139#define DECODEU(f) { \
140        if (*cp == 0) {\
141                (f) = htons((cp[1] << 8) | cp[2]); \
142                cp += 3; \
143        } else { \
144                (f) = htons((u_long)*cp++); \
145        } \
146}
147
148u_int
149vj_compress_tcp(m, ip, comp, compress_cid)
150        struct mbuf *m;
151        register struct ip *ip;
152        struct vjcompress *comp;
153        int compress_cid;
154{
155        register struct cstate *cs = comp->last_cs->cs_next;
156        register u_int hlen = ip->ip_hl;
157        register struct tcphdr *oth;
158        register struct tcphdr *th;
159        register u_int deltaS, deltaA;
160        register u_int changes = 0;
161        u_char new_seq[16];
162        register u_char *cp = new_seq;
163
164        /*
165         * Bail if this is an IP fragment or if the TCP packet isn't
166         * `compressible' (i.e., ACK isn't set or some other control bit is
167         * set).  (We assume that the caller has already made sure the
168         * packet is IP proto TCP).
169         */
170        if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40)
171                return (TYPE_IP);
172
173        th = (struct tcphdr *)&((int *)ip)[hlen];
174        if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
175                return (TYPE_IP);
176        /*
177         * Packet is compressible -- we're going to send either a
178         * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
179         * to locate (or create) the connection state.  Special case the
180         * most recently used connection since it's most likely to be used
181         * again & we don't have to do any reordering if it's used.
182         */
183        INCR(sls_packets)
184        if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
185            ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
186            *(int *)th != ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl]) {
187                /*
188                 * Wasn't the first -- search for it.
189                 *
190                 * States are kept in a circularly linked list with
191                 * last_cs pointing to the end of the list.  The
192                 * list is kept in lru order by moving a state to the
193                 * head of the list whenever it is referenced.  Since
194                 * the list is short and, empirically, the connection
195                 * we want is almost always near the front, we locate
196                 * states via linear search.  If we don't find a state
197                 * for the datagram, the oldest state is (re-)used.
198                 */
199                register struct cstate *lcs;
200                register struct cstate *lastcs = comp->last_cs;
201
202                do {
203                        lcs = cs; cs = cs->cs_next;
204                        INCR(sls_searches)
205                        if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
206                            && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
207                            && *(int *)th == ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl])
208                                goto found;
209                } while (cs != lastcs);
210
211                /*
212                 * Didn't find it -- re-use oldest cstate.  Send an
213                 * uncompressed packet that tells the other side what
214                 * connection number we're using for this conversation.
215                 * Note that since the state list is circular, the oldest
216                 * state points to the newest and we only need to set
217                 * last_cs to update the lru linkage.
218                 */
219                INCR(sls_misses)
220                comp->last_cs = lcs;
221                hlen += th->th_off;
222                hlen <<= 2;
223                goto uncompressed;
224
225        found:
226                /*
227                 * Found it -- move to the front on the connection list.
228                 */
229                if (cs == lastcs)
230                        comp->last_cs = lcs;
231                else {
232                        lcs->cs_next = cs->cs_next;
233                        cs->cs_next = lastcs->cs_next;
234                        lastcs->cs_next = cs;
235                }
236        }
237
238        /*
239         * Make sure that only what we expect to change changed. The first
240         * line of the `if' checks the IP protocol version, header length &
241         * type of service.  The 2nd line checks the "Don't fragment" bit.
242         * The 3rd line checks the time-to-live and protocol (the protocol
243         * check is unnecessary but costless).  The 4th line checks the TCP
244         * header length.  The 5th line checks IP options, if any.  The 6th
245         * line checks TCP options, if any.  If any of these things are
246         * different between the previous & current datagram, we send the
247         * current datagram `uncompressed'.
248         */
249        oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];
250        deltaS = hlen;
251        hlen += th->th_off;
252        hlen <<= 2;
253
254        if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||
255            ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||
256            ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||
257            th->th_off != oth->th_off ||
258            (deltaS > 5 &&
259             BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
260            (th->th_off > 5 &&
261             BCMP(th + 1, oth + 1, (th->th_off - 5) << 2)))
262                goto uncompressed;
263
264        /*
265         * Figure out which of the changing fields changed.  The
266         * receiver expects changes in the order: urgent, window,
267         * ack, seq (the order minimizes the number of temporaries
268         * needed in this section of code).
269         */
270        if (th->th_flags & TH_URG) {
271                deltaS = ntohs(th->th_urp);
272                ENCODEZ(deltaS);
273                changes |= NEW_U;
274        } else if (th->th_urp != oth->th_urp)
275                /* argh! URG not set but urp changed -- a sensible
276                 * implementation should never do this but RFC793
277                 * doesn't prohibit the change so we have to deal
278                 * with it. */
279                 goto uncompressed;
280
281        if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win)))) {
282                ENCODE(deltaS);
283                changes |= NEW_W;
284        }
285
286        if ((deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack))) {
287                if (deltaA > 0xffff)
288                        goto uncompressed;
289                ENCODE(deltaA);
290                changes |= NEW_A;
291        }
292
293        if ((deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq))) {
294                if (deltaS > 0xffff)
295                        goto uncompressed;
296                ENCODE(deltaS);
297                changes |= NEW_S;
298        }
299
300        switch(changes) {
301
302        case 0:
303                /*
304                 * Nothing changed. If this packet contains data and the
305                 * last one didn't, this is probably a data packet following
306                 * an ack (normal on an interactive connection) and we send
307                 * it compressed.  Otherwise it's probably a retransmit,
308                 * retransmitted ack or window probe.  Send it uncompressed
309                 * in case the other side missed the compressed version.
310                 */
311                if (ip->ip_len != cs->cs_ip.ip_len &&
312                    ntohs(cs->cs_ip.ip_len) == hlen)
313                        break;
314
315                /* (fall through) */
316
317        case SPECIAL_I:
318        case SPECIAL_D:
319                /*
320                 * actual changes match one of our special case encodings --
321                 * send packet uncompressed.
322                 */
323                goto uncompressed;
324
325        case NEW_S|NEW_A:
326                if (deltaS == deltaA &&
327                    deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
328                        /* special case for echoed terminal traffic */
329                        changes = SPECIAL_I;
330                        cp = new_seq;
331                }
332                break;
333
334        case NEW_S:
335                if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
336                        /* special case for data xfer */
337                        changes = SPECIAL_D;
338                        cp = new_seq;
339                }
340                break;
341        }
342
343        deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
344        if (deltaS != 1) {
345                ENCODEZ(deltaS);
346                changes |= NEW_I;
347        }
348        if (th->th_flags & TH_PUSH)
349                changes |= TCP_PUSH_BIT;
350        /*
351         * Grab the cksum before we overwrite it below.  Then update our
352         * state with this packet's header.
353         */
354        deltaA = ntohs(th->th_sum);
355        BCOPY(ip, &cs->cs_ip, hlen);
356
357        /*
358         * We want to use the original packet as our compressed packet.
359         * (cp - new_seq) is the number of bytes we need for compressed
360         * sequence numbers.  In addition we need one byte for the change
361         * mask, one for the connection id and two for the tcp checksum.
362         * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
363         * many bytes of the original packet to toss so subtract the two to
364         * get the new packet size.
365         */
366        deltaS = cp - new_seq;
367        cp = (u_char *)ip;
368        if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
369                comp->last_xmit = cs->cs_id;
370                hlen -= deltaS + 4;
371                cp += hlen;
372                *cp++ = changes | NEW_C;
373                *cp++ = cs->cs_id;
374        } else {
375                hlen -= deltaS + 3;
376                cp += hlen;
377                *cp++ = changes;
378        }
379        m->m_len -= hlen;
380        m->m_data += hlen;
381        *cp++ = deltaA >> 8;
382        *cp++ = deltaA;
383        BCOPY(new_seq, cp, deltaS);
384        INCR(sls_compressed)
385        return (TYPE_COMPRESSED_TCP);
386
387        /*
388         * Update connection state cs & send uncompressed packet ('uncompressed'
389         * means a regular ip/tcp packet but with the 'conversation id' we hope
390         * to use on future compressed packets in the protocol field).
391         */
392uncompressed:
393        BCOPY(ip, &cs->cs_ip, hlen);
394        ip->ip_p = cs->cs_id;
395        comp->last_xmit = cs->cs_id;
396        return (TYPE_UNCOMPRESSED_TCP);
397}
398
399
400int
401vj_uncompress_tcp(bufp, len, type, comp)
402        u_char **bufp;
403        int len;
404        u_int type;
405        struct vjcompress *comp;
406{
407        u_char *hdr, *cp;
408        int hlen, vjlen;
409
410        cp = bufp? *bufp: NULL;
411        vjlen = vj_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen);
412        if (vjlen < 0)
413                return (0);     /* error */
414        if (vjlen == 0)
415                return (len);   /* was uncompressed already */
416
417        cp += vjlen;
418        len -= vjlen;
419
420        /*
421         * At this point, cp points to the first byte of data in the
422         * packet.  If we're not aligned on a 4-byte boundary, copy the
423         * data down so the ip & tcp headers will be aligned.  Then back up
424         * cp by the tcp/ip header length to make room for the reconstructed
425         * header (we assume the packet we were handed has enough space to
426         * prepend 128 bytes of header).
427         */
428        if ((int)cp & 3) {
429                if (len > 0)
430                        (void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), len);
431                cp = (u_char *)((int)cp &~ 3);
432        }
433        cp -= hlen;
434        len += hlen;
435        BCOPY(hdr, cp, hlen);
436
437        *bufp = cp;
438        return (len);
439}
440
441/*
442 * Uncompress a packet of total length total_len.  The first buflen
443 * bytes are at buf; this must include the entire (compressed or
444 * uncompressed) TCP/IP header.  This procedure returns the length
445 * of the VJ header, with a pointer to the uncompressed IP header
446 * in *hdrp and its length in *hlenp.
447 */
448int
449vj_uncompress_tcp_core(buf, buflen, total_len, type, comp, hdrp, hlenp)
450        u_char *buf;
451        int buflen, total_len;
452        u_int type;
453        struct vjcompress *comp;
454        u_char **hdrp;
455        u_int *hlenp;
456{
457        register u_char *cp;
458        register u_int hlen, changes;
459        register struct tcphdr *th;
460        register struct cstate *cs;
461        register struct ip *ip;
462        register u_short *bp;
463        register u_int vjlen;
464
465        switch (type) {
466
467        case TYPE_UNCOMPRESSED_TCP:
468                ip = (struct ip *) buf;
469                if (ip->ip_p >= MAX_STATES)
470                        goto bad;
471                cs = &comp->rstate[comp->last_recv = ip->ip_p];
472                comp->flags &=~ SLF_TOSS;
473                ip->ip_p = IPPROTO_TCP;
474                /*
475                 * Calculate the size of the TCP/IP header and make sure that
476                 * we don't overflow the space we have available for it.
477                 */
478                hlen = ip->ip_hl << 2;
479                if (hlen + sizeof(struct tcphdr) > buflen)
480                        goto bad;
481                hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2;
482                if (hlen > MAX_HDR || hlen > buflen)
483                        goto bad;
484                BCOPY(ip, &cs->cs_ip, hlen);
485                cs->cs_hlen = hlen;
486                INCR(sls_uncompressedin)
487                *hdrp = (u_char *) &cs->cs_ip;
488                *hlenp = hlen;
489                return (0);
490
491        default:
492                goto bad;
493
494        case TYPE_COMPRESSED_TCP:
495                break;
496        }
497        /* We've got a compressed packet. */
498        INCR(sls_compressedin)
499        cp = buf;
500        changes = *cp++;
501        if (changes & NEW_C) {
502                /* Make sure the state index is in range, then grab the state.
503                 * If we have a good state index, clear the 'discard' flag. */
504                if (*cp >= MAX_STATES)
505                        goto bad;
506
507                comp->flags &=~ SLF_TOSS;
508                comp->last_recv = *cp++;
509        } else {
510                /* this packet has an implicit state index.  If we've
511                 * had a line error since the last time we got an
512                 * explicit state index, we have to toss the packet. */
513                if (comp->flags & SLF_TOSS) {
514                        INCR(sls_tossed)
515                        return (-1);
516                }
517        }
518        cs = &comp->rstate[comp->last_recv];
519        hlen = cs->cs_ip.ip_hl << 2;
520        th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
521        th->th_sum = htons((*cp << 8) | cp[1]);
522        cp += 2;
523        if (changes & TCP_PUSH_BIT)
524                th->th_flags |= TH_PUSH;
525        else
526                th->th_flags &=~ TH_PUSH;
527
528        switch (changes & SPECIALS_MASK) {
529        case SPECIAL_I:
530                {
531                register u_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
532                th->th_ack = htonl(ntohl(th->th_ack) + i);
533                th->th_seq = htonl(ntohl(th->th_seq) + i);
534                }
535                break;
536
537        case SPECIAL_D:
538                th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
539                                   - cs->cs_hlen);
540                break;
541
542        default:
543                if (changes & NEW_U) {
544                        th->th_flags |= TH_URG;
545                        DECODEU(th->th_urp)
546                } else
547                        th->th_flags &=~ TH_URG;
548                if (changes & NEW_W)
549                        DECODES(th->th_win)
550                if (changes & NEW_A)
551                        DECODEL(th->th_ack)
552                if (changes & NEW_S)
553                        DECODEL(th->th_seq)
554                break;
555        }
556        if (changes & NEW_I) {
557                DECODES(cs->cs_ip.ip_id)
558        } else
559                cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
560
561        /*
562         * At this point, cp points to the first byte of data in the
563         * packet.  Fill in the IP total length and update the IP
564         * header checksum.
565         */
566        vjlen = cp - buf;
567        buflen -= vjlen;
568        if (buflen < 0)
569                /* we must have dropped some characters (crc should detect
570                 * this but the old slip framing won't) */
571                goto bad;
572
573        total_len += cs->cs_hlen - vjlen;
574        cs->cs_ip.ip_len = htons(total_len);
575
576        /* recompute the ip header checksum */
577        bp = (u_short *) &cs->cs_ip;
578        cs->cs_ip.ip_sum = 0;
579        for (changes = 0; hlen > 0; hlen -= 2)
580                changes += *bp++;
581        changes = (changes & 0xffff) + (changes >> 16);
582        changes = (changes & 0xffff) + (changes >> 16);
583        cs->cs_ip.ip_sum = ~ changes;
584
585        *hdrp = (u_char *) &cs->cs_ip;
586        *hlenp = cs->cs_hlen;
587        return vjlen;
588
589bad:
590        comp->flags |= SLF_TOSS;
591        INCR(sls_errorin)
592        return (-1);
593}
Note: See TracBrowser for help on using the repository browser.