xref: /netbsd-src/external/bsd/libpcap/dist/pcap-rpcap-unix.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*
2  * Reimplementation of winpcap pcap-remote.c
3  * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
4  * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the Politecnico di Torino, CACE Technologies
17  * nor the names of its contributors may be used to endorse or promote
18  * products derived from this software without specific prior written
19  * permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include "pcap-int.h"
39 
40 #ifdef NEED_STRERROR_H
41 #include "strerror.h"
42 #endif
43 
44 #include <errno.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <sys/socket.h>
49 #include <arpa/inet.h>
50 
51 #include <time.h>
52 #include <sys/time.h>
53 #include <netinet/in.h>
54 #include <sys/types.h>
55 
56 #include "pcap-rpcap-unix.h"
57 
58 #define RPCAP_IFACE "rpcap://"
59 
60 /* default */
61 #define RPCAP_DEFAULT_NETPORT 2002
62 
63 /* version */
64 #define RPCAP_VERSION_EXPERIMENTAL 0
65 
66 /* packets */
67 #define RPCAP_MSG_ERROR 1				/*!< Message that keeps an error notification */
68 #define RPCAP_MSG_OPEN_REQ 3			/*!< Request to open a remote device */
69 #define RPCAP_MSG_STARTCAP_REQ 4		/*!< Request to start a capture on a remote device */
70 #define RPCAP_MSG_UPDATEFILTER_REQ 5	/*!< Send a compiled filter into the remote device */
71 #define RPCAP_MSG_PACKET 7				/*!< This is a 'data' message, which carries a network packet */
72 #define RPCAP_MSG_AUTH_REQ 8			/*!< Message that keeps the authentication parameters */
73 #define RPCAP_MSG_STATS_REQ 9			/*!< It requires to have network statistics */
74 
75 #define RPCAP_UPDATEFILTER_BPF 1			/*!< This code tells us that the filter is encoded with the BPF/NPF syntax */
76 
77 static unsigned short
78 get16(const unsigned char *buf)
79 {
80 	unsigned short val;
81 
82 	val = buf[0];
83 	val = val << 8 | buf[1];
84 	return val;
85 }
86 
87 static void
88 put16(unsigned char *buf, unsigned int val)
89 {
90 	buf[0] = val >> 8;
91 	buf[1] = val >> 0;
92 }
93 
94 static unsigned int
95 get32(const unsigned char *buf)
96 {
97 	unsigned int val;
98 
99 	val = buf[0];
100 	val = val << 8 | buf[1];
101 	val = val << 8 | buf[2];
102 	val = val << 8 | buf[3];
103 	return val;
104 }
105 
106 static void
107 put32(unsigned char *buf, unsigned int val)
108 {
109 	buf[0] = val >> 24;
110 	buf[1] = val >> 16;
111 	buf[2] = val >> 8;
112 	buf[3] = val >> 0;
113 }
114 
115 static int
116 rpcap_recv_pkt(pcap_t *p, int fd, unsigned char *recv_buf, unsigned int buflen)
117 {
118 	static unsigned char discard[1024];
119 
120 	size_t mlen;
121 	int ret;
122 	unsigned char *buf;
123 	unsigned int len;
124 	unsigned int pkt_len;
125 
126 	unsigned char hdr[8];
127 	int pkt_type;
128 
129 /* read header loop */
130 	buf = hdr;
131 	len = 8;
132 
133 	ret = 0;
134 	do {
135 		buf += ret;
136 		len -= ret;
137 
138 		do {
139 			ret = read(fd, buf, len);
140 			if (p->break_loop) {
141 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "break-loop");
142 				p->break_loop = 0;
143 				return -2;
144 			}
145 		} while (ret == -1 && errno == EINTR);
146 	} while (ret > 0 && len-ret);
147 
148 	if (ret <= 0) {
149 		if (!ret)
150 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection closed");
151 		else
152 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection error (%s)", strerror(errno));
153 		return -1;
154 	}
155 
156 	if (hdr[0] != RPCAP_VERSION_EXPERIMENTAL) {
157 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: incorrect reply version (%.2x)", hdr[0]);
158 		return -1;
159 	}
160 
161 	pkt_type = (unsigned char) hdr[1];
162 	pkt_len  = get32(&hdr[4]);
163 
164 	if (pkt_type == RPCAP_MSG_ERROR) {
165 		recv_buf = (unsigned char *)p->errbuf;
166 		buflen = PCAP_ERRBUF_SIZE-1;
167 	}
168 
169 	buf = recv_buf;
170 
171 /* read payload loop */
172 	if (pkt_len) {
173 		ret = 0;
174 		len = pkt_len;
175 		do {
176 			buf += ret;
177 			buflen -= ret;
178 			len -= ret;
179 
180 			if (!buflen) {
181 				buf = discard;
182 				buflen = sizeof(discard);
183 			}
184 
185 			mlen = (len < 0x7fff) ? len : 0x7fff;
186 
187 			if (mlen > buflen)
188 				mlen = buflen;
189 
190 			do {
191 				ret = read(fd, buf, mlen);
192 				if (p->break_loop) {
193 					p->break_loop = 0;
194 					snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "break-loop");
195 					return -2;
196 				}
197 			} while (ret == -1 && errno == EINTR);
198 		} while (ret > 0 && len-ret);
199 
200 		if (ret <= 0) {
201 			if (!ret)
202 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection closed");
203 			else
204 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection error (%s)", strerror(errno));
205 			return -1;
206 		}
207 		buf += ret;
208 	}
209 
210 	/* always NUL terminate errbuf, and signal error */
211 	if (pkt_type == RPCAP_MSG_ERROR) {
212 		*buf = '\0';
213 		return -1;
214 	}
215 	return pkt_len;
216 }
217 
218 static int
219 rpcap_send_pkt(pcap_t *p, const unsigned char *send_buf, unsigned int len)
220 {
221 	size_t mlen;
222 	int ret;
223 
224 /* send loop */
225 	ret = 0;
226 	do {
227 		send_buf += ret;
228 		len -= ret;
229 
230 		mlen = (len < 0x7fff) ? len : 0x7fff;
231 
232 		do {
233 			ret = write(p->fd, send_buf, mlen);
234 			if (p->break_loop) {
235 				p->break_loop = 0;
236 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "break-loop");
237 				return -2;
238 			}
239 		} while (ret == -1 && errno == EINTR);
240 	} while (ret > 0 && len-ret);
241 
242 	if (ret <= 0) {
243 		if (!ret)
244 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection closed");
245 		else
246 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection error (%s)", strerror(errno));
247 		return -1;
248 	}
249 	return 0;
250 }
251 
252 static int
253 rpcap_send_request(pcap_t *p, char type, unsigned char *buf, unsigned int payload_len)
254 {
255 	buf[0] = RPCAP_VERSION_EXPERIMENTAL;
256 	buf[1] = type;
257 	buf[2] = buf[3] = 0;
258 	put32(&buf[4], payload_len);
259 
260 	return rpcap_send_pkt(p, buf, 8+payload_len);
261 }
262 
263 static int
264 rpcap_send_request_auth(pcap_t *p, const char *username, const char *password)
265 {
266 
267 	if (username || password) {
268 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: auth not supported (yet!)");
269 		return -1;
270 
271 	} else {
272 		static const unsigned char login_null_pkt[16] = {
273 			RPCAP_VERSION_EXPERIMENTAL,
274 			RPCAP_MSG_AUTH_REQ,
275 			0, 0,
276 			0, 0, 0, 8,
277 
278 			0, 0, 0, 0, 0, 0, 0, 0
279 		};
280 
281 		if (rpcap_send_pkt(p, login_null_pkt, sizeof(login_null_pkt)))
282 			return -1;
283 	}
284 
285 	return rpcap_recv_pkt(p, p->fd, NULL, 0);
286 }
287 
288 static int
289 rpcap_send_request_open(pcap_t *p, const char *interface)
290 {
291 	const size_t interface_len = strlen(interface);
292 
293 	unsigned char buf_open[8+255] = {
294 		RPCAP_VERSION_EXPERIMENTAL,
295 		RPCAP_MSG_OPEN_REQ,
296 		0, 0,
297 		0, 0, 0, interface_len
298 	};
299 
300 	unsigned char reply_buf[8];
301 	int reply_len;
302 
303 	if (interface_len > 255) {
304 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: maximum interface length: 255");
305 		return -1;
306 	}
307 
308 	memcpy(buf_open + 8, interface, interface_len);
309 	if (rpcap_send_pkt(p, buf_open, 8 + interface_len))
310 		return -1;
311 
312 	reply_len = rpcap_recv_pkt(p, p->fd, reply_buf, sizeof(reply_buf));
313 	if (reply_len != sizeof(reply_buf)) {
314 		if (reply_len >= 0)
315 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (openreply: %u)", reply_len);
316 		return -1;
317 	}
318 
319 	p->linktype = get32(&reply_buf[0]);
320 	p->tzoff    = get32(&reply_buf[4]);
321 
322 	return 0;
323 }
324 
325 static int
326 rpcap_send_request_start(pcap_t *p, struct in_addr *server_ip)
327 {
328 	unsigned char buf_start[8+12+8+8] = {
329 		RPCAP_VERSION_EXPERIMENTAL,
330 		RPCAP_MSG_STARTCAP_REQ,
331 		0, 0,
332 		0, 0, 0, 12+8+8,
333 /* rpcap_startcapreq (12B) */
334 		0xff, 0xff, 0xff, 0xff, /* snaplen */
335 		0xff, 0xff, 0xff, 0xff, /* timeout */
336 		0x00, 0x00, /* flags */
337 		0x00, 0x00, /* portdata */
338 /* rpcap_filter (8B+8B) */
339 		0x00, RPCAP_UPDATEFILTER_BPF, /* filtertype */
340 		0x00, 0x00,
341 		0x00, 0x00, 0x00, 0x01,
342 
343 			0x00, 0x06,				/* ret */
344 			0x00,
345 			0x00,
346 			0x00, 0x00, 0xff, 0xff	/* #65535 */
347 	};
348 
349 	struct sockaddr_in sin;
350 	unsigned char reply_buf[8];
351 	int reply_len;
352 	int fd;
353 
354 	unsigned short portdata;
355 
356 	put32(&buf_start[8], p->snapshot);      /* snaplen */
357 	put32(&buf_start[12], p->opt.timeout/2); /* read_timeout */
358 
359 	if (rpcap_send_pkt(p, buf_start, sizeof(buf_start)))
360 		return -1;
361 
362 	reply_len = rpcap_recv_pkt(p, p->fd, reply_buf, sizeof(reply_buf));
363 	if (reply_len != sizeof(reply_buf)) {
364 		if (reply_len >= 0)
365 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (startreply: %u)", reply_len);
366 		return -1;
367 	}
368 
369 	get32(&reply_buf[0]);
370 	portdata = get16(&reply_buf[4]);
371 
372 	fd = socket(AF_INET, SOCK_STREAM, 0);
373 	if (fd < 0) {
374 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
375 				"Can't create data socket %d:%s",
376 				errno, pcap_strerror(errno));
377 		return -1;
378 	}
379 	sin.sin_family = AF_INET;
380 	sin.sin_addr = *server_ip;
381 	sin.sin_port = htons(portdata);
382 
383 	if (connect(fd, (struct sockaddr *) &sin, sizeof(sin))) {
384 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
385 				"Can't connect to data socket (%d:%s)",
386 				errno, pcap_strerror(errno));
387 		return -1;
388 	}
389 	p->selectable_fd = fd;
390 
391 	return 0;
392 }
393 
394 static int
395 rpcap_inject_common(pcap_t *handle, const void *buf, size_t size)
396 {
397 	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported with remote capture");
398 	return -1;
399 }
400 
401 static int
402 rpcap_stats_common(pcap_t *handle, struct pcap_stat *stats)
403 {
404 	static const unsigned char buf_stats[8] = {
405 		RPCAP_VERSION_EXPERIMENTAL,
406 		RPCAP_MSG_STATS_REQ,
407 		0, 0,
408 		0, 0, 0, 0
409 	};
410 
411 	unsigned char reply_buf[16];
412 	int reply_len;
413 
414 /* local */
415 #if 0
416 	stats->ps_recv = handle->md.packets_read;
417 	stats->ps_drop = 0;
418 	stats->ps_ifdrop = 0;
419 #endif
420 
421 /* remote */
422 	if (rpcap_send_pkt(handle, buf_stats, sizeof(buf_stats)))
423 		return -1;
424 
425 	reply_len = rpcap_recv_pkt(handle, handle->fd, reply_buf, sizeof(reply_buf));
426 	if (reply_len != sizeof(reply_buf)) {
427 		if (reply_len >= 0)
428 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (statsreply: %u)", reply_len);
429 		return -1;
430 	}
431 
432 	stats->ps_recv   = get32(&reply_buf[0]);
433 	stats->ps_ifdrop = get32(&reply_buf[4]);
434 	stats->ps_drop   = get32(&reply_buf[8]);
435 	return 0;
436 }
437 
438 static int
439 rpcap_setfilter_common(pcap_t *handle, struct bpf_program *prog)
440 {
441 	unsigned char *buf_setfilter;
442 
443 	/* update local filter */
444 	if (install_bpf_program(handle, prog) == -1)
445 		return -1;
446 
447 	/* update remote filter */
448 	if (prog->bf_len < 0xfffff) {
449 		unsigned int data_size = 8 + 8 * prog->bf_len;
450 		unsigned char *buf_filter;
451 		unsigned char *buf_insn;
452 		size_t i;
453 
454 		buf_setfilter = malloc(8 + data_size);
455 		if (!buf_setfilter) {
456 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "No memory for setfilter packet");
457 			return -1;
458 		}
459 
460 		buf_filter = &buf_setfilter[8];
461 		buf_insn = &buf_filter[8];
462 
463 		put16(&buf_filter[0], RPCAP_UPDATEFILTER_BPF);
464 		put16(&buf_filter[2], 0);
465 		put32(&buf_filter[4], prog->bf_len);
466 
467 		for (i = 0; i < prog->bf_len; i++) {
468 			unsigned char *data = &buf_insn[i * 8];
469 
470 			put16(&data[0], prog->bf_insns[i].code);
471 			data[2] = prog->bf_insns[i].jt;
472 			data[3] = prog->bf_insns[i].jf;
473 			put32(&data[4], prog->bf_insns[i].k);
474 		}
475 
476 		if (rpcap_send_request(handle, RPCAP_MSG_UPDATEFILTER_REQ, buf_setfilter, data_size)) {
477 			free(buf_setfilter);
478 			return -1;
479 		}
480 		free(buf_setfilter);
481 
482 		if (rpcap_recv_pkt(handle, handle->fd, NULL, 0) < 0)
483 			return -1;
484 	}
485 	return 0;
486 }
487 
488 static int
489 rpcap_read_unix(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
490 {
491 	struct pcap_pkthdr pkth;
492 	const unsigned char *pkt;
493 	const unsigned char *buf;
494 	unsigned int pkt_len;
495 	int count = 0;
496 
497 	pkt_len = rpcap_recv_pkt(handle, handle->selectable_fd, handle->buffer, handle->bufsize);
498 	if (pkt_len < 20) {
499 		if (pkt_len == 0) {
500 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkt_len check failed (%u < 20)", pkt_len);
501 			return -1;
502 		}
503 		return pkt_len;
504 	}
505 	buf = handle->buffer;
506 
507 /* local */
508 #if 0
509 	gettimeofday(&pkth.ts, NULL);
510 	pkth.caplen = pkth.len = pkt_len - 20
511 #endif
512 /* remote */
513 	pkth.ts.tv_sec = get32(&buf[0]);
514 	pkth.ts.tv_usec = get32(&buf[4]);
515 	pkth.caplen = get32(&buf[8]);
516 	pkth.len = get32(&buf[12]);
517 	/* pktnr */
518 	pkt = &buf[20];
519 
520 	/* sanity caplen */
521 	if (pkt_len - 20 < pkth.caplen) {
522 		/* pkt.caplen = pkt_len - 20; */
523 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkth.caplen check failed (%u < %u)", pkt_len - 20, pkth.caplen);
524 		return -1;
525 	}
526 
527 	if (handle->fcode.bf_insns == NULL ||
528 			bpf_filter(handle->fcode.bf_insns, pkt, pkth.len, pkth.caplen))
529 	{
530 //		handle->md.packets_read++;
531 		callback(user, &pkth, pkt);
532 		count++;
533 	}
534 	return count;
535 }
536 
537 static void
538 rpcap_cleanup(pcap_t *handle)
539 {
540 	if (handle->selectable_fd != handle->fd) {
541 		int fd = handle->selectable_fd;
542 
543 		if (fd != -1) {
544 			handle->selectable_fd = -1;
545 			close(fd);
546 		}
547 	}
548 	pcap_cleanup_live_common(handle);
549 }
550 
551 static int
552 rpcap_activate(pcap_t *handle)
553 {
554 	const char *dev = handle->opt.device;
555 	const char *tmp;
556 
557 	char *host;
558 	char *username = NULL;
559 	char *password = NULL;
560 	const char *interface = NULL;
561 	int port;
562 
563 	struct sockaddr_in sin;
564 
565 	/* rpcap[s]://login:password@host:port/interface */
566 	if (strncmp(dev, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0) {
567 		port = RPCAP_DEFAULT_NETPORT;
568 		dev += strlen(RPCAP_IFACE);
569 
570 	} /* else if (strncmp(dev, "rpcaps://", strlen("rpcaps://")) == 0) {
571 		port = RPCAP_DEFAULT_NETPORT_SSL;
572 		dev += strlen("rpcaps://");
573 
574 	} */ else {
575 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid protocol");
576 		return PCAP_ERROR;
577 	}
578 
579 	if ((tmp = strchr(dev, '@'))) {
580 		char *ptmp;
581 
582 		if ((ptmp = strchr(dev, ':'))) {
583 			username = strndup(dev, ptmp-dev);
584 			password = strndup(ptmp+1, tmp-(ptmp+1));
585 
586 		} else {
587 			username = strndup(dev, tmp-dev);
588 
589 			/* XXX, ask for password? */
590 		}
591 
592 		dev = tmp + 1;
593 	}
594 
595 	if (*dev == '[') {
596 		tmp = strchr(dev, ']');
597 		if (!tmp) {
598 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid host (missing ']')");
599 			return PCAP_ERROR;
600 		}
601 
602 		host = strndup(dev+1, tmp-(dev+1));
603 
604 		dev = tmp + 1;
605 	} else {
606 		tmp = strchr(dev, ':');
607 		if (!tmp)
608 			tmp = strchr(dev, '/');
609 
610 		if (tmp) {
611 			host = strndup(dev, tmp-dev);
612 			dev = tmp;
613 		} else
614 			host = strdup(dev);
615 	}
616 
617 	if (*dev == ':') {
618 		char *end;
619 
620 		if (dev[1] == '\0') {
621 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: missing port");
622 			return PCAP_ERROR;
623 		}
624 
625 		port = strtol(dev + 1, &end, 10);
626 		if (port < 1 || port > 65535) {
627 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid port");
628 			return PCAP_ERROR;
629 		}
630 
631 		dev = end;
632 	}
633 
634 	if (*dev == '/')
635 		interface = dev+1;
636 
637 	if (!host) {
638 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse host");
639 		return PCAP_ERROR;
640 	}
641 
642 	if (!interface) {
643 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse interface");
644 		return PCAP_ERROR;
645 	}
646 
647 	/* XXX, gethostbyname, ipv6, etc... */
648 	sin.sin_family = AF_INET;
649 	sin.sin_addr.s_addr = inet_addr(host);
650 	sin.sin_port = htons(port);
651 	if (sin.sin_addr.s_addr == INADDR_NONE) {
652 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: not ipv4 address");
653 		goto free_fail;
654 	}
655 
656 	/* Initialize some components of the pcap structure. */
657 	handle->offset = 20;
658 	handle->bufsize = handle->snapshot + handle->offset;
659 	handle->linktype = -1;	/* invalid for now */
660 	handle->read_op = rpcap_read_unix;
661 	handle->setfilter_op = rpcap_setfilter_common;
662 	handle->inject_op = rpcap_inject_common;
663 	handle->setdirection_op = NULL;
664 	handle->set_datalink_op = NULL;	/* not possible */
665 	handle->getnonblock_op = pcap_getnonblock_fd;
666 	handle->setnonblock_op = pcap_setnonblock_fd;
667 	handle->stats_op = rpcap_stats_common;
668 	handle->cleanup_op = rpcap_cleanup;
669 
670 	/* Create socket */
671 	handle->fd = socket(AF_INET, SOCK_STREAM, 0);
672 	handle->selectable_fd = -1;
673 	if (handle->fd < 0) {
674 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
675 				"Can't create socket %d:%s",
676 				errno, pcap_strerror(errno));
677 		goto close_fail;
678 	}
679 
680 	if (connect(handle->fd, (struct sockaddr *) &sin, sizeof(sin))) {
681 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
682 				"Can't connect to %s:%d (%d:%s)",
683 				host, port, errno, pcap_strerror(errno));
684 		goto free_fail;
685 	}
686 
687 /* login */
688 	if (rpcap_send_request_auth(handle, username, password) < 0)
689 		goto close_fail;
690 	if (rpcap_send_request_open(handle, interface) < 0)
691 		goto close_fail;
692 	if (rpcap_send_request_start(handle, &(sin.sin_addr)) < 0)
693 		goto close_fail;
694 
695 	handle->buffer = malloc(handle->bufsize);
696 	if (!handle->buffer) {
697 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
698 				"Can't allocate dump buffer: %s",
699 				pcap_strerror(errno));
700 		goto close_fail;
701 	}
702 
703 	if (handle->opt.rfmon) {
704 		/*
705 		 * Monitor mode doesn't apply to rpcap.
706 		 */
707 		rpcap_cleanup(handle);
708 		return PCAP_ERROR_RFMON_NOTSUP;
709 	}
710 
711 	if (handle->opt.buffer_size != 0) {
712 		/*
713 		 * Set the socket buffer size to the specified value.
714 		 */
715 		if (setsockopt(handle->selectable_fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
716 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
717 			goto close_fail;
718 		}
719 	}
720 	free(username);
721 	free(password);
722 	free(host);
723 
724 	return 0;
725 
726 close_fail:
727 	rpcap_cleanup(handle);
728 free_fail:
729 	free(username);
730 	free(password);
731 	free(host);
732 	return PCAP_ERROR;
733 }
734 
735 pcap_t *
736 rpcap_create(const char *device, char *err_str, int *is_ours)
737 {
738 	const char *cp = device;
739 	pcap_t *p;
740 
741 	if (strncmp(cp, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0)
742 		cp += strlen(RPCAP_IFACE);
743 	else {
744 		*is_ours = 0;
745 		return NULL;
746 	}
747 
748 	if (*cp == '\0') {
749 		*is_ours = 0;
750 		return NULL;
751 	}
752 
753 	*is_ours = 1;
754 
755 	p = pcap_create_common(__UNCONST(device), 16384);
756 	if (p == NULL)
757 		return NULL;
758 
759 	p->activate_op = rpcap_activate;
760 	return p;
761 }
762 
763