dsniff  2.4b2
About: A collection of tools for network auditing
  Fossies Dox: dsniff-2.4b2.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

tcp_raw.c
Go to the documentation of this file.
1 /*
2  * tcp_raw.c
3  *
4  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
5  *
6  * $Id: tcp_raw.c,v 1.10 2001/03/15 08:33:04 dugsong Exp $
7  */
8 
9 #include "config.h"
10 
11 #include <sys/types.h>
12 #include <sys/uio.h>
13 #include <netinet/in.h>
14 
15 #include <time.h>
16 #include <err.h>
17 #include <libnet.h>
18 #include "options.h"
19 #include "tcp_raw.h"
20 
21 struct tha {
24  u_short port;
25 };
26 
27 struct tcp_seg {
28  u_int32_t seq;
29  u_char *data;
30  int len;
31 };
32 
33 struct tcp_conn {
34  struct tha tha;
35  time_t mtime;
36  struct tcp_seg *seg;
37  int segcnt;
38  int segmax;
39  struct tcp_conn *next;
40 };
41 
42 #define TCP_TIMEOUT 60
43 #define TCP_HASHSIZE 919
44 
45 static struct tcp_conn conntab[TCP_HASHSIZE];
46 
47 static int
48 tcp_seg_compare(const void *a, const void *b)
49 {
50  struct tcp_seg *sa, *sb;
51 
52  sa = (struct tcp_seg *) a;
53  sb = (struct tcp_seg *) b;
54 
55  if (sa->seq < sb->seq)
56  return (-1);
57  else if (sa->seq > sb->seq)
58  return (1);
59  else return (0);
60 }
61 
62 static void
63 tcp_raw_delete(struct tcp_conn *conn)
64 {
65  struct tcp_conn *hold;
66  int i;
67 
68  if (conn->next != NULL) {
69  for (i = 0; i < conn->segcnt; i++) {
70  if (conn->seg[i].data)
71  free(conn->seg[i].data);
72  }
73  free(conn->seg);
74  conn->seg = NULL;
75  conn->segcnt = conn->segmax = 0;
76 
77  if (conn->next->next != NULL) {
78  hold = conn->next;
79  *conn = *conn->next;
80  free(hold);
81  }
82  else {
83  free(conn->next);
84  conn->next = NULL;
85  }
86  }
87 }
88 
89 static struct iovec *
90 tcp_raw_reassemble(struct tcp_conn *conn, int minlen)
91 {
92  struct iovec *iov;
93  int i, len;
94 
95  len = 0;
96 
97  for (i = 0; i < conn->segcnt; i++)
98  len += conn->seg[i].len;
99 
100  if (len < minlen)
101  return (NULL);
102 
103  if ((iov = (struct iovec *) malloc(sizeof(*iov))) == NULL)
104  err(1, "tcp_raw_reassemble: malloc");
105 
106  if ((iov->iov_base = (u_char *) malloc(len)) == NULL)
107  err(1, "tcp_raw_reassemble: malloc");
108 
109  iov->iov_len = 0;
110 
111  qsort(conn->seg, conn->segcnt, sizeof(*conn->seg), tcp_seg_compare);
112 
113  for (i = 0; i < conn->segcnt; i++) {
114  len = conn->seg[i].len;
115  memcpy(iov->iov_base + iov->iov_len, conn->seg[i].data, len);
116  iov->iov_len += len;
117  }
118  return (iov);
119 }
120 
121 struct iovec *
122 tcp_raw_input(struct libnet_ipv4_hdr *ip, struct libnet_tcp_hdr *tcp, int len)
123 {
124  struct tha tha;
125  struct tcp_conn *conn;
126  struct tcp_seg seg;
127  struct iovec *iov;
128  u_short cksum;
129  u_char *buf;
130  libnet_t *l;
131  char errbuf[LIBNET_ERRBUF_SIZE];
132 
133  l = libnet_init(
134  LIBNET_RAW4, /* or LIBNET_LINK or LIBNET_RAW6 */
135  NULL, /* or device if you using LIBNET_LINK */
136  errbuf);
137 
138 
139  int tcp_hl = tcp->th_off * 4;
140 
141  /* Verify TCP checksum. */
142  cksum = tcp->th_sum;
143 
144  libnet_do_checksum(l, (u_char *) ip, IPPROTO_TCP, len);
145 
146  if (cksum != tcp->th_sum)
147  return (NULL);
148 
149  tha.src = ip->ip_src.s_addr;
150  tha.dst = ip->ip_dst.s_addr;
151  tha.port = ntohs(tcp->th_sport) << 16 | ntohs(tcp->th_dport);
152 
153  buf = (u_char *)tcp + tcp_hl;
154  len -= tcp_hl;
155  iov = NULL;
156 
157  /* Find half-duplex stream associated with this segment. */
158  for (conn = &conntab[tha.port % TCP_HASHSIZE];
159  conn->next != NULL; conn = conn->next) {
160  if (memcmp((char *)&tha, (char *)&conn->tha, sizeof(tha)) == 0)
161  break;
162  }
163  /* Process by TCP flags. */
164  if (conn->next == NULL) {
165  if (tcp->th_flags & TH_SYN) {
166  if (conn->next == NULL &&
167  (conn->next = (struct tcp_conn *)
168  calloc(1, sizeof(*conn))) == NULL) {
169  err(1, "tcp_raw_input: calloc");
170  }
171  conn->tha = tha;
172 
173  if (conn->seg == NULL &&
174  (conn->seg = (struct tcp_seg *)
175  malloc(sizeof(seg) * 128)) == NULL) {
176  err(1, "tcp_raw_input: malloc");
177  }
178  conn->segmax = 128;
179  }
180  }
181  else if (tcp->th_flags & TH_FIN || tcp->th_flags & TH_RST) {
182  iov = tcp_raw_reassemble(conn, 1);
183  }
184  else if (tcp->th_flags & TH_ACK && len > 0) {
185  seg.seq = ntohl(tcp->th_seq);
186  if (bsearch(&seg, conn->seg, conn->segcnt,
187  sizeof(seg), tcp_seg_compare) == NULL) {
188 
189  if ((seg.data = (u_char *) malloc(len)) == NULL)
190  err(1, "tcp_raw_input: malloc");
191  memcpy(seg.data, buf, len);
192  seg.len = len;
193 
194  if (conn->segcnt == conn->segmax) {
195  if ((conn->seg = (struct tcp_seg *)
196  realloc(conn->seg, (conn->segmax * 2) *
197  sizeof(seg))) == NULL)
198  err(1, "tcp_raw_input: realloc");
199  conn->segmax *= 2;
200  }
201  conn->seg[conn->segcnt++] = seg;
202 
203  iov = tcp_raw_reassemble(conn, Opt_snaplen);
204  }
205  }
206  conn->mtime = time(NULL);
207 
208  /* If we successfully reassembled the stream, delete its entry. */
209  if (iov != NULL) {
210  tcp_raw_delete(conn);
211  }
212  return (iov);
213 }
214 
215 void
216 tcp_raw_timeout(int timeout, tcp_raw_callback_t callback)
217 {
218  struct tcp_conn *conn;
219  struct iovec *iov;
220  time_t now;
221  int i;
222 
223  now = time(NULL);
224 
225  for (i = 0; i < TCP_HASHSIZE; i++) {
226  for (conn = &conntab[i]; conn != NULL && conn->next != NULL;
227  conn = conn->next) {
228  if (now - conn->mtime > timeout) {
229 
230  iov = tcp_raw_reassemble(conn, 1);
231 
232  if (iov != NULL) {
233  callback(conn->tha.src, conn->tha.dst,
234  conn->tha.port >> 16,
235  conn->tha.port & 0xffff,
236  iov->iov_base, iov->iov_len);
237 
238  free(iov->iov_base);
239  free(iov);
240  }
241  tcp_raw_delete(conn);
242  }
243  }
244  }
245 }
246 
tcp_raw_callback_t
void(* tcp_raw_callback_t)(in_addr_t src, in_addr_t dst, u_short sport, u_short dport, u_char *buf, int len)
Definition: tcp_raw.h:13
now
static clock_t now
Definition: sshow.c:79
tcp_conn::mtime
time_t mtime
Definition: tcp_raw.c:35
tcp_seg
Definition: tcp_raw.c:27
options.h
tha::port
u_short port
Definition: tcp_raw.c:24
buf
static u_char buf[BUFSIZ]
Definition: filenamesnarf.c:29
tha::src
u_int32_t src
Definition: tcp_raw.c:22
l
libnet_t * l
Definition: arpspoof.c:34
errbuf
char errbuf[LIBNET_ERRBUF_SIZE]
Definition: arpspoof.c:35
tcp_raw_delete
static void tcp_raw_delete(struct tcp_conn *conn)
Definition: tcp_raw.c:63
tcp_seg_compare
static int tcp_seg_compare(const void *a, const void *b)
Definition: tcp_raw.c:48
tcp_conn::segmax
int segmax
Definition: tcp_raw.c:38
tcp_raw_reassemble
static struct iovec * tcp_raw_reassemble(struct tcp_conn *conn, int minlen)
Definition: tcp_raw.c:90
tcp_conn::segcnt
int segcnt
Definition: tcp_raw.c:37
tcp_raw.h
tha
Definition: tcp_raw.c:21
err.h
buf
Definition: buf.h:14
err
void err(int eval, const char *fmt,...)
Definition: err.c:47
tcp_conn
Definition: tcp_raw.c:33
conntab
static struct tcp_conn conntab[919]
Definition: tcp_raw.c:45
tcp_conn::tha
struct tha tha
Definition: tcp_raw.c:34
Opt_snaplen
int Opt_snaplen
Definition: dsniff.c:42
tcp_conn::next
struct tcp_conn * next
Definition: tcp_raw.c:39
tha::dst
u_int32_t dst
Definition: tcp_raw.c:23
TCP_HASHSIZE
#define TCP_HASHSIZE
Definition: tcp_raw.c:43
in_addr_t
#define in_addr_t
Definition: config.h:32
tcp_seg::seq
u_int32_t seq
Definition: tcp_raw.c:28
memcmp
int memcmp(void *s1, void *s2, size_t n) const
Definition: memcmp.c:44
config.h
tcp_conn::seg
struct tcp_seg * seg
Definition: tcp_raw.c:36
if
if(screen !=save_screen)
Definition: vroot.h:71
tcp_raw_input
struct iovec * tcp_raw_input(struct libnet_ipv4_hdr *ip, struct libnet_tcp_hdr *tcp, int len)
Definition: tcp_raw.c:122
tcp_raw_timeout
void tcp_raw_timeout(int timeout, tcp_raw_callback_t callback)
Definition: tcp_raw.c:216
tcp_seg::data
u_char * data
Definition: tcp_raw.c:29
tcp_seg::len
int len
Definition: tcp_raw.c:30