slcompress.c 16 KB

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