Add comments about nettl support.
[obnox/wireshark/wip.git] / packet-tcp.c
1 /* packet-tcp.c
2  * Routines for TCP packet disassembly
3  *
4  * $Id: packet-tcp.c,v 1.57 2000/02/15 21:03:15 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
36 #endif
37
38 #include <stdio.h>
39 #include <glib.h>
40 #include "globals.h"
41 #include "resolv.h"
42 #include "follow.h"
43
44 #ifdef NEED_SNPRINTF_H
45 # ifdef HAVE_STDARG_H
46 #  include <stdarg.h>
47 # else
48 #  include <varargs.h>
49 # endif
50 # include "snprintf.h"
51 #endif
52
53 #include "plugins.h"
54
55 #include "packet-bgp.h"
56 #include "packet-ip.h"
57 #include "packet-ftp.h"
58 #include "packet-giop.h"
59 #include "packet-http.h"
60 #include "packet-imap.h"
61 #include "packet-irc.h"
62 #include "packet-ldap.h"
63 #include "packet-lpd.h"
64 #include "packet-mapi.h"
65 #include "packet-nbns.h"
66 #include "packet-ncp.h"
67 #include "packet-nntp.h"
68 #include "packet-ntp.h"
69 #include "packet-pop.h"
70 #include "packet-pptp.h"
71 #include "packet-rpc.h"
72 #include "packet-rtsp.h"
73 #include "packet-srvloc.h"
74 #include "packet-tacacs.h"
75 #include "packet-telnet.h"
76 #include "packet-tns.h"
77 #include "packet-yhoo.h"
78
79 extern FILE* data_out_file;
80
81 static gchar info_str[COL_MAX_LEN];
82 static int   info_len;
83
84 static int proto_tcp = -1;
85 static int hf_tcp_srcport = -1;
86 static int hf_tcp_dstport = -1;
87 static int hf_tcp_port = -1;
88 static int hf_tcp_seq = -1;
89 static int hf_tcp_ack = -1;
90 static int hf_tcp_hdr_len = -1;
91 static int hf_tcp_flags = -1;
92 static int hf_tcp_flags_urg = -1;
93 static int hf_tcp_flags_ack = -1;
94 static int hf_tcp_flags_push = -1;
95 static int hf_tcp_flags_reset = -1;
96 static int hf_tcp_flags_syn = -1;
97 static int hf_tcp_flags_fin = -1;
98 static int hf_tcp_window_size = -1;
99 static int hf_tcp_checksum = -1;
100 static int hf_tcp_urgent_pointer = -1;
101
102 static gint ett_tcp = -1;
103 static gint ett_tcp_flags = -1;
104 static gint ett_tcp_options = -1;
105 static gint ett_tcp_option_sack = -1;
106
107 /* TCP Ports */
108
109 #define TCP_PORT_FTPDATA                20
110 #define TCP_PORT_FTP                    21
111 #define TCP_PORT_TELNET                 23
112 #define TCP_PORT_SMTP                   25
113 #define TCP_PORT_HTTP                   80
114 #define TCP_PORT_TACACS                 49
115 #define TCP_PORT_POP                    110
116 #define TCP_PORT_NNTP                   119
117 #define TCP_PORT_NTP                    123
118 #define TCP_PORT_NBSS                   139
119 #define TCP_PORT_IMAP                   143
120 #define TCP_PORT_BGP                    179
121 #define TCP_PORT_LDAP                   389
122 #define TCP_PORT_SRVLOC                 427
123 #define TCP_PORT_PRINTER                515
124 #define TCP_PORT_NCP                    524
125 #define TCP_PORT_RTSP                   554
126 #define TCP_PORT_MAPI                   1065
127 #define TCP_PORT_TNS                    1521
128 #define TCP_PORT_PPTP                   1723
129 #define TCP_PORT_PROXY_HTTP             3128
130 #define TCP_PORT_PROXY_ADMIN_HTTP       3132
131 #define TCP_PORT_YHOO                   5050
132 #define TCP_ALT_PORT_HTTP               8080
133 #define TCP_PORT_IRC                    6667
134         /* good candidate for dynamic port specification */
135
136 /* TCP structs and definitions */
137
138 typedef struct _e_tcphdr {
139   guint16 th_sport;
140   guint16 th_dport;
141   guint32 th_seq;
142   guint32 th_ack;
143   guint8  th_off_x2; /* combines th_off and th_x2 */
144   guint8  th_flags;
145 #define TH_FIN  0x01
146 #define TH_SYN  0x02
147 #define TH_RST  0x04
148 #define TH_PUSH 0x08
149 #define TH_ACK  0x10
150 #define TH_URG  0x20
151   guint16 th_win;
152   guint16 th_sum;
153   guint16 th_urp;
154 } e_tcphdr;
155
156 /*
157  *      TCP option
158  */
159  
160 #define TCPOPT_NOP              1       /* Padding */
161 #define TCPOPT_EOL              0       /* End of options */
162 #define TCPOPT_MSS              2       /* Segment size negotiating */
163 #define TCPOPT_WINDOW           3       /* Window scaling */
164 #define TCPOPT_SACK_PERM        4       /* SACK Permitted */
165 #define TCPOPT_SACK             5       /* SACK Block */
166 #define TCPOPT_ECHO             6
167 #define TCPOPT_ECHOREPLY        7
168 #define TCPOPT_TIMESTAMP        8       /* Better RTT estimations/PAWS */
169 #define TCPOPT_CC               11
170 #define TCPOPT_CCNEW            12
171 #define TCPOPT_CCECHO           13
172
173 /*
174  *     TCP option lengths
175  */
176
177 #define TCPOLEN_MSS            4
178 #define TCPOLEN_WINDOW         3
179 #define TCPOLEN_SACK_PERM      2
180 #define TCPOLEN_SACK_MIN       2
181 #define TCPOLEN_ECHO           6
182 #define TCPOLEN_ECHOREPLY      6
183 #define TCPOLEN_TIMESTAMP      10
184 #define TCPOLEN_CC             6
185 #define TCPOLEN_CCNEW          6
186 #define TCPOLEN_CCECHO         6
187
188 static void
189 tcp_info_append_uint(const char *abbrev, guint32 val) {
190   int add_len = 0;
191   
192   if (info_len > 0)
193   if(info_len > 0)
194     add_len = snprintf(&info_str[info_len], COL_MAX_LEN - info_len, " %s=%u",
195       abbrev, val);
196   if (add_len > 0)
197     info_len += add_len;
198 }
199
200 static void
201 dissect_tcpopt_maxseg(const ip_tcp_opt *optp, const u_char *opd,
202     int offset, guint optlen, proto_tree *opt_tree)
203 {
204   proto_tree_add_text(opt_tree, offset,      optlen,
205                         "%s: %u bytes", optp->name, pntohs(opd));
206   tcp_info_append_uint("MSS", pntohs(opd));
207 }
208
209 static void
210 dissect_tcpopt_wscale(const ip_tcp_opt *optp, const u_char *opd,
211     int offset, guint optlen, proto_tree *opt_tree)
212 {
213   proto_tree_add_text(opt_tree, offset,      optlen,
214                         "%s: %u bytes", optp->name, *opd);
215   tcp_info_append_uint("WS", *opd);
216 }
217
218 static void
219 dissect_tcpopt_sack(const ip_tcp_opt *optp, const u_char *opd,
220     int offset, guint optlen, proto_tree *opt_tree)
221 {
222   proto_tree *field_tree = NULL;
223   proto_item *tf;
224   guint leftedge, rightedge;
225
226   tf = proto_tree_add_text(opt_tree, offset,      optlen, "%s:", optp->name);
227   offset += 2;  /* skip past type and length */
228   optlen -= 2;  /* subtract size of type and length */
229   while (optlen > 0) {
230     if (field_tree == NULL) {
231       /* Haven't yet made a subtree out of this option.  Do so. */
232       field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
233     }
234     if (optlen < 4) {
235       proto_tree_add_text(field_tree, offset,      optlen,
236         "(suboption would go past end of option)");
237       break;
238     }
239     /* XXX - check whether it goes past end of packet */
240     leftedge = pntohl(opd);
241     opd += 4;
242     optlen -= 4;
243     if (optlen < 4) {
244       proto_tree_add_text(field_tree, offset,      optlen,
245         "(suboption would go past end of option)");
246       break;
247     }
248     /* XXX - check whether it goes past end of packet */
249     rightedge = pntohl(opd);
250     opd += 4;
251     optlen -= 4;
252     proto_tree_add_text(field_tree, offset,      8,
253         "left edge = %u, right edge = %u", leftedge, rightedge);
254     tcp_info_append_uint("SLE", leftedge);
255     tcp_info_append_uint("SRE", rightedge);
256     offset += 8;
257   }
258 }
259
260 static void
261 dissect_tcpopt_echo(const ip_tcp_opt *optp, const u_char *opd,
262     int offset, guint optlen, proto_tree *opt_tree)
263 {
264   proto_tree_add_text(opt_tree, offset,      optlen,
265                         "%s: %u", optp->name, pntohl(opd));
266   tcp_info_append_uint("ECHO", pntohl(opd));
267 }
268
269 static void
270 dissect_tcpopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
271     int offset, guint optlen, proto_tree *opt_tree)
272 {
273   proto_tree_add_text(opt_tree, offset,      optlen,
274     "%s: tsval %u, tsecr %u", optp->name, pntohl(opd), pntohl(opd + 4));
275   tcp_info_append_uint("TSV", pntohl(opd));
276   tcp_info_append_uint("TSER", pntohl(opd + 4));
277 }
278
279 static void
280 dissect_tcpopt_cc(const ip_tcp_opt *optp, const u_char *opd,
281     int offset, guint optlen, proto_tree *opt_tree)
282 {
283   proto_tree_add_text(opt_tree, offset,      optlen,
284                         "%s: %u", optp->name, pntohl(opd));
285   tcp_info_append_uint("CC", pntohl(opd));
286 }
287
288 static const ip_tcp_opt tcpopts[] = {
289   {
290     TCPOPT_EOL,
291     "EOL",
292     NULL,
293     NO_LENGTH,
294     0,
295     NULL,
296   },
297   {
298     TCPOPT_NOP,
299     "NOP",
300     NULL,
301     NO_LENGTH,
302     0,
303     NULL,
304   },
305   {
306     TCPOPT_MSS,
307     "Maximum segment size",
308     NULL,
309     FIXED_LENGTH,
310     TCPOLEN_MSS,
311     dissect_tcpopt_maxseg
312   },
313   {
314     TCPOPT_WINDOW,
315     "Window scale",
316     NULL,
317     FIXED_LENGTH,
318     TCPOLEN_WINDOW,
319     dissect_tcpopt_wscale
320   },
321   {
322     TCPOPT_SACK_PERM,
323     "SACK permitted",
324     NULL,
325     FIXED_LENGTH,
326     TCPOLEN_SACK_PERM,
327     NULL,
328   },
329   {
330     TCPOPT_SACK,
331     "SACK",
332     &ett_tcp_option_sack,
333     VARIABLE_LENGTH,
334     TCPOLEN_SACK_MIN,
335     dissect_tcpopt_sack
336   },
337   {
338     TCPOPT_ECHO,
339     "Echo",
340     NULL,
341     FIXED_LENGTH,
342     TCPOLEN_ECHO,
343     dissect_tcpopt_echo
344   },
345   {
346     TCPOPT_ECHOREPLY,
347     "Echo reply",
348     NULL,
349     FIXED_LENGTH,
350     TCPOLEN_ECHOREPLY,
351     dissect_tcpopt_echo
352   },
353   {
354     TCPOPT_TIMESTAMP,
355     "Time stamp",
356     NULL,
357     FIXED_LENGTH,
358     TCPOLEN_TIMESTAMP,
359     dissect_tcpopt_timestamp
360   },
361   {
362     TCPOPT_CC,
363     "CC",
364     NULL,
365     FIXED_LENGTH,
366     TCPOLEN_CC,
367     dissect_tcpopt_cc
368   },
369   {
370     TCPOPT_CCNEW,
371     "CC.NEW",
372     NULL,
373     FIXED_LENGTH,
374     TCPOPT_CCNEW,
375     dissect_tcpopt_cc
376   },
377   {
378     TCPOPT_CCECHO,
379     "CC.ECHO",
380     NULL,
381     FIXED_LENGTH,
382     TCPOLEN_CCECHO,
383     dissect_tcpopt_cc
384   }
385 };
386
387 #define N_TCP_OPTS      (sizeof tcpopts / sizeof tcpopts[0])
388
389 /* TCP flags flag */
390 static const true_false_string flags_set_truth = {
391   "Set",
392   "Not set"
393 };
394
395 void
396 dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
397   e_tcphdr   th;
398   proto_tree *tcp_tree = NULL, *field_tree = NULL;
399   proto_item *ti, *tf;
400   gchar      flags[64] = "<None>";
401   gchar     *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG"};
402   gint       fpos = 0, i;
403   guint      bpos;
404   guint      hlen;
405   guint      optlen;
406   guint      packet_max = pi.len;
407
408   /* To do: Check for {cap len,pkt len} < struct len */
409   /* Avoids alignment problems on many architectures. */
410   memcpy(&th, &pd[offset], sizeof(e_tcphdr));
411   th.th_sport = ntohs(th.th_sport);
412   th.th_dport = ntohs(th.th_dport);
413   th.th_win   = ntohs(th.th_win);
414   th.th_sum   = ntohs(th.th_sum);
415   th.th_urp   = ntohs(th.th_urp);
416   th.th_seq   = ntohl(th.th_seq);
417   th.th_ack   = ntohl(th.th_ack);
418   
419   info_len = 0;
420
421   if (check_col(fd, COL_PROTOCOL) || tree) {  
422     for (i = 0; i < 6; i++) {
423       bpos = 1 << i;
424       if (th.th_flags & bpos) {
425         if (fpos) {
426           strcpy(&flags[fpos], ", ");
427           fpos += 2;
428         }
429         strcpy(&flags[fpos], fstr[i]);
430         fpos += 3;
431       }
432     }
433     flags[fpos] = '\0';
434   }
435   
436   hlen = hi_nibble(th.th_off_x2) * 4;  /* TCP header length, in bytes */
437
438   if (check_col(fd, COL_PROTOCOL))
439     col_add_str(fd, COL_PROTOCOL, "TCP");
440   if (check_col(fd, COL_INFO)) {
441     /* Copy the data into info_str in case one of the option handling
442        routines needs to append to it. */
443     if (th.th_flags & TH_URG)
444       info_len = snprintf(info_str, COL_MAX_LEN, "%s > %s [%s] Seq=%u Ack=%u Win=%u Urg=%u",
445         get_tcp_port(th.th_sport), get_tcp_port(th.th_dport), flags,
446         th.th_seq, th.th_ack, th.th_win, th.th_urp);
447     else
448       info_len = snprintf(info_str, COL_MAX_LEN, "%s > %s [%s] Seq=%u Ack=%u Win=%u",
449         get_tcp_port(th.th_sport), get_tcp_port(th.th_dport), flags,
450         th.th_seq, th.th_ack, th.th_win);
451     /* The info column is actually written after the options are decoded */
452   }
453   
454   if (tree) {
455     ti = proto_tree_add_item_format(tree, proto_tcp, offset, hlen, NULL, "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u), Seq: %u, Ack: %u", get_tcp_port(th.th_sport), th.th_sport, get_tcp_port(th.th_dport), th.th_dport, th.th_seq, th.th_ack);
456     tcp_tree = proto_item_add_subtree(ti, ett_tcp);
457     proto_tree_add_item_format(tcp_tree, hf_tcp_srcport, offset, 2, th.th_sport,
458         "Source port: %s (%u)", get_tcp_port(th.th_sport), th.th_sport);
459     proto_tree_add_item_format(tcp_tree, hf_tcp_dstport, offset + 2, 2, th.th_dport,
460         "Destination port: %s (%u)", get_tcp_port(th.th_dport), th.th_dport);
461     proto_tree_add_item_hidden(tcp_tree, hf_tcp_port, offset, 2, th.th_sport);
462     proto_tree_add_item_hidden(tcp_tree, hf_tcp_port, offset + 2, 2, th.th_dport);
463     proto_tree_add_item(tcp_tree, hf_tcp_seq, offset + 4, 4, th.th_seq);
464     if (th.th_flags & TH_ACK)
465       proto_tree_add_item(tcp_tree, hf_tcp_ack, offset + 8, 4, th.th_ack);
466     proto_tree_add_item_format(tcp_tree, hf_tcp_hdr_len, offset + 12, 1, hlen,
467         "Header length: %u bytes", hlen);
468     tf = proto_tree_add_item_format(tcp_tree, hf_tcp_flags, offset + 13, 1,
469         th.th_flags, "Flags: 0x%04x (%s)", th.th_flags, flags);
470     field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
471     proto_tree_add_item(field_tree, hf_tcp_flags_urg, offset + 13, 1, th.th_flags);
472     proto_tree_add_item(field_tree, hf_tcp_flags_ack, offset + 13, 1, th.th_flags);
473     proto_tree_add_item(field_tree, hf_tcp_flags_push, offset + 13, 1, th.th_flags);
474     proto_tree_add_item(field_tree, hf_tcp_flags_reset, offset + 13, 1, th.th_flags);
475     proto_tree_add_item(field_tree, hf_tcp_flags_syn, offset + 13, 1, th.th_flags);
476     proto_tree_add_item(field_tree, hf_tcp_flags_fin, offset + 13, 1, th.th_flags);
477     proto_tree_add_item(tcp_tree, hf_tcp_window_size, offset + 14, 2, th.th_win);
478     proto_tree_add_item(tcp_tree, hf_tcp_checksum, offset + 16, 2, th.th_sum);
479     if (th.th_flags & TH_URG)
480       proto_tree_add_item(tcp_tree, hf_tcp_urgent_pointer, offset + 18, 2, th.th_urp);
481   }
482
483   /* Decode TCP options, if any. */
484   if (tree  && hlen > sizeof (e_tcphdr)) {
485     /* There's more than just the fixed-length header.  Decode the
486        options. */
487     optlen = hlen - sizeof (e_tcphdr); /* length of options, in bytes */
488     tf = proto_tree_add_text(tcp_tree, offset +  20, optlen,
489       "Options: (%d bytes)", optlen);
490     field_tree = proto_item_add_subtree(tf, ett_tcp_options);
491     dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
492       tcpopts, N_TCP_OPTS, TCPOPT_EOL, field_tree);
493   }
494
495   if (check_col(fd, COL_INFO))
496     col_add_str(fd, COL_INFO, info_str);
497
498   /* Skip over header + options */
499   offset += hlen;
500
501   pi.ptype = PT_TCP;
502   pi.srcport = th.th_sport;
503   pi.destport = th.th_dport;
504   
505   /* Check the packet length to see if there's more data
506      (it could be an ACK-only packet) */
507   if (packet_max > offset) {
508
509     /* try to apply the plugins */
510 #ifdef HAVE_PLUGINS
511     plugin *pt_plug = plugin_list;
512
513     if (pt_plug) {
514       while (pt_plug) {
515         if (pt_plug->enabled && !strcmp(pt_plug->protocol, "tcp") &&
516             tree && dfilter_apply(pt_plug->filter, tree, pd)) {
517           pt_plug->dissector(pd, offset, fd, tree);
518           goto reas;
519         }
520         pt_plug = pt_plug->next;
521       }
522     }
523 #endif
524
525     /* ONC RPC.  We can't base this on anything in the TCP header; we have
526        to look at the payload.  If "dissect_rpc()" returns TRUE, it was
527        an RPC packet, otherwise it's some other type of packet. */
528     if (dissect_rpc(pd, offset, fd, tree))
529       goto reas;
530
531     /* XXX - this should be handled the way UDP handles this, with a table
532        of port numbers to which stuff can be added */
533 #define PORT_IS(port)   (th.th_sport == port || th.th_dport == port)
534     if (PORT_IS(TCP_PORT_PRINTER))
535       dissect_lpd(pd, offset, fd, tree);
536     else if (PORT_IS(TCP_PORT_TELNET)) {
537       pi.match_port = TCP_PORT_TELNET;
538       dissect_telnet(pd, offset, fd, tree);
539     } else if (PORT_IS(TCP_PORT_FTPDATA)) {
540       pi.match_port = TCP_PORT_FTPDATA;
541       dissect_ftpdata(pd, offset, fd, tree);
542     } else if (PORT_IS(TCP_PORT_FTP)) {
543       pi.match_port = TCP_PORT_FTP;
544       dissect_ftp(pd, offset, fd, tree);
545     } else if (PORT_IS(TCP_PORT_POP)) {
546       pi.match_port = TCP_PORT_POP;
547       dissect_pop(pd, offset, fd, tree);
548     } else if (PORT_IS(TCP_PORT_IMAP)) {
549       pi.match_port = TCP_PORT_IMAP;
550       dissect_imap(pd, offset, fd, tree);
551     } else if (PORT_IS(TCP_PORT_NNTP)) {
552       pi.match_port = TCP_PORT_NNTP;
553       dissect_nntp(pd, offset, fd, tree);
554     } else if (PORT_IS(TCP_PORT_NTP)) {
555       pi.match_port = TCP_PORT_NTP;
556       dissect_ntp(pd, offset, fd, tree);
557     } else if (PORT_IS(TCP_PORT_PPTP)) {
558       pi.match_port = TCP_PORT_PPTP;
559       dissect_pptp(pd, offset, fd, tree);
560     } else if (PORT_IS(TCP_PORT_HTTP) || PORT_IS(TCP_ALT_PORT_HTTP)
561             || PORT_IS(631) || PORT_IS(TCP_PORT_PROXY_HTTP)
562             || PORT_IS(TCP_PORT_PROXY_ADMIN_HTTP))
563       dissect_http(pd, offset, fd, tree);
564     else if (PORT_IS(TCP_PORT_NBSS)) {
565       pi.match_port = TCP_PORT_NBSS;
566       dissect_nbss(pd, offset, fd, tree);
567     } else if (PORT_IS(TCP_PORT_RTSP))
568       dissect_rtsp(pd, offset, fd, tree);
569     else if (PORT_IS(TCP_PORT_BGP)) {
570       pi.match_port = TCP_PORT_BGP;
571       dissect_bgp(pd, offset, fd, tree);
572     } else if (PORT_IS(TCP_PORT_TACACS)) {
573       pi.match_port = TCP_PORT_TACACS;
574       dissect_tacplus(pd, offset, fd, tree);
575     } else if (PORT_IS(TCP_PORT_MAPI)) {
576       pi.match_port = TCP_PORT_MAPI;
577       dissect_mapi(pd, offset, fd, tree);
578     } else if (PORT_IS(TCP_PORT_TNS)) {
579       pi.match_port = TCP_PORT_TNS;
580       dissect_tns(pd, offset, fd, tree);
581     } else if (PORT_IS(TCP_PORT_IRC)) {
582       pi.match_port = TCP_PORT_IRC;
583       dissect_irc(pd, offset, fd, tree);
584     } else if (PORT_IS(TCP_PORT_LDAP)) {
585       pi.match_port = TCP_PORT_LDAP;
586       dissect_ldap(pd, offset, fd, tree);
587     } else if (PORT_IS(TCP_PORT_SRVLOC)) {
588       pi.match_port = TCP_PORT_SRVLOC;
589       dissect_srvloc(pd, offset, fd, tree);
590     } else if (PORT_IS(TCP_PORT_NCP)) {
591       pi.match_port = TCP_PORT_NCP;
592       dissect_ncp(pd, offset, fd, tree); /* XXX -- need to handle nw_server_address */
593     } else {
594         /* check existence of high level protocols */
595
596         if (memcmp(&pd[offset], "GIOP",  4) == 0) {
597           dissect_giop(pd, offset, fd, tree);
598         }
599         else if ( PORT_IS(TCP_PORT_YHOO) && 
600                 (memcmp(&pd[offset], "YPNS",  4) == 0 ||
601                         memcmp(&pd[offset], "YHOO",  4) == 0 )) {
602           dissect_yhoo(pd, offset, fd, tree);
603         }
604         else {
605           dissect_data(pd, offset, fd, tree);
606         }
607     }
608   }
609
610 reas:
611  
612   if( data_out_file ) {
613     reassemble_tcp( th.th_seq,          /* sequence number */
614         ( pi.len - offset ),            /* data length */
615         ( pd+offset ),                  /* data */
616         ( pi.captured_len - offset ),   /* captured data length */
617         ( th.th_flags & TH_SYN ),       /* is syn set? */
618         &pi.net_src,
619         &pi.net_dst,
620         pi.srcport,
621         pi.destport,
622         fd->rel_secs,
623         fd->rel_usecs);
624   }
625 }
626
627 void
628 proto_register_tcp(void)
629 {
630         static hf_register_info hf[] = {
631
632                 { &hf_tcp_srcport,
633                 { "Source Port",                "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
634                         "" }},
635
636                 { &hf_tcp_dstport,
637                 { "Destination Port",           "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
638                         "" }},
639
640                 { &hf_tcp_port,
641                 { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
642                         "" }},
643
644                 { &hf_tcp_seq,
645                 { "Sequence number",            "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
646                         "" }},
647
648                 { &hf_tcp_ack,
649                 { "Acknowledgement number",     "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
650                         "" }},
651
652                 { &hf_tcp_hdr_len,
653                 { "Header Length",              "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
654                         "" }},
655
656                 { &hf_tcp_flags,
657                 { "Flags",                      "tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
658                         "" }},
659
660                 { &hf_tcp_flags_urg,
661                 { "Urgent",                     "tcp.flags.urg", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_URG,
662                         "" }},
663
664                 { &hf_tcp_flags_ack,
665                 { "Acknowledgment",             "tcp.flags.ack", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ACK,
666                         "" }},
667
668                 { &hf_tcp_flags_push,
669                 { "Push",                       "tcp.flags.push", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_PUSH,
670                         "" }},
671
672                 { &hf_tcp_flags_reset,
673                 { "Reset",                      "tcp.flags.reset", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_RST,
674                         "" }},
675
676                 { &hf_tcp_flags_syn,
677                 { "Syn",                        "tcp.flags.syn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_SYN,
678                         "" }},
679
680                 { &hf_tcp_flags_fin,
681                 { "Fin",                        "tcp.flags.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_FIN,
682                         "" }},
683
684                 { &hf_tcp_window_size,
685                 { "Window size",                "tcp.window_size", FT_UINT16, BASE_DEC, NULL, 0x0,
686                         "" }},
687
688                 { &hf_tcp_checksum,
689                 { "Checksum",                   "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
690                         "" }},
691
692                 { &hf_tcp_urgent_pointer,
693                 { "Urgent pointer",             "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
694                         "" }},
695         };
696         static gint *ett[] = {
697                 &ett_tcp,
698                 &ett_tcp_flags,
699                 &ett_tcp_options,
700                 &ett_tcp_option_sack,
701         };
702
703         proto_tcp = proto_register_protocol ("Transmission Control Protocol", "tcp");
704         proto_register_field_array(proto_tcp, hf, array_length(hf));
705         proto_register_subtree_array(ett, array_length(ett));
706 }