xref: /netbsd-src/external/bsd/libpcap/dist/pcap-rpcap-unix.c (revision 8bda04910f1f2c366c51d4cbd40df19f5b57f1dd)
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 #if 0
321 	p->tzoff    = get32(&reply_buf[4]);
322 #endif
323 
324 	return 0;
325 }
326 
327 static int
328 rpcap_send_request_start(pcap_t *p, struct in_addr *server_ip)
329 {
330 	unsigned char buf_start[8+12+8+8] = {
331 		RPCAP_VERSION_EXPERIMENTAL,
332 		RPCAP_MSG_STARTCAP_REQ,
333 		0, 0,
334 		0, 0, 0, 12+8+8,
335 /* rpcap_startcapreq (12B) */
336 		0xff, 0xff, 0xff, 0xff, /* snaplen */
337 		0xff, 0xff, 0xff, 0xff, /* timeout */
338 		0x00, 0x00, /* flags */
339 		0x00, 0x00, /* portdata */
340 /* rpcap_filter (8B+8B) */
341 		0x00, RPCAP_UPDATEFILTER_BPF, /* filtertype */
342 		0x00, 0x00,
343 		0x00, 0x00, 0x00, 0x01,
344 
345 			0x00, 0x06,				/* ret */
346 			0x00,
347 			0x00,
348 			0x00, 0x00, 0xff, 0xff	/* #65535 */
349 	};
350 
351 	struct sockaddr_in sin;
352 	unsigned char reply_buf[8];
353 	int reply_len;
354 	int fd;
355 
356 	unsigned short portdata;
357 
358 	put32(&buf_start[8], p->snapshot);      /* snaplen */
359 	put32(&buf_start[12], p->opt.timeout/2); /* read_timeout */
360 
361 	if (rpcap_send_pkt(p, buf_start, sizeof(buf_start)))
362 		return -1;
363 
364 	reply_len = rpcap_recv_pkt(p, p->fd, reply_buf, sizeof(reply_buf));
365 	if (reply_len != sizeof(reply_buf)) {
366 		if (reply_len >= 0)
367 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (startreply: %u)", reply_len);
368 		return -1;
369 	}
370 
371 	get32(&reply_buf[0]);
372 	portdata = get16(&reply_buf[4]);
373 
374 	fd = socket(AF_INET, SOCK_STREAM, 0);
375 	if (fd < 0) {
376 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
377 				"Can't create data socket %d:%s",
378 				errno, pcap_strerror(errno));
379 		return -1;
380 	}
381 	sin.sin_family = AF_INET;
382 	sin.sin_addr = *server_ip;
383 	sin.sin_port = htons(portdata);
384 
385 	if (connect(fd, (struct sockaddr *) &sin, sizeof(sin))) {
386 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
387 				"Can't connect to data socket (%d:%s)",
388 				errno, pcap_strerror(errno));
389 		return -1;
390 	}
391 	p->selectable_fd = fd;
392 
393 	return 0;
394 }
395 
396 static int
397 rpcap_inject_common(pcap_t *handle, const void *buf, size_t size)
398 {
399 	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported with remote capture");
400 	return -1;
401 }
402 
403 static int
404 rpcap_stats_common(pcap_t *handle, struct pcap_stat *stats)
405 {
406 	static const unsigned char buf_stats[8] = {
407 		RPCAP_VERSION_EXPERIMENTAL,
408 		RPCAP_MSG_STATS_REQ,
409 		0, 0,
410 		0, 0, 0, 0
411 	};
412 
413 	unsigned char reply_buf[16];
414 	int reply_len;
415 
416 /* local */
417 #if 0
418 	stats->ps_recv = handle->md.packets_read;
419 	stats->ps_drop = 0;
420 	stats->ps_ifdrop = 0;
421 #endif
422 
423 /* remote */
424 	if (rpcap_send_pkt(handle, buf_stats, sizeof(buf_stats)))
425 		return -1;
426 
427 	reply_len = rpcap_recv_pkt(handle, handle->fd, reply_buf, sizeof(reply_buf));
428 	if (reply_len != sizeof(reply_buf)) {
429 		if (reply_len >= 0)
430 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (statsreply: %u)", reply_len);
431 		return -1;
432 	}
433 
434 	stats->ps_recv   = get32(&reply_buf[0]);
435 	stats->ps_ifdrop = get32(&reply_buf[4]);
436 	stats->ps_drop   = get32(&reply_buf[8]);
437 	return 0;
438 }
439 
440 static int
441 rpcap_setfilter_common(pcap_t *handle, struct bpf_program *prog)
442 {
443 	unsigned char *buf_setfilter;
444 
445 	/* update local filter */
446 	if (pcapint_install_bpf_program(handle, prog) == -1)
447 		return -1;
448 
449 	/* update remote filter */
450 	if (prog->bf_len < 0xfffff) {
451 		unsigned int data_size = 8 + 8 * prog->bf_len;
452 		unsigned char *buf_filter;
453 		unsigned char *buf_insn;
454 		size_t i;
455 
456 		buf_setfilter = malloc(8 + data_size);
457 		if (!buf_setfilter) {
458 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "No memory for setfilter packet");
459 			return -1;
460 		}
461 
462 		buf_filter = &buf_setfilter[8];
463 		buf_insn = &buf_filter[8];
464 
465 		put16(&buf_filter[0], RPCAP_UPDATEFILTER_BPF);
466 		put16(&buf_filter[2], 0);
467 		put32(&buf_filter[4], prog->bf_len);
468 
469 		for (i = 0; i < prog->bf_len; i++) {
470 			unsigned char *data = &buf_insn[i * 8];
471 
472 			put16(&data[0], prog->bf_insns[i].code);
473 			data[2] = prog->bf_insns[i].jt;
474 			data[3] = prog->bf_insns[i].jf;
475 			put32(&data[4], prog->bf_insns[i].k);
476 		}
477 
478 		if (rpcap_send_request(handle, RPCAP_MSG_UPDATEFILTER_REQ, buf_setfilter, data_size)) {
479 			free(buf_setfilter);
480 			return -1;
481 		}
482 		free(buf_setfilter);
483 
484 		if (rpcap_recv_pkt(handle, handle->fd, NULL, 0) < 0)
485 			return -1;
486 	}
487 	return 0;
488 }
489 
490 static int
491 rpcap_read_unix(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
492 {
493 	struct pcap_pkthdr pkth;
494 	const unsigned char *pkt;
495 	const unsigned char *buf;
496 	unsigned int pkt_len;
497 	int count = 0;
498 
499 	pkt_len = rpcap_recv_pkt(handle, handle->selectable_fd, handle->buffer, handle->bufsize);
500 	if (pkt_len < 20) {
501 		if (pkt_len == 0) {
502 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkt_len check failed (%u < 20)", pkt_len);
503 			return -1;
504 		}
505 		return pkt_len;
506 	}
507 	buf = handle->buffer;
508 
509 /* local */
510 #if 0
511 	gettimeofday(&pkth.ts, NULL);
512 	pkth.caplen = pkth.len = pkt_len - 20
513 #endif
514 /* remote */
515 	pkth.ts.tv_sec = get32(&buf[0]);
516 	pkth.ts.tv_usec = get32(&buf[4]);
517 	pkth.caplen = get32(&buf[8]);
518 	pkth.len = get32(&buf[12]);
519 	/* pktnr */
520 	pkt = &buf[20];
521 
522 	/* sanity caplen */
523 	if (pkt_len - 20 < pkth.caplen) {
524 		/* pkt.caplen = pkt_len - 20; */
525 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkth.caplen check failed (%u < %u)", pkt_len - 20, pkth.caplen);
526 		return -1;
527 	}
528 
529 	if (handle->fcode.bf_insns == NULL ||
530 			bpf_filter(handle->fcode.bf_insns, pkt, pkth.len, pkth.caplen))
531 	{
532 //		handle->md.packets_read++;
533 		callback(user, &pkth, pkt);
534 		count++;
535 	}
536 	return count;
537 }
538 
539 static void
540 rpcap_cleanup(pcap_t *handle)
541 {
542 	if (handle->selectable_fd != handle->fd) {
543 		int fd = handle->selectable_fd;
544 
545 		if (fd != -1) {
546 			handle->selectable_fd = -1;
547 			close(fd);
548 		}
549 	}
550 	pcapint_cleanup_live_common(handle);
551 }
552 
553 static int
554 rpcap_activate(pcap_t *handle)
555 {
556 	const char *dev = handle->opt.device;
557 	const char *tmp;
558 
559 	char *host;
560 	char *username = NULL;
561 	char *password = NULL;
562 	const char *interface = NULL;
563 	int port;
564 
565 	struct sockaddr_in sin;
566 
567 	/* rpcap[s]://login:password@host:port/interface */
568 	if (strncmp(dev, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0) {
569 		port = RPCAP_DEFAULT_NETPORT;
570 		dev += strlen(RPCAP_IFACE);
571 
572 	} /* else if (strncmp(dev, "rpcaps://", strlen("rpcaps://")) == 0) {
573 		port = RPCAP_DEFAULT_NETPORT_SSL;
574 		dev += strlen("rpcaps://");
575 
576 	} */ else {
577 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid protocol");
578 		return PCAP_ERROR;
579 	}
580 
581 	if ((tmp = strchr(dev, '@'))) {
582 		char *ptmp;
583 
584 		if ((ptmp = strchr(dev, ':'))) {
585 			username = strndup(dev, ptmp-dev);
586 			password = strndup(ptmp+1, tmp-(ptmp+1));
587 
588 		} else {
589 			username = strndup(dev, tmp-dev);
590 
591 			/* XXX, ask for password? */
592 		}
593 
594 		dev = tmp + 1;
595 	}
596 
597 	if (*dev == '[') {
598 		tmp = strchr(dev, ']');
599 		if (!tmp) {
600 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid host (missing ']')");
601 			return PCAP_ERROR;
602 		}
603 
604 		host = strndup(dev+1, tmp-(dev+1));
605 
606 		dev = tmp + 1;
607 	} else {
608 		tmp = strchr(dev, ':');
609 		if (!tmp)
610 			tmp = strchr(dev, '/');
611 
612 		if (tmp) {
613 			host = strndup(dev, tmp-dev);
614 			dev = tmp;
615 		} else
616 			host = strdup(dev);
617 	}
618 
619 	if (*dev == ':') {
620 		char *end;
621 
622 		if (dev[1] == '\0') {
623 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: missing port");
624 			return PCAP_ERROR;
625 		}
626 
627 		port = strtol(dev + 1, &end, 10);
628 		if (port < 1 || port > 65535) {
629 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid port");
630 			return PCAP_ERROR;
631 		}
632 
633 		dev = end;
634 	}
635 
636 	if (*dev == '/')
637 		interface = dev+1;
638 
639 	if (!host) {
640 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse host");
641 		return PCAP_ERROR;
642 	}
643 
644 	if (!interface) {
645 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse interface");
646 		return PCAP_ERROR;
647 	}
648 
649 	/* XXX, gethostbyname, ipv6, etc... */
650 	sin.sin_family = AF_INET;
651 	sin.sin_addr.s_addr = inet_addr(host);
652 	sin.sin_port = htons(port);
653 	if (sin.sin_addr.s_addr == INADDR_NONE) {
654 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: not ipv4 address");
655 		goto free_fail;
656 	}
657 
658 	/* Initialize some components of the pcap structure. */
659 	handle->offset = 20;
660 	handle->bufsize = handle->snapshot + handle->offset;
661 	handle->linktype = -1;	/* invalid for now */
662 	handle->read_op = rpcap_read_unix;
663 	handle->setfilter_op = rpcap_setfilter_common;
664 	handle->inject_op = rpcap_inject_common;
665 	handle->setdirection_op = NULL;
666 	handle->set_datalink_op = NULL;	/* not possible */
667 	handle->getnonblock_op = pcapint_getnonblock_fd;
668 	handle->setnonblock_op = pcapint_setnonblock_fd;
669 	handle->stats_op = rpcap_stats_common;
670 	handle->cleanup_op = rpcap_cleanup;
671 
672 	/* Create socket */
673 	handle->fd = socket(AF_INET, SOCK_STREAM, 0);
674 	handle->selectable_fd = -1;
675 	if (handle->fd < 0) {
676 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
677 				"Can't create socket %d:%s",
678 				errno, pcap_strerror(errno));
679 		goto close_fail;
680 	}
681 
682 	if (connect(handle->fd, (struct sockaddr *) &sin, sizeof(sin))) {
683 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
684 				"Can't connect to %s:%d (%d:%s)",
685 				host, port, errno, pcap_strerror(errno));
686 		goto free_fail;
687 	}
688 
689 /* login */
690 	if (rpcap_send_request_auth(handle, username, password) < 0)
691 		goto close_fail;
692 	if (rpcap_send_request_open(handle, interface) < 0)
693 		goto close_fail;
694 	if (rpcap_send_request_start(handle, &(sin.sin_addr)) < 0)
695 		goto close_fail;
696 
697 	handle->buffer = malloc(handle->bufsize);
698 	if (!handle->buffer) {
699 		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
700 				"Can't allocate dump buffer: %s",
701 				pcap_strerror(errno));
702 		goto close_fail;
703 	}
704 
705 	if (handle->opt.rfmon) {
706 		/*
707 		 * Monitor mode doesn't apply to rpcap.
708 		 */
709 		rpcap_cleanup(handle);
710 		return PCAP_ERROR_RFMON_NOTSUP;
711 	}
712 
713 	if (handle->opt.buffer_size != 0) {
714 		/*
715 		 * Set the socket buffer size to the specified value.
716 		 */
717 		if (setsockopt(handle->selectable_fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
718 			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno));
719 			goto close_fail;
720 		}
721 	}
722 	free(username);
723 	free(password);
724 	free(host);
725 
726 	return 0;
727 
728 close_fail:
729 	rpcap_cleanup(handle);
730 free_fail:
731 	free(username);
732 	free(password);
733 	free(host);
734 	return PCAP_ERROR;
735 }
736 
737 pcap_t *
738 rpcap_create(const char *device, char *err_str, int *is_ours)
739 {
740 	const char *cp = device;
741 	pcap_t *p;
742 
743 	if (strncmp(cp, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0)
744 		cp += strlen(RPCAP_IFACE);
745 	else {
746 		*is_ours = 0;
747 		return NULL;
748 	}
749 
750 	if (*cp == '\0') {
751 		*is_ours = 0;
752 		return NULL;
753 	}
754 
755 	*is_ours = 1;
756 
757 	p = pcapint_create_common(__UNCONST(device), 16384, 0);
758 	if (p == NULL)
759 		return NULL;
760 
761 	p->activate_op = rpcap_activate;
762 	return p;
763 }
764 
765