There's no need to allocate and fill in an array of sub-authorities and
[obnox/wireshark/wip.git] / packet-vj.c
1 /* packet-vj.c
2  * Routines for Van Jacobson header decompression. 
3  *
4  * $Id: packet-vj.c,v 1.7 2002/04/14 23:22:22 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  *
9  * This file created by Irfan Khan <ikhan@qualcomm.com>
10  * Copyright (c) 2001  by QUALCOMM, Incorporated.
11  * All Rights reserved.
12  * 
13  * Routines to compress and uncompress tcp packets (for transmission
14  * over low speed serial lines).
15  *
16  * Copyright (c) 1989 Regents of the University of California.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that the above copyright notice and this paragraph are
21  * duplicated in all such forms and that any documentation,
22  * advertising materials, and other materials related to such
23  * distribution and use acknowledge that the software was developed
24  * by the University of California, Berkeley.  The name of the
25  * University may not be used to endorse or promote products derived
26  * from this software without specific prior written permission.
27  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
28  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
29  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  *      Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
32  *      - Initial distribution.
33  *
34  *
35  * modified for KA9Q Internet Software Package by
36  * Katie Stevens (dkstevens@ucdavis.edu)
37  * University of California, Davis
38  * Computing Services
39  *      - 01-31-90      initial adaptation (from 1.19)
40  *      PPP.05  02-15-90 [ks]
41  *      PPP.08  05-02-90 [ks]   use PPP protocol field to signal compression
42  *      PPP.15  09-90    [ks]   improve mbuf handling
43  *      PPP.16  11-02    [karn] substantially rewritten to use NOS facilities
44  *
45  *      - Feb 1991      Bill_Simpson@um.cc.umich.edu
46  *                      variable number of conversation slots
47  *                      allow zero or one slots
48  *                      separate routines
49  *                      status display
50  *      - Jul 1994      Dmitry Gorodchanin
51  *                      Fixes for memory leaks.
52  *      - Oct 1994      Dmitry Gorodchanin
53  *                      Modularization.
54  *      - Jan 1995      Bjorn Ekwall
55  *                      Use ip_fast_csum from ip.h
56  *      - July 1995     Christos A. Polyzols
57  *                      Spotted bug in tcp option checking
58  *      - Sep 2001      Irfan Khan 
59  *                      Rewrite to make the code work for ethereal.
60  */
61
62 #ifdef HAVE_CONFIG_H
63 # include "config.h"
64 #endif
65
66 #ifdef HAVE_SYS_TYPES_H
67 # include <sys/types.h>
68 #endif
69
70 #include <glib.h>
71 #include <string.h>
72 #include <epan/packet.h>
73 #include "packet-ppp.h"
74 #include "ppptypes.h"
75 #include "in_cksum.h"
76 #include "epan/tvbuff.h"
77
78 /* Define relevant IP/TCP parameters */
79 #define IP_FIELD_SRC         12 /* Byte 12 in IP hdr - src address        */
80 #define IP_FIELD_DST         16 /* Byte 16 in IP hdr - dst address        */
81 #define IP_ADDR_SIZE          4 /* Size in bytes of IPv4 address          */
82 #define IP_FIELD_PROTOCOL     9 /* Protocol field byte in IP hdr          */
83 #define IP_PROTOCOL_TCP    0x06 /* Protocol field value for TCP           */
84 #define IP_HDR_LEN           20 /* Minimum IP header length               */
85 #define IP_HDR_LEN_MASK    0x0f /* Mask for header length field           */
86 #define IP_MAX_OPT_LEN       44 /* Max length of IP options               */
87 #define TCP_HDR_LEN          20 /* Minimum TCP header length              */
88 #define TCP_MAX_OPT_LEN      44 /* Max length of TCP options              */
89 #define TCP_SIMUL_CONV      256 /* Number of simul. TCP conversations     */
90 #define TCP_SIMUL_CONV_MAX  256 /* Max number of simul. TCP conversations */
91 #define CHANGE_PUSH_BIT    0x10 /* TCP push bit changed                   */
92 #define TCP_PUSH_BIT       0x08 /* TCP push bit                           */
93 #define TCP_URG_BIT        0x20 /* TCP urgent bit                         */
94
95 /* Bits in first octet of compressed packet */
96 /* flag bits for what changed in a packet */
97 #define NEW_C   0x40    
98 #define NEW_I   0x20
99 #define NEW_S   0x08
100 #define NEW_A   0x04
101 #define NEW_W   0x02
102 #define NEW_U   0x01
103
104 /* reserved, special-case values of above */
105 #define SPECIAL_I     (NEW_S|NEW_W|NEW_U)    /* echoed interactive traffic */
106 #define SPECIAL_D     (NEW_S|NEW_A|NEW_W|NEW_U)/* unidirectional data */
107 #define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
108
109 /* Function return values */
110 #define VJ_OK           0
111 #define VJ_ERROR       -1
112
113 /* Define for 0 */
114 #define ZERO            0
115
116 /* Two byte CRC */
117 #define CRC_LEN         sizeof(guint16) 
118
119 /* VJ Mem Chunk defines */
120 #define VJ_DATA_SIZE  128 /* Max IP hdr(64)+Max TCP hdr(64) */
121 #define VJ_ATOM_COUNT 250 /* Number of Atoms per block      */ 
122
123 /* IP and TCP header types */
124 typedef struct {
125   guint8  ihl_version;
126   guint8  tos;
127   guint16 tot_len;
128   guint16 id;
129   guint16 frag_off;
130   guint8  ttl;
131   guint8  proto;
132   guint16 cksum;
133   guint32 src;
134   guint32 dst;
135 } iphdr_type; 
136
137 typedef struct {
138   guint16 srcport;
139   guint16 dstport;
140   guint32 seq;
141   guint32 ack_seq;
142   guint8  off_x2;
143   guint8  flags;
144   guint16 window;
145   guint16 cksum;
146   guint16 urg_ptr;
147 } tcphdr_type;
148
149 #define TCP_OFFSET(th)  (((th)->off_x2 & 0xf0) >> 4)
150
151 /* State per active tcp conversation */
152 typedef struct cstate {
153   struct cstate *next;   /* next in ring (xmit) */
154   iphdr_type cs_ip; 
155   tcphdr_type cs_tcp;
156   guint8 cs_ipopt[IP_MAX_OPT_LEN];
157   guint8 cs_tcpopt[TCP_MAX_OPT_LEN];
158 } cstate;
159
160 /* All the state data for one serial line */
161 typedef struct {
162   cstate *rstate;  /* receive connection states (array)*/
163   guint8 rslot_limit;     /* highest receive slot id */
164   guint8 recv_current;    /* most recent rcvd id */
165   guint8 flags;
166 #define SLF_TOSS  0x01    /* tossing rcvd frames until id received */
167 } slcompress;
168
169 /* Initialize the protocol and registered fields */
170 static int proto_vj = -1;
171
172 /* Protocol handles */
173 static dissector_handle_t ip_handle;
174 static dissector_handle_t data_handle;
175
176 /* State repository (Full Duplex) */
177 #define RX_TX_STATE_COUNT 2
178 static slcompress *rx_tx_state[RX_TX_STATE_COUNT] = {NULL, NULL};
179  
180 /* Mem Chunks for storing decompressed headers */
181 static GMemChunk *vj_header_memchunk = NULL;
182 typedef struct {
183         guint32 offset;
184         guint8  data[VJ_DATA_SIZE];
185 } vj_header_t;
186         
187 /* Function prototypes */
188 static void decodes(tvbuff_t *tvb, guint32 *offset, gint16 *val);
189 static void decodel(tvbuff_t *tvb, guint32 *offset, gint32 *val);
190 static guint16 ip_csum(const guint8 *ptr, guint32 len);
191 static slcompress *slhc_init(gint rslots);
192 static void vj_init(void);
193 static gint vjuc_check(tvbuff_t *tvb, slcompress *comp);
194 static void vjuc_update_state(tvbuff_t *tvb, slcompress *comp, guint8 index);
195 static gint vjuc_tvb_setup(tvbuff_t *tvb, tvbuff_t **dst_tvb, 
196                            slcompress *comp, frame_data *fd);
197 static gint vjc_check(tvbuff_t *src_tvb, slcompress *comp);
198 static gint vjc_update_state(tvbuff_t *src_tvb, slcompress *comp, 
199                              frame_data *fd);
200 static gint vjc_tvb_setup(tvbuff_t *src_tvb, tvbuff_t **dst_tvb, 
201                           frame_data *fd);
202
203 /* Dissector for VJ Uncompressed packets */
204 static void
205 dissect_vjuc(tvbuff_t *tvb, packet_info *pinfo, proto_tree * tree)
206 {
207   tvbuff_t   *next_tvb    = NULL;
208   slcompress *comp        = NULL;
209   gint        conn_index  = ZERO;
210   gint        err         = VJ_OK;
211
212   /* Return if VJ is off or direction is not known */
213   if(ppp_vj_decomp == FALSE || pinfo->p2p_dir == P2P_DIR_UNKNOWN) 
214     err = VJ_ERROR;
215
216   if((comp = rx_tx_state[pinfo->p2p_dir]) == NULL)
217     err = VJ_ERROR;
218
219   /* Check if packet malformed. */
220   if(err == VJ_OK)
221     err = conn_index = vjuc_check(tvb, comp); 
222
223   /* Set up tvb containing decompressed packet */
224   if(err != VJ_ERROR)
225     err = vjuc_tvb_setup(tvb, &next_tvb, comp, pinfo->fd);
226
227   /* If packet seen for first time update state */
228   if(pinfo->fd->flags.visited != 1 && err == VJ_OK) 
229     vjuc_update_state(next_tvb, comp, conn_index);
230
231   /* If no errors call IP dissector else dissect as data. */
232   if(err == VJ_OK)
233     call_dissector(ip_handle, next_tvb, pinfo, tree);
234   else
235     call_dissector(data_handle, tvb, pinfo, tree);
236 }
237
238 /* Dissector for VJ Compressed packets */
239 static void
240 dissect_vjc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
241 {
242   tvbuff_t   *next_tvb = NULL;
243   slcompress *comp     = NULL;
244   gint        err      = VJ_OK;
245   
246   /* Return if VJ is off or direction is not known */
247   if(ppp_vj_decomp == FALSE || pinfo->p2p_dir == P2P_DIR_UNKNOWN) 
248     err = VJ_ERROR;
249   
250   if((comp = rx_tx_state[pinfo->p2p_dir]) == NULL)
251     err = VJ_ERROR;
252
253   /* Check if packet malformed. */
254   if(err != VJ_ERROR)
255     err = vjc_check(tvb, comp);
256
257   /* If packet seen for first time update state */
258   if(pinfo->fd->flags.visited != 1 && err == VJ_OK) {
259     err = vjc_update_state(tvb, comp, pinfo->fd); 
260   }
261
262   /* Set up tvb containing decompressed packet */
263   if(err == VJ_OK)
264     err = vjc_tvb_setup(tvb, &next_tvb, pinfo->fd); 
265
266   /* If no errors call IP dissector else dissect as data */
267   if(err == VJ_OK)
268     call_dissector(ip_handle, next_tvb, pinfo, tree);
269   else
270     call_dissector(data_handle, tvb, pinfo, tree);
271 }
272
273 /* Registeration functions for dissectors */
274 void
275 proto_register_vj(void)
276 {
277   proto_vj = proto_register_protocol("PPP VJ Compression", "PPP VJ", "vj");
278   register_init_routine(&vj_init);
279 }
280
281 void
282 proto_reg_handoff_vj(void)
283 {
284   dissector_handle_t vjc_handle;
285   dissector_handle_t vjuc_handle;
286
287   vjc_handle = create_dissector_handle(dissect_vjc, proto_vj);
288   dissector_add("ppp.protocol", PPP_VJC_COMP, vjc_handle);
289
290   vjuc_handle = create_dissector_handle(dissect_vjuc, proto_vj);
291   dissector_add("ppp.protocol", PPP_VJC_UNCOMP, vjuc_handle);
292
293   ip_handle = find_dissector("ip");
294   data_handle = find_dissector("data");
295 }
296
297 /* Initialization function */
298 static void 
299 vj_init(void)
300 {
301   gint i           = ZERO;
302   slcompress *pslc = NULL;
303   cstate *pstate   = NULL;
304
305   if(vj_header_memchunk != NULL)
306     g_mem_chunk_destroy(vj_header_memchunk);
307   vj_header_memchunk = g_mem_chunk_new("vj header store", sizeof (vj_header_t), 
308                                        sizeof (vj_header_t) * VJ_ATOM_COUNT,
309                                        G_ALLOC_ONLY);
310   for(i=0; i< RX_TX_STATE_COUNT; i++){
311     if((pslc = rx_tx_state[i]) != NULL){
312       if((pstate = pslc->rstate) != NULL)
313         g_free(pstate);
314       g_free(pslc);
315     }
316     rx_tx_state[i] = slhc_init(TCP_SIMUL_CONV);
317   }
318   return;
319 }
320
321 /* Initialization routine for VJ decompression */
322 static slcompress *
323 slhc_init(gint rslots)
324 {
325   size_t rsize     = rslots * sizeof(cstate);
326   slcompress *comp = g_malloc(sizeof(slcompress));
327
328   if(rslots < ZERO || rslots > TCP_SIMUL_CONV_MAX)
329     return NULL;
330
331   if (comp != NULL) {
332     memset(comp, ZERO, sizeof(slcompress));
333     if ((comp->rstate = g_malloc(rsize)) == NULL) {
334       g_free(comp);
335       comp = NULL;
336     }
337     else {
338       memset(comp->rstate, ZERO, rsize);
339       comp->rslot_limit = rslots - 1;
340       comp->recv_current = TCP_SIMUL_CONV_MAX - 1;
341       comp->flags |= SLF_TOSS;
342     }
343   }
344   return comp;
345
346
347 /* Setup the decompressed packet tvb for VJ compressed packets */
348 static gint 
349 vjc_tvb_setup(tvbuff_t *src_tvb, 
350               tvbuff_t **dst_tvb, 
351               frame_data * fd)
352 {
353   vj_header_t *hdr_buf;
354   guint8      *data_ptr;
355   guint8      *pbuf        = NULL;
356   gint         hdr_len     = ZERO;
357   gint         buf_len     = ZERO;
358   guint8       offset      = ZERO;
359
360   g_assert(src_tvb);
361
362   /* Get decompressed header stored in fd protocol area */
363   hdr_buf = p_get_proto_data(fd, proto_vj);
364   if(hdr_buf == NULL) 
365     return VJ_ERROR;
366
367   /* Get the data offset in the tvbuff */
368   offset  = hdr_buf->offset;
369
370   /* Copy header and form tvb */
371   data_ptr = hdr_buf->data;
372   hdr_len  = lo_nibble(((iphdr_type *)data_ptr)->ihl_version) * 4;
373   hdr_len += TCP_OFFSET(((tcphdr_type *)(data_ptr + hdr_len))) * 4;
374   buf_len  = tvb_length(src_tvb) + hdr_len - offset;
375   pbuf     = g_malloc(buf_len); 
376   memcpy(pbuf, data_ptr, hdr_len);
377   tvb_memcpy(src_tvb, pbuf + hdr_len, offset, buf_len - hdr_len);
378   *dst_tvb = tvb_new_real_data(pbuf, buf_len, buf_len);
379   tvb_set_child_real_data_tvbuff(src_tvb, *dst_tvb);
380   add_new_data_source(fd, *dst_tvb, "VJ Decompressed");
381   return VJ_OK;
382
383
384 /* For VJ compressed packets update the decompressor state */
385 static gint 
386 vjc_update_state(tvbuff_t *src_tvb,  slcompress *comp, frame_data *fd)
387 {
388   vj_header_t   *buf_hdr;
389   guint8        *data_ptr;
390   cstate        *cs      = &comp->rstate[comp->recv_current];
391   tcphdr_type   *thp     = &cs->cs_tcp;
392   iphdr_type    *ip      = &cs->cs_ip;
393   gint           changes = ZERO;
394   gint           len     = ZERO;
395   gint           hdrlen  = ZERO;
396   guint32        offset  = ZERO;
397   guint16        word    = ZERO;
398
399   g_assert(src_tvb);
400   g_assert(comp);
401   g_assert(fd);
402
403   /* Read the change byte */
404   changes = tvb_get_guint8(src_tvb, offset++);
405   if(changes & NEW_C)
406    offset++;
407
408   /* Build TCP and IP headers */
409   hdrlen = lo_nibble(ip->ihl_version) * 4 + TCP_OFFSET(thp) * 4;
410   thp->cksum = htons(tvb_get_ntohs(src_tvb, offset));
411   offset += 2;
412   if (changes & CHANGE_PUSH_BIT)  
413     thp->flags |= TCP_PUSH_BIT; 
414   else
415     thp->flags &= ~TCP_PUSH_BIT;
416
417   /* Deal with special cases and normal deltas */
418   switch(changes & SPECIALS_MASK){
419     case SPECIAL_I:                   /* Echoed terminal traffic */
420       word = ntohs(ip->tot_len) - hdrlen;
421       thp->ack_seq = htonl( ntohl(thp->ack_seq) + word);
422       thp->seq = htonl( ntohl(thp->seq) + word);
423     break;
424     case SPECIAL_D:                   /* Unidirectional data */
425       thp->seq = htonl( ntohl(thp->seq) + ntohs(ip->tot_len) - hdrlen);
426     break;
427     default:
428       if(changes & NEW_U){
429         thp->urg_ptr = ZERO;
430         decodes(src_tvb, &offset, &thp->urg_ptr);  
431         thp->flags |= TCP_URG_BIT;
432       } 
433       else
434         thp->flags &= ~TCP_URG_BIT;
435       if(changes & NEW_W)
436         decodes(src_tvb, &offset, &thp->window); 
437       if(changes & NEW_A)
438         decodel(src_tvb, &offset, &thp->ack_seq); 
439       if(changes & NEW_S)
440         decodel(src_tvb, &offset, &thp->seq); 
441     break;
442   }
443   if(changes & NEW_I)
444     decodes(src_tvb, &offset, &ip->id); 
445   else
446     ip->id = htons (ntohs (ip->id) + 1);
447
448   /* Compute ip packet length and the buffer length needed */
449   if((len = tvb_length(src_tvb) - offset - CRC_LEN) < ZERO) {
450     comp->flags |= SLF_TOSS;
451     return VJ_ERROR;
452   }
453   len += hdrlen;
454   ip->tot_len = htons(len);
455   /* Compute IP check sum */
456   ip->cksum = ZERO;
457   ip->cksum = ip_csum((guint8 *)ip, lo_nibble(ip->ihl_version) * 4);
458
459   /* Store the reconstructed header in frame data area */
460   buf_hdr = g_mem_chunk_alloc(vj_header_memchunk);
461   buf_hdr->offset = offset;  /* Offset in tvbuff is also stored */
462   data_ptr = buf_hdr->data;
463   memcpy(data_ptr, ip, IP_HDR_LEN);
464   data_ptr += IP_HDR_LEN;
465   if(lo_nibble(ip->ihl_version) > 5) {
466     memcpy(data_ptr, cs->cs_ipopt, (lo_nibble(ip->ihl_version) - 5) * 4);
467     data_ptr += (lo_nibble(ip->ihl_version) - 5) * 4;
468   }
469   memcpy(data_ptr, thp, TCP_HDR_LEN);
470   data_ptr += TCP_HDR_LEN;
471   if(TCP_OFFSET(thp) > 5)
472     memcpy(data_ptr, cs->cs_tcpopt, (TCP_OFFSET(thp) - 5) * 4);
473   p_add_proto_data(fd, proto_vj, buf_hdr);
474
475   return VJ_OK;
476
477
478 /* For VJ compressed packet check if it is malformed */
479 static gint 
480 vjc_check(tvbuff_t *src_tvb, slcompress *comp)
481 {
482   guint8 conn_index = ZERO;
483   guint8 offset     = ZERO;
484   gint   changes    = ZERO;
485
486   g_assert(src_tvb);
487   g_assert(comp);
488
489   if(tvb_length(src_tvb) < 3){
490     comp->flags |= SLF_TOSS;
491     return VJ_ERROR;
492   }
493
494   /* Read the change byte */
495   changes = tvb_get_guint8(src_tvb, offset++);
496
497   if(changes & NEW_C){    /* Read conn index */
498     conn_index = tvb_get_guint8(src_tvb, offset++);
499     if(conn_index > comp->rslot_limit) {
500       comp->flags |= SLF_TOSS;
501       return VJ_ERROR;
502     }
503     comp->flags &= ~SLF_TOSS;
504     comp->recv_current = conn_index;
505   } 
506   else {
507    if(comp->flags & SLF_TOSS)
508      return VJ_ERROR;
509   }
510   
511   return VJ_OK;
512
513
514 /* Decode the delta of a 32 bit header field */
515 static void 
516 decodel(tvbuff_t *tvb, guint32* offset, gint32 *val)
517 {
518   gint del = tvb_get_guint8(tvb, (*offset)++);
519   if(del == ZERO){
520     del = tvb_get_ntohs(tvb, *offset);
521     *offset= *offset + 2;
522   }
523   *val = htonl(ntohl(*val) + del);
524   return;
525 }
526
527 /* Decode the delta of a 16 bit header field */
528 static void 
529 decodes(tvbuff_t *tvb, guint32* offset, gint16 *val)
530 {
531   gint del = tvb_get_guint8(tvb, (*offset)++);
532   if(del == ZERO){
533     del = tvb_get_ntohs(tvb, *offset);
534     *offset= *offset + 2;
535   }
536   *val = htons(ntohs(*val) + del);
537   return;
538 }
539
540 /* For VJ uncompressed packet check if it is malformed */
541 static gint 
542 vjuc_check(tvbuff_t *tvb, slcompress *comp)
543 {
544   guint8 ihl   = ZERO;
545   gint   index = ZERO;
546
547   g_assert(comp);
548   g_assert(tvb);
549
550   if(tvb_length(tvb) < IP_HDR_LEN) {
551     comp->flags |= SLF_TOSS;
552     index = VJ_ERROR;
553   }
554   else {
555     /* Get the IP header length */
556     ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
557     ihl <<= 2;
558
559     /* Get connection index */
560     index = tvb_get_guint8(tvb, IP_FIELD_PROTOCOL);
561
562     /* Check connection number and IP header length field */
563     if(ihl < IP_HDR_LEN || index > comp->rslot_limit) {
564       comp->flags |= SLF_TOSS;
565       index = VJ_ERROR;
566     }
567   }
568
569   return index;
570
571
572 /* Setup the decompressed packet tvb for VJ uncompressed packets */
573 static gint 
574 vjuc_tvb_setup(tvbuff_t *tvb, 
575                tvbuff_t **dst_tvb, 
576                slcompress *comp,
577                frame_data *fd)
578 {
579   guint8     ihl         = ZERO;
580   gint       isize       = tvb_length(tvb);
581   guint8    *buffer      = NULL;
582
583   g_assert(comp);
584   g_assert(tvb);
585
586   /* Get the IP header length */
587   ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
588   ihl <<= 2;
589   
590   /* Copy packet data to a buffer */
591   buffer   = g_malloc(isize);
592   tvb_memcpy(tvb, buffer, 0, isize);
593   buffer[IP_FIELD_PROTOCOL] = IP_PROTOCOL_TCP;
594
595   /* Compute checksum */
596   if (ip_csum(buffer, ihl) != ZERO) {
597     g_free(buffer);
598     comp->flags |= SLF_TOSS;
599     return VJ_ERROR;
600   }
601
602   /* 
603    * Form the new tvbuff. 
604    * Neither header checksum is recalculated
605    */
606   *dst_tvb = tvb_new_real_data(buffer, isize, isize);
607   tvb_set_child_real_data_tvbuff(tvb, *dst_tvb);
608   add_new_data_source(fd, *dst_tvb, "VJ Uncompressed");
609   return VJ_OK;
610
611
612 /* For VJ uncompressed packets update the decompressor state */
613 static void 
614 vjuc_update_state(tvbuff_t *tvb, slcompress *comp, guint8 index)
615 {
616   cstate  *cs    = NULL;
617   guint8   ihl   = ZERO;
618
619   g_assert(comp);
620   g_assert(tvb);
621
622   /* Get the IP header length */
623   ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
624   ihl <<= 2;
625   
626   /* Update local state */
627   cs = &comp->rstate[comp->recv_current = index];
628   comp->flags &= ~SLF_TOSS;
629   tvb_memcpy(tvb, (guint8 *)&cs->cs_ip, 0, IP_HDR_LEN);
630   tvb_memcpy(tvb, (guint8 *)&cs->cs_tcp, ihl, TCP_HDR_LEN);
631   if (ihl > IP_HDR_LEN)
632     tvb_memcpy(tvb, cs->cs_ipopt, sizeof(iphdr_type), ihl - IP_HDR_LEN);
633   if (TCP_OFFSET(&(cs->cs_tcp)) > 5)
634     tvb_memcpy(tvb, cs->cs_tcpopt, ihl + sizeof(tcphdr_type), 
635                (TCP_OFFSET(&(cs->cs_tcp)) - 5) * 4);
636   return;
637
638
639 /* Wraper for in_cksum function */
640 static guint16 
641 ip_csum(const guint8 * ptr, guint32 len)
642 {
643         vec_t cksum_vec[1];
644
645         cksum_vec[0].ptr = ptr;
646         cksum_vec[0].len = len;
647         return in_cksum(&cksum_vec[0], 1);
648 }