Again, leave the SET_ADDRESS() stuff for IP to the IP dissector.
[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.3 2001/12/20 06:32:19 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 "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_PUSH_BIT       0x10 /* TCP push bit                           */
89 #define TCP_MAX_OPT_LEN      44 /* Max length of TCP options               */
90 #define TCP_SIMUL_CONV      256 /* Number of simul. TCP conversations     */
91 #define TCP_SIMUL_CONV_MAX  256 /* Max number of simul. TCP conversations */
92
93 /* Bits in first octet of compressed packet */
94 /* flag bits for what changed in a packet */
95 #define NEW_C   0x40    
96 #define NEW_I   0x20
97 #define NEW_S   0x08
98 #define NEW_A   0x04
99 #define NEW_W   0x02
100 #define NEW_U   0x01
101
102 /* reserved, special-case values of above */
103 #define SPECIAL_I     (NEW_S|NEW_W|NEW_U)    /* echoed interactive traffic */
104 #define SPECIAL_D     (NEW_S|NEW_A|NEW_W|NEW_U)/* unidirectional data */
105 #define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
106
107 /* Function return values */
108 #define VJ_OK           0
109 #define VJ_ERROR       -1
110
111 /* Define for 0 */
112 #define ZERO            0
113
114 /* Two byte CRC */
115 #define CRC_LEN         sizeof(guint16) 
116
117 /* VJ Mem Chunk defines */
118 #define VJ_DATA_SIZE  128 /* Max IP hdr(64)+Max TCP hdr(64) */
119 #define VJ_ATOM_COUNT 250 /* Number of Atoms per block      */ 
120
121 /* IP and TCP header types */
122 typedef struct {
123 #if BYTE_ORDER == LITTLE_ENDIAN 
124   guint8  ihl:4,
125           version:4;
126 #else 
127   guint8  version:4,
128           ihl:4;
129 #endif
130   guint8  tos;
131   guint16 tot_len;
132   guint16 id;
133   guint16 frag_off;
134   guint8  ttl;
135   guint8  proto;
136   guint16 cksum;
137   guint32 src;
138   guint32 dst;
139 } iphdr_type; 
140
141 typedef struct {
142   guint16 srcport;
143   guint16 dstport;
144   guint32 seq;
145   guint32 ack_seq;
146 #if BYTE_ORDER == LITTLE_ENDIAN
147   guint16 res1:4,
148           doff:4,
149           fin:1,
150           syn:1,
151           rst:1,
152           psh:1,
153           ack:1,
154           urg:1,
155           ece:1,
156           cwr:1;
157 #else 
158   guint16 doff:4,
159           res1:4,
160           cwr:1,
161           ece:1,
162           urg:1,
163           ack:1,
164           psh:1,
165           rst:1,
166           syn:1,
167           fin:1;
168 #endif
169   guint16 window;
170   guint16 cksum;
171   guint16 urg_ptr;
172 } tcphdr_type;
173
174
175 /* State per active tcp conversation */
176 typedef struct cstate {
177   struct cstate *next;   /* next in ring (xmit) */
178   iphdr_type cs_ip; 
179   tcphdr_type cs_tcp;
180   guint8 cs_ipopt[IP_MAX_OPT_LEN];
181   guint8 cs_tcpopt[TCP_MAX_OPT_LEN];
182 } cstate;
183
184 /* All the state data for one serial line */
185 typedef struct {
186   cstate *rstate;  /* receive connection states (array)*/
187   guint8 rslot_limit;     /* highest receive slot id */
188   guint8 recv_current;    /* most recent rcvd id */
189   guint8 flags;
190 #define SLF_TOSS  0x01    /* tossing rcvd frames until id received */
191 } slcompress;
192
193 /* Initialize the protocol and registered fields */
194 static int proto_vj = -1;
195
196 /* Protocol handles */
197 static dissector_handle_t vjc_handle;
198 static dissector_handle_t vjuc_handle;
199 static dissector_handle_t data_handle;
200
201 /* State repository (Full Duplex) */
202 #define RX_TX_STATE_COUNT 2
203 static slcompress *rx_tx_state[RX_TX_STATE_COUNT] = {NULL, NULL};
204  
205 /* Mem Chunks for storing decompressed headers */
206 static GMemChunk *vj_header_memchunk = NULL;
207 typedef struct {
208         guint32 offset;
209         guint8  data[VJ_DATA_SIZE];
210 } vj_header_t;
211         
212 /* Function prototypes */
213 static void decodes(tvbuff_t *tvb, guint32 *offset, gint16 *val);
214 static void decodel(tvbuff_t *tvb, guint32 *offset, gint32 *val);
215 static guint16 ip_csum(const guint8 *ptr, guint32 len);
216 static slcompress *slhc_init(gint rslots);
217 static void vj_init(void);
218 static void vj_display_pkt(tvbuff_t *parent_tvb, tvbuff_t *child_tvb, 
219                            packet_info *pinfo, proto_tree *tree);
220 static gint vjuc_check(tvbuff_t *tvb, slcompress *comp);
221 static void vjuc_update_state(tvbuff_t *tvb, slcompress *comp, guint8 index);
222 static gint vjuc_tvb_setup(tvbuff_t *tvb, tvbuff_t **dst_tvb, 
223                            slcompress *comp);
224 static gint vjc_check(tvbuff_t *src_tvb, slcompress *comp);
225 static gint vjc_update_state(tvbuff_t *src_tvb, slcompress *comp, 
226                              frame_data *fd);
227 static gint vjc_tvb_setup(tvbuff_t *src_tvb, tvbuff_t **dst_tvb, 
228                           frame_data *fd);
229
230 /* Dissector for VJ Uncompressed packets */
231 static void
232 dissect_vjuc(tvbuff_t *tvb, packet_info *pinfo, proto_tree * tree)
233 {
234   tvbuff_t   *next_tvb    = NULL;
235   tvbuff_t   *data_tvb    = NULL;
236   slcompress *comp        = NULL;
237   gint        conn_index  = ZERO;
238   gint        err         = VJ_OK;
239
240   /* Return if VJ is off or direction is not known */
241   if(ppp_vj_decomp == FALSE || pinfo->p2p_dir == P2P_DIR_UNKNOWN) 
242     err = VJ_ERROR;
243
244   if((comp = rx_tx_state[pinfo->p2p_dir]) == NULL)
245     err = VJ_ERROR;
246
247   /* Check if packet malformed. */
248   if(err == VJ_OK)
249     err = conn_index = vjuc_check(tvb, comp); 
250
251   /* Set up tvb containing decompressed packet */
252   if(err != VJ_ERROR)
253     err = vjuc_tvb_setup(tvb, &next_tvb, comp); 
254
255   /* If packet seen for first time update state */
256   if(pinfo->fd->flags.visited != 1 && err == VJ_OK) 
257     vjuc_update_state(next_tvb, comp, conn_index);
258
259   /* If no errors call IP dissector else dissect as data. */
260   if(err == VJ_OK)
261     vj_display_pkt(tvb, next_tvb, pinfo, tree);
262   else {
263     data_tvb = tvb_new_subset(tvb, 0, -1, -1);
264     call_dissector(data_handle, data_tvb, pinfo, tree);
265   }
266 }
267
268 /* Dissector for VJ Compressed packets */
269 static void
270 dissect_vjc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
271 {
272   tvbuff_t   *next_tvb = NULL;
273   tvbuff_t   *data_tvb = NULL;
274   slcompress *comp     = NULL;
275   gint        err      = VJ_OK;
276   
277   /* Return if VJ is off or direction is not known */
278   if(ppp_vj_decomp == FALSE || pinfo->p2p_dir == P2P_DIR_UNKNOWN) 
279     err = VJ_ERROR;
280   
281   if((comp = rx_tx_state[pinfo->p2p_dir]) == NULL)
282     err = VJ_ERROR;
283
284   /* Check if packet malformed. */
285   if(err != VJ_ERROR)
286     err = vjc_check(tvb, comp);
287
288   /* If packet seen for first time update state */
289   if(pinfo->fd->flags.visited != 1 && err == VJ_OK) {
290     err = vjc_update_state(tvb, comp, pinfo->fd); 
291   }
292
293   /* Set up tvb containing decompressed packet */
294   if(err == VJ_OK)
295     err = vjc_tvb_setup(tvb, &next_tvb, pinfo->fd); 
296
297   /* If no errors call IP dissector else dissect as data */
298   if(err == VJ_OK)
299     vj_display_pkt(tvb, next_tvb, pinfo, tree);
300   else {
301     data_tvb = tvb_new_subset(tvb, 0, -1, -1);
302     call_dissector(data_handle, data_tvb, pinfo, tree);
303   }
304 }
305
306 /* Registeration functions for dissectors */
307 void
308 proto_register_vj(void)
309 {
310   proto_vj = proto_register_protocol("PPP VJ Compression", "PPP VJ", "vj");
311   register_init_routine(&vj_init);
312
313   vjc_handle = create_dissector_handle(dissect_vjc, proto_vj);
314   vjuc_handle = create_dissector_handle(dissect_vjuc, proto_vj);
315
316 }
317
318 void
319 proto_reg_handoff_vj(void)
320 {
321   dissector_add("ppp.protocol", PPP_VJC_COMP, vjc_handle);
322   dissector_add("ppp.protocol", PPP_VJC_UNCOMP, vjuc_handle);
323
324   data_handle = find_dissector("data");
325 }
326
327 /* Function to setup decompressed packet display */
328 static void 
329 vj_display_pkt(tvbuff_t *parent_tvb, 
330                tvbuff_t *child_tvb, 
331                packet_info *pinfo, 
332                proto_tree *tree)
333 {
334   dissector_handle_t ip_handle = find_dissector("ip");
335   frame_data *fd               = pinfo->fd;
336   tvbuff_t   *data_tvb         = NULL;
337   
338   g_assert(parent_tvb);
339   g_assert(child_tvb);
340   g_assert(fd);
341
342   if (ip_handle == NULL) {
343     data_tvb = tvb_new_subset(child_tvb, 0, -1, -1);
344     call_dissector(data_handle, data_tvb, pinfo, tree);
345   }
346   else {
347     tvb_set_child_real_data_tvbuff(parent_tvb, child_tvb);
348     fd->data_src = g_slist_append(fd->data_src, child_tvb);
349     call_dissector(ip_handle, child_tvb, pinfo, tree);
350   }
351   return;
352 }
353
354 /* Initialization function */
355 static void 
356 vj_init(void)
357 {
358   gint i           = ZERO;
359   slcompress *pslc = NULL;
360   cstate *pstate   = NULL;
361
362   if(vj_header_memchunk != NULL)
363     g_mem_chunk_destroy(vj_header_memchunk);
364   vj_header_memchunk = g_mem_chunk_new("vj header store", sizeof (vj_header_t), 
365                                        sizeof (vj_header_t) * VJ_ATOM_COUNT,
366                                        G_ALLOC_ONLY);
367   for(i=0; i< RX_TX_STATE_COUNT; i++){
368     if((pslc = rx_tx_state[i]) != NULL){
369       if((pstate = pslc->rstate) != NULL)
370         g_free(pstate);
371       g_free(pslc);
372     }
373     rx_tx_state[i] = slhc_init(TCP_SIMUL_CONV);
374   }
375   return;
376 }
377
378 /* Initialization routine for VJ decompression */
379 static slcompress *
380 slhc_init(gint rslots)
381 {
382   size_t rsize     = rslots * sizeof(cstate);
383   slcompress *comp = g_malloc(sizeof(slcompress));
384
385   if(rslots < ZERO || rslots > TCP_SIMUL_CONV_MAX)
386     return NULL;
387
388   if (comp != NULL) {
389     memset(comp, ZERO, sizeof(slcompress));
390     if ((comp->rstate = g_malloc(rsize)) == NULL) {
391       g_free(comp);
392       comp = NULL;
393     }
394     else {
395       memset(comp->rstate, ZERO, rsize);
396       comp->rslot_limit = rslots - 1;
397       comp->recv_current = TCP_SIMUL_CONV_MAX - 1;
398       comp->flags |= SLF_TOSS;
399     }
400   }
401   return comp;
402
403
404 /* Setup the decompressed packet tvb for VJ compressed packets */
405 static gint 
406 vjc_tvb_setup(tvbuff_t *src_tvb, 
407               tvbuff_t **dst_tvb, 
408               frame_data * fd)
409 {
410   tvbuff_t    *orig_tvb    = NULL;
411   vj_header_t *hdr_buf;
412   guint8      *data_ptr;
413   guint8      *pbuf        = NULL;
414   gint         hdr_len     = ZERO;
415   gint         buf_len     = ZERO;
416   guint8       offset      = ZERO;
417
418   g_assert(src_tvb);
419
420   /* Get decompressed header stored in fd protocol area */
421   hdr_buf = p_get_proto_data(fd, proto_vj);
422   if(hdr_buf == NULL) 
423     return VJ_ERROR;
424
425   /* Get the data offset in the tvbuff */
426   offset  = hdr_buf->offset;
427
428   /* Copy header and form tvb */
429   data_ptr = hdr_buf->data;
430   hdr_len  = ((iphdr_type *)data_ptr)->ihl * 4;
431   hdr_len += ((tcphdr_type *)(data_ptr + hdr_len))->doff * 4;
432   buf_len  = tvb_length(src_tvb) + hdr_len - offset;
433   pbuf     = g_malloc(buf_len); 
434   memcpy(pbuf, data_ptr, hdr_len);
435   tvb_memcpy(src_tvb, pbuf + hdr_len, offset, buf_len - hdr_len);
436   *dst_tvb = tvb_new_real_data(pbuf, buf_len, buf_len, "VJ Decompressed");
437   return VJ_OK;
438
439
440 /* For VJ compressed packets update the decompressor state */
441 static gint 
442 vjc_update_state(tvbuff_t *src_tvb,  slcompress *comp, frame_data *fd)
443 {
444   vj_header_t   *buf_hdr;
445   guint8        *data_ptr;
446   cstate        *cs      = &comp->rstate[comp->recv_current];
447   tcphdr_type   *thp     = &cs->cs_tcp;
448   iphdr_type    *ip      = &cs->cs_ip;
449   gint           changes = ZERO;
450   gint           len     = ZERO;
451   gint           hdrlen  = ZERO;
452   guint32        offset  = ZERO;
453   guint16        word    = ZERO;
454
455   g_assert(src_tvb);
456   g_assert(comp);
457   g_assert(fd);
458
459   /* Read the change byte */
460   changes = tvb_get_guint8(src_tvb, offset++);
461   if(changes & NEW_C)
462    offset++;
463
464   /* Build TCP and IP headers */
465   hdrlen = ip->ihl * 4 + thp->doff * 4;
466   thp->cksum = htons((tvb_get_guint8(src_tvb, offset++) << 8) | 
467                       tvb_get_guint8(src_tvb, offset++));
468   thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
469
470   /* Deal with special cases and normal deltas */
471   switch(changes & SPECIALS_MASK){
472     case SPECIAL_I:                   /* Echoed terminal traffic */
473       word = ntohs(ip->tot_len) - hdrlen;
474       thp->ack_seq = htonl( ntohl(thp->ack_seq) + word);
475       thp->seq = htonl( ntohl(thp->seq) + word);
476     break;
477     case SPECIAL_D:                   /* Unidirectional data */
478       thp->seq = htonl( ntohl(thp->seq) + ntohs(ip->tot_len) - hdrlen);
479     break;
480     default:
481       if(changes & NEW_U){
482         thp->urg_ptr = ZERO;
483         decodes(src_tvb, &offset, &thp->urg_ptr);  
484         thp->urg = 1;
485       } 
486       else
487         thp->urg = 0;
488       if(changes & NEW_W)
489         decodes(src_tvb, &offset, &thp->window); 
490       if(changes & NEW_A)
491         decodel(src_tvb, &offset, &thp->ack_seq); 
492       if(changes & NEW_S)
493         decodel(src_tvb, &offset, &thp->seq); 
494     break;
495   }
496   if(changes & NEW_I)
497     decodes(src_tvb, &offset, &ip->id); 
498   else
499     ip->id = htons (ntohs (ip->id) + 1);
500
501   /* Compute ip packet length and the buffer length needed */
502   if((len = tvb_length(src_tvb) - offset - CRC_LEN) < ZERO) {
503     comp->flags |= SLF_TOSS;
504     return VJ_ERROR;
505   }
506   len += hdrlen;
507   ip->tot_len = htons(len);
508   /* Compute IP check sum */
509   ip->cksum = ZERO;
510   ip->cksum = ip_csum((guint8 *)ip, ip->ihl * 4);
511
512   /* Store the reconstructed header in frame data area */
513   buf_hdr = g_mem_chunk_alloc(vj_header_memchunk);
514   buf_hdr->offset = offset;  /* Offset in tvbuff is also stored */
515   data_ptr = buf_hdr->data;
516   memcpy(data_ptr, ip, IP_HDR_LEN);
517   data_ptr += IP_HDR_LEN;
518   if(ip->ihl > 5) {
519     memcpy(data_ptr, cs->cs_ipopt, (ip->ihl - 5) * 4);
520     data_ptr += (ip->ihl - 5) * 4;
521   }
522   memcpy(data_ptr, thp, TCP_HDR_LEN);
523   data_ptr += TCP_HDR_LEN;
524   if(thp->doff > 5)
525     memcpy(data_ptr, cs->cs_tcpopt, (thp->doff - 5) * 4);
526   p_add_proto_data(fd, proto_vj, buf_hdr);
527
528   return VJ_OK;
529
530
531 /* For VJ compressed packet check if it is malformed */
532 static gint 
533 vjc_check(tvbuff_t *src_tvb, slcompress *comp)
534 {
535   guint8 conn_index = ZERO;
536   guint8 offset     = ZERO;
537   gint   changes    = ZERO;
538
539   g_assert(src_tvb);
540   g_assert(comp);
541
542   if(tvb_length(src_tvb) < 3){
543     comp->flags |= SLF_TOSS;
544     return VJ_ERROR;
545   }
546
547   /* Read the change byte */
548   changes = tvb_get_guint8(src_tvb, offset++);
549
550   if(changes & NEW_C){    /* Read conn index */
551     conn_index = tvb_get_guint8(src_tvb, offset++);
552     if(conn_index > comp->rslot_limit) {
553       comp->flags |= SLF_TOSS;
554       return VJ_ERROR;
555     }
556     comp->flags &= ~SLF_TOSS;
557     comp->recv_current = conn_index;
558   } 
559   else {
560    if(comp->flags & SLF_TOSS)
561      return VJ_ERROR;
562   }
563   
564   return VJ_OK;
565
566
567 /* Decode the delta of a 32 bit header field */
568 static void 
569 decodel(tvbuff_t *tvb, guint32* offset, gint32 *val)
570 {
571   gint del = tvb_get_guint8(tvb, (*offset)++);
572   if(del == ZERO){
573     del = tvb_get_ntohs(tvb, *offset);
574     *offset= *offset + 2;
575   }
576   *val = htonl(ntohl(*val) + del);
577   return;
578 }
579
580 /* Decode the delta of a 16 bit header field */
581 static void 
582 decodes(tvbuff_t *tvb, guint32* offset, gint16 *val)
583 {
584   gint del = tvb_get_guint8(tvb, (*offset)++);
585   if(del == ZERO){
586     del = tvb_get_ntohs(tvb, *offset);
587     *offset= *offset + 2;
588   }
589   *val = htons(ntohs(*val) + del);
590   return;
591 }
592
593 /* For VJ uncompressed packet check if it is malformed */
594 static gint 
595 vjuc_check(tvbuff_t *tvb, slcompress *comp)
596 {
597   guint8 ihl   = ZERO;
598   gint   index = ZERO;
599
600   g_assert(comp);
601   g_assert(tvb);
602
603   if(tvb_length(tvb) < IP_HDR_LEN) {
604     comp->flags |= SLF_TOSS;
605     index = VJ_ERROR;
606   }
607   else {
608     /* Get the IP header length */
609     ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
610     ihl <<= 2;
611
612     /* Get connection index */
613     index = tvb_get_guint8(tvb, IP_FIELD_PROTOCOL);
614
615     /* Check connection number and IP header length field */
616     if(ihl < IP_HDR_LEN || index > comp->rslot_limit) {
617       comp->flags |= SLF_TOSS;
618       index = VJ_ERROR;
619     }
620   }
621
622   return index;
623
624
625 /* Setup the decompressed packet tvb for VJ uncompressed packets */
626 static gint 
627 vjuc_tvb_setup(tvbuff_t *tvb, 
628                tvbuff_t **dst_tvb, 
629                slcompress *comp)
630 {
631   guint8     ihl         = ZERO;
632   guint8     index       = ZERO;
633   gint       isize       = tvb_length(tvb);
634   guint8    *buffer      = NULL;
635   tvbuff_t  *orig_tvb    = NULL;
636   gint       orig_offset = 0;
637
638   g_assert(comp);
639   g_assert(tvb);
640
641   /* Get the IP header length */
642   ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
643   ihl <<= 2;
644   
645   /* Copy packet data to a buffer */
646   buffer   = g_malloc(isize);
647   tvb_memcpy(tvb, buffer, 0, isize);
648   buffer[IP_FIELD_PROTOCOL] = IP_PROTOCOL_TCP;
649
650   /* Compute checksum */
651   if (ip_csum(buffer, ihl) != ZERO) {
652     g_free(buffer);
653     comp->flags |= SLF_TOSS;
654     return VJ_ERROR;
655   }
656
657   /* 
658    * Form the new tvbuff. 
659    * Neither header checksum is recalculated
660    */
661   *dst_tvb = tvb_new_real_data(buffer, isize, isize, "VJ Uncompressed");
662   return VJ_OK;
663
664
665 /* For VJ uncompressed packets update the decompressor state */
666 static void 
667 vjuc_update_state(tvbuff_t *tvb, slcompress *comp, guint8 index)
668 {
669   cstate  *cs    = NULL;
670   guint8   ihl   = ZERO;
671   gint     isize = tvb_length(tvb);
672
673   g_assert(comp);
674   g_assert(tvb);
675
676   /* Get the IP header length */
677   ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
678   ihl <<= 2;
679   
680   /* Update local state */
681   cs = &comp->rstate[comp->recv_current = index];
682   comp->flags &= ~SLF_TOSS;
683   tvb_memcpy(tvb, (guint8 *)&cs->cs_ip, 0, IP_HDR_LEN);
684   tvb_memcpy(tvb, (guint8 *)&cs->cs_tcp, ihl, TCP_HDR_LEN);
685   if (ihl > IP_HDR_LEN)
686     tvb_memcpy(tvb, cs->cs_ipopt, sizeof(iphdr_type), ihl - IP_HDR_LEN);
687   if (cs->cs_tcp.doff > 5)
688     tvb_memcpy(tvb, cs->cs_tcpopt, ihl + sizeof(tcphdr_type), 
689                (cs->cs_tcp.doff - 5) * 4);
690   return;
691
692
693 /* Wraper for in_cksum function */
694 static guint16 
695 ip_csum(const guint8 * ptr, guint32 len)
696 {
697         vec_t cksum_vec[1];
698
699         cksum_vec[0].ptr = ptr;
700         cksum_vec[0].len = len;
701         return in_cksum(&cksum_vec[0], 1);
702 }