summaryrefslogtreecommitdiff
path: root/dist/ipf/samples/proxy.c
blob: 6476945a999f8c8a61eda3bb78a5bbe8147d8ab0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*	$NetBSD: proxy.c,v 1.2 2000/05/03 11:40:20 veego Exp $	*/

/*
 * Sample transparent proxy program.
 *
 * Sample implementation of a program which intercepts a TCP connectiona and
 * just echos all data back to the origin.  Written to work via inetd as a
 * "nonwait" program running as root; ie.
 * tcpmux          stream  tcp     nowait root /usr/local/bin/proxy proxy
 * with a NAT rue like this:
 * rdr smc0 0/0 port 80 -> 127.0.0.1/32 port 1
 */
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <syslog.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#else
#include <sys/byteorder.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#if defined(sun) && (defined(__svr4__) || defined(__SVR4))
# include <sys/ioccom.h>
# include <sys/sysmacros.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include <ctype.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
#include "netinet/ip_proxy.h"
#include "netinet/ip_nat.h"


main(argc, argv)
int argc;
char *argv[];
{
	struct	sockaddr_in	sin, sloc, sout;
	natlookup_t	natlook;
	natlookup_t	*natlookp = &natlook;
	char	buffer[512];
	int	namelen, fd, n;

	/*
	 * get IP# and port # of the remote end of the connection (at the
	 * origin).
	 */
	namelen = sizeof(sin);
	if (getpeername(0, (struct sockaddr *)&sin, &namelen) == -1) {
		perror("getpeername");
		exit(-1);
	}

	/*
	 * get IP# and port # of the local end of the connection (at the
	 * man-in-the-middle).
	 */
	namelen = sizeof(sin);
	if (getsockname(0, (struct sockaddr *)&sloc, &namelen) == -1) {
		perror("getsockname");
		exit(-1);
	}

	/*
	 * Build up the NAT natlookup structure.
	 */
	bzero((char *)&natlook, sizeof(natlook));
	natlook.nl_outip = sin.sin_addr;
	natlook.nl_inip = sloc.sin_addr;
	natlook.nl_flags = IPN_TCP;
	natlook.nl_outport = sin.sin_port;
	natlook.nl_inport = sloc.sin_port;

	/*
	 * Open the NAT device and lookup the mapping pair.
	 */
	fd = open(IPL_NAT, O_RDONLY);
	if (ioctl(fd, SIOCGNATL, &natlookp) == -1) {
		perror("ioctl");
		exit(-1);
	}
	close(fd);
	/*
	 * Log it
	 */
	syslog(LOG_DAEMON|LOG_INFO, "connect to %s,%d",
		inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport));
	printf("connect to %s,%d\n",
		inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport));

	/*
	 * Just echo data read in from stdin to stdout
	 */
	while ((n = read(0, buffer, sizeof(buffer))) > 0)
		if (write(1, buffer, n) != n)
			break;
	close(0);
}