1/* 2 * Copyright (c) 2003 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29extern "C" { 30#include <pcap.h> 31} 32 33#include <dnet.h> 34 35#include <arpa/inet.h> 36 37#include <sys/ioctl.h> 38#include <sys/types.h> 39#include <sys/socket.h> 40 41#include <netinet/in.h> 42#include <netinet/tcp.h> 43 44#include <errno.h> 45#include <fcntl.h> 46#include <libgen.h> 47#include <netdb.h> 48#include <poll.h> 49#include <signal.h> 50#include <unistd.h> 51 52#include <list> 53#include <string> 54 55#include "base/cprintf.hh" 56 57#define panic(arg...) \ 58 do { cprintf("Panic: " arg); exit(1); } while (0) 59 60char *program = "ethertap"; 61void 62usage() 63{ 64 cprintf( 65 "usage: \n" 66 "\t%s [-b bufsize] [-d] [-f filter] [-p port] [-v] <device> <host>\n" 67 "\t%s [-b bufsize] [-d] [-f filter] [-l] [-p port] [-v] <device>\n", 68 program, program); 69 exit(2); 70} 71 72int verbose = 0; 73#define DPRINTF(args...) do { \
| 1/* 2 * Copyright (c) 2003 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29extern "C" { 30#include <pcap.h> 31} 32 33#include <dnet.h> 34 35#include <arpa/inet.h> 36 37#include <sys/ioctl.h> 38#include <sys/types.h> 39#include <sys/socket.h> 40 41#include <netinet/in.h> 42#include <netinet/tcp.h> 43 44#include <errno.h> 45#include <fcntl.h> 46#include <libgen.h> 47#include <netdb.h> 48#include <poll.h> 49#include <signal.h> 50#include <unistd.h> 51 52#include <list> 53#include <string> 54 55#include "base/cprintf.hh" 56 57#define panic(arg...) \ 58 do { cprintf("Panic: " arg); exit(1); } while (0) 59 60char *program = "ethertap"; 61void 62usage() 63{ 64 cprintf( 65 "usage: \n" 66 "\t%s [-b bufsize] [-d] [-f filter] [-p port] [-v] <device> <host>\n" 67 "\t%s [-b bufsize] [-d] [-f filter] [-l] [-p port] [-v] <device>\n", 68 program, program); 69 exit(2); 70} 71 72int verbose = 0; 73#define DPRINTF(args...) do { \
|
74 if (verbose > 1) \
| 74 if (verbose >= 1) \
|
75 cprintf(args); \ 76} while (0) 77 78#define DDUMP(args...) do { \
| 75 cprintf(args); \ 76} while (0) 77 78#define DDUMP(args...) do { \
|
79 if (verbose > 2) \
| 79 if (verbose >= 2) \
|
80 dump((const u_char *)args); \ 81} while (0) 82 83void 84dump(const u_char *data, int len) 85{ 86 int c, i, j; 87 88 for (i = 0; i < len; i += 16) { 89 cprintf("%08x ", i); 90 c = len - i; 91 if (c > 16) c = 16; 92 93 for (j = 0; j < c; j++) { 94 cprintf("%02x ", data[i + j] & 0xff); 95 if ((j & 0xf) == 7 && j > 0) 96 cprintf(" "); 97 } 98 99 for (; j < 16; j++) 100 cprintf(" "); 101 cprintf(" "); 102 103 for (j = 0; j < c; j++) { 104 int ch = data[i + j] & 0x7f; 105 cprintf("%c", (char)(isprint(ch) ? ch : ' ')); 106 } 107 108 cprintf("\n"); 109 110 if (c < 16) 111 break; 112 } 113} 114 115bool quit = false; 116void 117quit_now(int sigtype) 118{ 119 DPRINTF("User requested exit\n"); 120 quit = true; 121} 122 123 124int 125Socket(int reuse) 126{ 127 int fd = ::socket(PF_INET, SOCK_STREAM, 0); 128 if (fd < 0)
| 80 dump((const u_char *)args); \ 81} while (0) 82 83void 84dump(const u_char *data, int len) 85{ 86 int c, i, j; 87 88 for (i = 0; i < len; i += 16) { 89 cprintf("%08x ", i); 90 c = len - i; 91 if (c > 16) c = 16; 92 93 for (j = 0; j < c; j++) { 94 cprintf("%02x ", data[i + j] & 0xff); 95 if ((j & 0xf) == 7 && j > 0) 96 cprintf(" "); 97 } 98 99 for (; j < 16; j++) 100 cprintf(" "); 101 cprintf(" "); 102 103 for (j = 0; j < c; j++) { 104 int ch = data[i + j] & 0x7f; 105 cprintf("%c", (char)(isprint(ch) ? ch : ' ')); 106 } 107 108 cprintf("\n"); 109 110 if (c < 16) 111 break; 112 } 113} 114 115bool quit = false; 116void 117quit_now(int sigtype) 118{ 119 DPRINTF("User requested exit\n"); 120 quit = true; 121} 122 123 124int 125Socket(int reuse) 126{ 127 int fd = ::socket(PF_INET, SOCK_STREAM, 0); 128 if (fd < 0)
|
129 panic("Can't create socket!");
| 129 panic("Can't create socket!\n");
|
130 131 if (reuse) { 132 int i = 1; 133 if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, 134 sizeof(i)) < 0)
| 130 131 if (reuse) { 132 int i = 1; 133 if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, 134 sizeof(i)) < 0)
|
135 panic("setsockopt() SO_REUSEADDR failed!");
| 135 panic("setsockopt() SO_REUSEADDR failed!\n");
|
136 } 137 138 return fd; 139} 140 141void 142Listen(int fd, int port) 143{ 144 struct sockaddr_in sockaddr; 145 sockaddr.sin_family = PF_INET; 146 sockaddr.sin_addr.s_addr = INADDR_ANY; 147 148 sockaddr.sin_port = htons(port); 149 int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)); 150 if (ret == -1)
| 136 } 137 138 return fd; 139} 140 141void 142Listen(int fd, int port) 143{ 144 struct sockaddr_in sockaddr; 145 sockaddr.sin_family = PF_INET; 146 sockaddr.sin_addr.s_addr = INADDR_ANY; 147 148 sockaddr.sin_port = htons(port); 149 int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)); 150 if (ret == -1)
|
151 panic("bind() failed!");
| 151 panic("bind() failed!\n");
|
152 153 if (::listen(fd, 1) == -1)
| 152 153 if (::listen(fd, 1) == -1)
|
154 panic("listen() failed!");
| 154 panic("listen() failed!\n");
|
155} 156 157// Open a connection. Accept will block, so if you don't want it to, 158// make sure a connection is ready before you call accept. 159int 160Accept(int fd, bool nodelay) 161{ 162 struct sockaddr_in sockaddr; 163 socklen_t slen = sizeof (sockaddr); 164 int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen); 165 if (sfd == -1)
| 155} 156 157// Open a connection. Accept will block, so if you don't want it to, 158// make sure a connection is ready before you call accept. 159int 160Accept(int fd, bool nodelay) 161{ 162 struct sockaddr_in sockaddr; 163 socklen_t slen = sizeof (sockaddr); 164 int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen); 165 if (sfd == -1)
|
166 panic("accept() failed!");
| 166 panic("accept() failed!\n");
|
167 168 if (nodelay) { 169 int i = 1; 170 ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)); 171 } 172 return sfd; 173} 174 175void 176Connect(int fd, const string &host, int port) 177{ 178 struct sockaddr_in sockaddr; 179 if (::inet_aton(host.c_str(), &sockaddr.sin_addr) == 0) { 180 struct hostent *hp; 181 hp = ::gethostbyname(host.c_str()); 182 if (!hp) 183 panic("Host %s not found\n", host); 184 185 sockaddr.sin_family = hp->h_addrtype; 186 memcpy(&sockaddr.sin_addr, hp->h_addr, hp->h_length); 187 } 188 189 sockaddr.sin_port = htons(port); 190 if (::connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0)
| 167 168 if (nodelay) { 169 int i = 1; 170 ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)); 171 } 172 return sfd; 173} 174 175void 176Connect(int fd, const string &host, int port) 177{ 178 struct sockaddr_in sockaddr; 179 if (::inet_aton(host.c_str(), &sockaddr.sin_addr) == 0) { 180 struct hostent *hp; 181 hp = ::gethostbyname(host.c_str()); 182 if (!hp) 183 panic("Host %s not found\n", host); 184 185 sockaddr.sin_family = hp->h_addrtype; 186 memcpy(&sockaddr.sin_addr, hp->h_addr, hp->h_length); 187 } 188 189 sockaddr.sin_port = htons(port); 190 if (::connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0)
|
191 panic("could not connect to %s on port %d", host, port);
| 191 panic("could not connect to %s on port %d\n", host, port);
|
192 193 DPRINTF("connected to %s on port %d\n", host, port); 194} 195 196int 197main(int argc, char *argv[]) 198{ 199 int port = 3500; 200 int bufsize = 2000; 201 bool listening = false; 202 char *device = NULL; 203 char *filter = ""; 204 char c; 205 int daemon = false; 206 string host; 207 208 program = basename(argv[0]); 209 210 while ((c = getopt(argc, argv, "b:df:lp:v")) != -1) { 211 switch (c) { 212 case 'b': 213 bufsize = atoi(optarg); 214 break; 215 case 'd': 216 daemon = true; 217 break; 218 case 'f': 219 filter = optarg; 220 break; 221 case 'l': 222 listening = true; 223 break; 224 case 'p': 225 port = atoi(optarg); 226 break; 227 case 'v': 228 verbose++; 229 break; 230 default: 231 usage(); 232 break; 233 } 234 } 235 236 signal(SIGINT, quit_now); 237 signal(SIGTERM, quit_now); 238 signal(SIGHUP, quit_now); 239 240 if (daemon) { 241 verbose = 0; 242 switch(fork()) { 243 case -1: 244 panic("Fork failed\n"); 245 case 0: 246 break; 247 default: 248 exit(0); 249 } 250 } 251 252 char *buffer = new char[bufsize]; 253 argc -= optind; 254 argv += optind; 255 256 if (argc-- == 0) 257 usage(); 258 259 device = *argv++; 260 261 if (listening) { 262 if (argc) 263 usage(); 264 } else { 265 if (argc != 1) 266 usage(); 267 268 host = *argv; 269 } 270 271 char errbuf[PCAP_ERRBUF_SIZE];
| 192 193 DPRINTF("connected to %s on port %d\n", host, port); 194} 195 196int 197main(int argc, char *argv[]) 198{ 199 int port = 3500; 200 int bufsize = 2000; 201 bool listening = false; 202 char *device = NULL; 203 char *filter = ""; 204 char c; 205 int daemon = false; 206 string host; 207 208 program = basename(argv[0]); 209 210 while ((c = getopt(argc, argv, "b:df:lp:v")) != -1) { 211 switch (c) { 212 case 'b': 213 bufsize = atoi(optarg); 214 break; 215 case 'd': 216 daemon = true; 217 break; 218 case 'f': 219 filter = optarg; 220 break; 221 case 'l': 222 listening = true; 223 break; 224 case 'p': 225 port = atoi(optarg); 226 break; 227 case 'v': 228 verbose++; 229 break; 230 default: 231 usage(); 232 break; 233 } 234 } 235 236 signal(SIGINT, quit_now); 237 signal(SIGTERM, quit_now); 238 signal(SIGHUP, quit_now); 239 240 if (daemon) { 241 verbose = 0; 242 switch(fork()) { 243 case -1: 244 panic("Fork failed\n"); 245 case 0: 246 break; 247 default: 248 exit(0); 249 } 250 } 251 252 char *buffer = new char[bufsize]; 253 argc -= optind; 254 argv += optind; 255 256 if (argc-- == 0) 257 usage(); 258 259 device = *argv++; 260 261 if (listening) { 262 if (argc) 263 usage(); 264 } else { 265 if (argc != 1) 266 usage(); 267 268 host = *argv; 269 } 270 271 char errbuf[PCAP_ERRBUF_SIZE];
|
| 272 memset(errbuf, 0, sizeof errbuf);
|
272 pcap_t *pcap = pcap_open_live(device, 1500, 1, -1, errbuf); 273 if (pcap == NULL) 274 panic("pcap_open_live failed: %s\n", errbuf); 275 276 bpf_program program; 277 bpf_u_int32 localnet, netmask;
| 273 pcap_t *pcap = pcap_open_live(device, 1500, 1, -1, errbuf); 274 if (pcap == NULL) 275 panic("pcap_open_live failed: %s\n", errbuf); 276 277 bpf_program program; 278 bpf_u_int32 localnet, netmask;
|
278 if (!pcap_lookupnet(device, &localnet, &netmask, errbuf))
| 279 if (pcap_lookupnet(device, &localnet, &netmask, errbuf) == -1)
|
279 panic("pcap_lookupnet failed: %s\n", errbuf); 280 281 if (pcap_compile(pcap, &program, filter, 1, netmask) == -1) 282 panic("pcap_compile failed, invalid filter:\n%s\n", filter); 283 284 if (pcap_setfilter(pcap, &program) == -1) 285 panic("pcap_setfilter failed\n"); 286 287 eth_t *ethernet = eth_open(device);
| 280 panic("pcap_lookupnet failed: %s\n", errbuf); 281 282 if (pcap_compile(pcap, &program, filter, 1, netmask) == -1) 283 panic("pcap_compile failed, invalid filter:\n%s\n", filter); 284 285 if (pcap_setfilter(pcap, &program) == -1) 286 panic("pcap_setfilter failed\n"); 287 288 eth_t *ethernet = eth_open(device);
|
| 289 if (!ethernet) 290 panic("cannot open the ethernet device for writing\n");
|
288 289 pollfd pfds[3]; 290 pfds[0].fd = Socket(true); 291 pfds[0].events = POLLIN; 292 pfds[0].revents = 0; 293 294 if (listening) 295 Listen(pfds[0].fd, port); 296 else 297 Connect(pfds[0].fd, host, port); 298 299 pfds[1].fd = pcap_fileno(pcap); 300 pfds[1].events = POLLIN; 301 pfds[1].revents = 0; 302 303 pfds[2].fd = 0; 304 pfds[2].events = POLLIN|POLLERR; 305 pfds[2].revents = 0; 306 307 pollfd *listen_pfd = listening ? &pfds[0] : NULL; 308 pollfd *tap_pfd = &pfds[1]; 309 pollfd *client_pfd = listening ? NULL : &pfds[0]; 310 int npfds = 2; 311 312 int32_t buffer_offset = 0; 313 int32_t data_len = 0; 314
| 291 292 pollfd pfds[3]; 293 pfds[0].fd = Socket(true); 294 pfds[0].events = POLLIN; 295 pfds[0].revents = 0; 296 297 if (listening) 298 Listen(pfds[0].fd, port); 299 else 300 Connect(pfds[0].fd, host, port); 301 302 pfds[1].fd = pcap_fileno(pcap); 303 pfds[1].events = POLLIN; 304 pfds[1].revents = 0; 305 306 pfds[2].fd = 0; 307 pfds[2].events = POLLIN|POLLERR; 308 pfds[2].revents = 0; 309 310 pollfd *listen_pfd = listening ? &pfds[0] : NULL; 311 pollfd *tap_pfd = &pfds[1]; 312 pollfd *client_pfd = listening ? NULL : &pfds[0]; 313 int npfds = 2; 314 315 int32_t buffer_offset = 0; 316 int32_t data_len = 0; 317
|
| 318 DPRINTF("Begin poll loop\n");
|
315 while (!quit) { 316 int ret = ::poll(pfds, npfds, INFTIM); 317 if (ret < 0) 318 continue; 319 320 if (listen_pfd && listen_pfd->revents) { 321 if (listen_pfd->revents & POLLIN) { 322 int fd = Accept(listen_pfd->fd, false); 323 if (client_pfd) { 324 DPRINTF("Connection rejected\n"); 325 close(fd); 326 } else { 327 DPRINTF("Connection accepted\n"); 328 client_pfd = &pfds[2]; 329 client_pfd->fd = fd; 330 npfds++; 331 } 332 } 333 listen_pfd->revents = 0; 334 } 335 336 if (tap_pfd && tap_pfd->revents) { 337 if (tap_pfd->revents & POLLIN) { 338 pcap_pkthdr hdr; 339 const u_char *data = pcap_next(pcap, &hdr); 340 if (data && client_pfd) { 341 DPRINTF("Received packet from ethernet len=%d\n", hdr.len); 342 DDUMP(data, hdr.len); 343 u_int32_t len = htonl(hdr.len); 344 write(client_pfd->fd, &len, sizeof(len)); 345 write(client_pfd->fd, data, hdr.len); 346 } 347 } 348 349 tap_pfd->revents = 0; 350 } 351 352 if (client_pfd && client_pfd->revents) { 353 if (client_pfd->revents & POLLIN) { 354 if (buffer_offset < data_len + sizeof(u_int32_t)) { 355 int len = read(client_pfd->fd, buffer + buffer_offset, 356 bufsize - buffer_offset); 357 358 if (len <= 0) { 359 perror("read"); 360 goto error; 361 } 362 363 buffer_offset += len; 364 if (data_len == 0) 365 data_len = ntohl(*(u_int32_t *)buffer); 366 367 DPRINTF("Received data from peer: len=%d buffer_offset=%d " 368 "data_len=%d\n", len, buffer_offset, data_len); 369 } 370 371 while (data_len != 0 && 372 buffer_offset >= data_len + sizeof(u_int32_t)) { 373 char *data = buffer + sizeof(u_int32_t); 374 eth_send(ethernet, data, data_len); 375 DPRINTF("Sent packet to ethernet len = %d\n", data_len); 376 DDUMP(data, data_len); 377 378 buffer_offset -= data_len + sizeof(u_int32_t); 379 if (buffer_offset > 0 && data_len > 0) { 380 memmove(buffer, data + data_len, buffer_offset); 381 data_len = ntohl(*(u_int32_t *)buffer); 382 } else 383 data_len = 0; 384 } 385 } 386 387 if (client_pfd->revents & POLLERR) { 388 error: 389 DPRINTF("Error on client socket\n"); 390 close(client_pfd->fd); 391 client_pfd = NULL; 392 393 if (listening) 394 npfds--;
| 319 while (!quit) { 320 int ret = ::poll(pfds, npfds, INFTIM); 321 if (ret < 0) 322 continue; 323 324 if (listen_pfd && listen_pfd->revents) { 325 if (listen_pfd->revents & POLLIN) { 326 int fd = Accept(listen_pfd->fd, false); 327 if (client_pfd) { 328 DPRINTF("Connection rejected\n"); 329 close(fd); 330 } else { 331 DPRINTF("Connection accepted\n"); 332 client_pfd = &pfds[2]; 333 client_pfd->fd = fd; 334 npfds++; 335 } 336 } 337 listen_pfd->revents = 0; 338 } 339 340 if (tap_pfd && tap_pfd->revents) { 341 if (tap_pfd->revents & POLLIN) { 342 pcap_pkthdr hdr; 343 const u_char *data = pcap_next(pcap, &hdr); 344 if (data && client_pfd) { 345 DPRINTF("Received packet from ethernet len=%d\n", hdr.len); 346 DDUMP(data, hdr.len); 347 u_int32_t len = htonl(hdr.len); 348 write(client_pfd->fd, &len, sizeof(len)); 349 write(client_pfd->fd, data, hdr.len); 350 } 351 } 352 353 tap_pfd->revents = 0; 354 } 355 356 if (client_pfd && client_pfd->revents) { 357 if (client_pfd->revents & POLLIN) { 358 if (buffer_offset < data_len + sizeof(u_int32_t)) { 359 int len = read(client_pfd->fd, buffer + buffer_offset, 360 bufsize - buffer_offset); 361 362 if (len <= 0) { 363 perror("read"); 364 goto error; 365 } 366 367 buffer_offset += len; 368 if (data_len == 0) 369 data_len = ntohl(*(u_int32_t *)buffer); 370 371 DPRINTF("Received data from peer: len=%d buffer_offset=%d " 372 "data_len=%d\n", len, buffer_offset, data_len); 373 } 374 375 while (data_len != 0 && 376 buffer_offset >= data_len + sizeof(u_int32_t)) { 377 char *data = buffer + sizeof(u_int32_t); 378 eth_send(ethernet, data, data_len); 379 DPRINTF("Sent packet to ethernet len = %d\n", data_len); 380 DDUMP(data, data_len); 381 382 buffer_offset -= data_len + sizeof(u_int32_t); 383 if (buffer_offset > 0 && data_len > 0) { 384 memmove(buffer, data + data_len, buffer_offset); 385 data_len = ntohl(*(u_int32_t *)buffer); 386 } else 387 data_len = 0; 388 } 389 } 390 391 if (client_pfd->revents & POLLERR) { 392 error: 393 DPRINTF("Error on client socket\n"); 394 close(client_pfd->fd); 395 client_pfd = NULL; 396 397 if (listening) 398 npfds--;
|
395 else
| 399 else { 400 DPRINTF("Calling it quits because of poll error\n");
|
396 quit = true;
| 401 quit = true;
|
| 402 }
|
397 } 398 399 if (client_pfd) 400 client_pfd->revents = 0; 401 }
| 403 } 404 405 if (client_pfd) 406 client_pfd->revents = 0; 407 }
|
402
| |
403 } 404 405 delete [] buffer; 406 pcap_close(pcap); 407 eth_close(ethernet); 408 if (listen_pfd) 409 close(listen_pfd->fd); 410 411 if (client_pfd) 412 close(client_pfd->fd); 413 414 return 0; 415}
| 408 } 409 410 delete [] buffer; 411 pcap_close(pcap); 412 eth_close(ethernet); 413 if (listen_pfd) 414 close(listen_pfd->fd); 415 416 if (client_pfd) 417 close(client_pfd->fd); 418 419 return 0; 420}
|