1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3*86d7f5d3SJohn Marino * All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino * are met:
8*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino *
14*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino * SUCH DAMAGE.
25*86d7f5d3SJohn Marino *
26*86d7f5d3SJohn Marino * $FreeBSD: src/lib/libalias/alias_proxy.c,v 1.4.2.5 2001/11/03 11:34:33 brian Exp $
27*86d7f5d3SJohn Marino * $DragonFly: src/lib/libalias/alias_proxy.c,v 1.3 2004/08/20 00:08:17 joerg Exp $
28*86d7f5d3SJohn Marino */
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /* file: alias_proxy.c
31*86d7f5d3SJohn Marino
32*86d7f5d3SJohn Marino This file encapsulates special operations related to transparent
33*86d7f5d3SJohn Marino proxy redirection. This is where packets with a particular destination,
34*86d7f5d3SJohn Marino usually tcp port 80, are redirected to a proxy server.
35*86d7f5d3SJohn Marino
36*86d7f5d3SJohn Marino When packets are proxied, the destination address and port are
37*86d7f5d3SJohn Marino modified. In certain cases, it is necessary to somehow encode
38*86d7f5d3SJohn Marino the original address/port info into the packet. Two methods are
39*86d7f5d3SJohn Marino presently supported: addition of a [DEST addr port] string at the
40*86d7f5d3SJohn Marino beginning a of tcp stream, or inclusion of an optional field
41*86d7f5d3SJohn Marino in the IP header.
42*86d7f5d3SJohn Marino
43*86d7f5d3SJohn Marino There is one public API function:
44*86d7f5d3SJohn Marino
45*86d7f5d3SJohn Marino PacketAliasProxyRule() -- Adds and deletes proxy
46*86d7f5d3SJohn Marino rules.
47*86d7f5d3SJohn Marino
48*86d7f5d3SJohn Marino Rules are stored in a linear linked list, so lookup efficiency
49*86d7f5d3SJohn Marino won't be too good for large lists.
50*86d7f5d3SJohn Marino
51*86d7f5d3SJohn Marino
52*86d7f5d3SJohn Marino Initial development: April, 1998 (cjm)
53*86d7f5d3SJohn Marino */
54*86d7f5d3SJohn Marino
55*86d7f5d3SJohn Marino
56*86d7f5d3SJohn Marino /* System includes */
57*86d7f5d3SJohn Marino #include <sys/param.h>
58*86d7f5d3SJohn Marino #include <sys/socket.h>
59*86d7f5d3SJohn Marino
60*86d7f5d3SJohn Marino #include <ctype.h>
61*86d7f5d3SJohn Marino #include <stdio.h>
62*86d7f5d3SJohn Marino #include <stdlib.h>
63*86d7f5d3SJohn Marino #include <string.h>
64*86d7f5d3SJohn Marino #include <netdb.h>
65*86d7f5d3SJohn Marino
66*86d7f5d3SJohn Marino /* BSD IPV4 includes */
67*86d7f5d3SJohn Marino #include <netinet/in_systm.h>
68*86d7f5d3SJohn Marino #include <netinet/in.h>
69*86d7f5d3SJohn Marino #include <netinet/ip.h>
70*86d7f5d3SJohn Marino #include <netinet/tcp.h>
71*86d7f5d3SJohn Marino
72*86d7f5d3SJohn Marino #include <arpa/inet.h>
73*86d7f5d3SJohn Marino
74*86d7f5d3SJohn Marino #include "alias_local.h" /* Functions used by alias*.c */
75*86d7f5d3SJohn Marino #include "alias.h" /* Public API functions for libalias */
76*86d7f5d3SJohn Marino
77*86d7f5d3SJohn Marino
78*86d7f5d3SJohn Marino
79*86d7f5d3SJohn Marino /*
80*86d7f5d3SJohn Marino Data structures
81*86d7f5d3SJohn Marino */
82*86d7f5d3SJohn Marino
83*86d7f5d3SJohn Marino /*
84*86d7f5d3SJohn Marino * A linked list of arbitrary length, based on struct proxy_entry is
85*86d7f5d3SJohn Marino * used to store proxy rules.
86*86d7f5d3SJohn Marino */
87*86d7f5d3SJohn Marino struct proxy_entry
88*86d7f5d3SJohn Marino {
89*86d7f5d3SJohn Marino #define PROXY_TYPE_ENCODE_NONE 1
90*86d7f5d3SJohn Marino #define PROXY_TYPE_ENCODE_TCPSTREAM 2
91*86d7f5d3SJohn Marino #define PROXY_TYPE_ENCODE_IPHDR 3
92*86d7f5d3SJohn Marino int rule_index;
93*86d7f5d3SJohn Marino int proxy_type;
94*86d7f5d3SJohn Marino u_char proto;
95*86d7f5d3SJohn Marino u_short proxy_port;
96*86d7f5d3SJohn Marino u_short server_port;
97*86d7f5d3SJohn Marino
98*86d7f5d3SJohn Marino struct in_addr server_addr;
99*86d7f5d3SJohn Marino
100*86d7f5d3SJohn Marino struct in_addr src_addr;
101*86d7f5d3SJohn Marino struct in_addr src_mask;
102*86d7f5d3SJohn Marino
103*86d7f5d3SJohn Marino struct in_addr dst_addr;
104*86d7f5d3SJohn Marino struct in_addr dst_mask;
105*86d7f5d3SJohn Marino
106*86d7f5d3SJohn Marino struct proxy_entry *next;
107*86d7f5d3SJohn Marino struct proxy_entry *last;
108*86d7f5d3SJohn Marino };
109*86d7f5d3SJohn Marino
110*86d7f5d3SJohn Marino
111*86d7f5d3SJohn Marino
112*86d7f5d3SJohn Marino /*
113*86d7f5d3SJohn Marino File scope variables
114*86d7f5d3SJohn Marino */
115*86d7f5d3SJohn Marino
116*86d7f5d3SJohn Marino static struct proxy_entry *proxyList;
117*86d7f5d3SJohn Marino
118*86d7f5d3SJohn Marino
119*86d7f5d3SJohn Marino
120*86d7f5d3SJohn Marino /* Local (static) functions:
121*86d7f5d3SJohn Marino
122*86d7f5d3SJohn Marino IpMask() -- Utility function for creating IP
123*86d7f5d3SJohn Marino masks from integer (1-32) specification.
124*86d7f5d3SJohn Marino IpAddr() -- Utility function for converting string
125*86d7f5d3SJohn Marino to IP address
126*86d7f5d3SJohn Marino IpPort() -- Utility function for converting string
127*86d7f5d3SJohn Marino to port number
128*86d7f5d3SJohn Marino RuleAdd() -- Adds an element to the rule list.
129*86d7f5d3SJohn Marino RuleDelete() -- Removes an element from the rule list.
130*86d7f5d3SJohn Marino RuleNumberDelete() -- Removes all elements from the rule list
131*86d7f5d3SJohn Marino having a certain rule number.
132*86d7f5d3SJohn Marino ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
133*86d7f5d3SJohn Marino of a TCP stream.
134*86d7f5d3SJohn Marino ProxyEncodeIpHeader() -- Adds an IP option indicating the true
135*86d7f5d3SJohn Marino destination of a proxied IP packet
136*86d7f5d3SJohn Marino */
137*86d7f5d3SJohn Marino
138*86d7f5d3SJohn Marino static int IpMask(int, struct in_addr *);
139*86d7f5d3SJohn Marino static int IpAddr(char *, struct in_addr *);
140*86d7f5d3SJohn Marino static int IpPort(char *, int, int *);
141*86d7f5d3SJohn Marino static void RuleAdd(struct proxy_entry *);
142*86d7f5d3SJohn Marino static void RuleDelete(struct proxy_entry *);
143*86d7f5d3SJohn Marino static int RuleNumberDelete(int);
144*86d7f5d3SJohn Marino static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
145*86d7f5d3SJohn Marino static void ProxyEncodeIpHeader(struct ip *, int);
146*86d7f5d3SJohn Marino
147*86d7f5d3SJohn Marino static int
IpMask(int nbits,struct in_addr * mask)148*86d7f5d3SJohn Marino IpMask(int nbits, struct in_addr *mask)
149*86d7f5d3SJohn Marino {
150*86d7f5d3SJohn Marino int i;
151*86d7f5d3SJohn Marino u_int imask;
152*86d7f5d3SJohn Marino
153*86d7f5d3SJohn Marino if (nbits < 0 || nbits > 32)
154*86d7f5d3SJohn Marino return -1;
155*86d7f5d3SJohn Marino
156*86d7f5d3SJohn Marino imask = 0;
157*86d7f5d3SJohn Marino for (i=0; i<nbits; i++)
158*86d7f5d3SJohn Marino imask = (imask >> 1) + 0x80000000;
159*86d7f5d3SJohn Marino mask->s_addr = htonl(imask);
160*86d7f5d3SJohn Marino
161*86d7f5d3SJohn Marino return 0;
162*86d7f5d3SJohn Marino }
163*86d7f5d3SJohn Marino
164*86d7f5d3SJohn Marino static int
IpAddr(char * s,struct in_addr * addr)165*86d7f5d3SJohn Marino IpAddr(char *s, struct in_addr *addr)
166*86d7f5d3SJohn Marino {
167*86d7f5d3SJohn Marino if (inet_aton(s, addr) == 0)
168*86d7f5d3SJohn Marino return -1;
169*86d7f5d3SJohn Marino else
170*86d7f5d3SJohn Marino return 0;
171*86d7f5d3SJohn Marino }
172*86d7f5d3SJohn Marino
173*86d7f5d3SJohn Marino static int
IpPort(char * s,int proto,int * port)174*86d7f5d3SJohn Marino IpPort(char *s, int proto, int *port)
175*86d7f5d3SJohn Marino {
176*86d7f5d3SJohn Marino int n;
177*86d7f5d3SJohn Marino
178*86d7f5d3SJohn Marino n = sscanf(s, "%d", port);
179*86d7f5d3SJohn Marino if (n != 1)
180*86d7f5d3SJohn Marino {
181*86d7f5d3SJohn Marino struct servent *se;
182*86d7f5d3SJohn Marino
183*86d7f5d3SJohn Marino if (proto == IPPROTO_TCP)
184*86d7f5d3SJohn Marino se = getservbyname(s, "tcp");
185*86d7f5d3SJohn Marino else if (proto == IPPROTO_UDP)
186*86d7f5d3SJohn Marino se = getservbyname(s, "udp");
187*86d7f5d3SJohn Marino else
188*86d7f5d3SJohn Marino return -1;
189*86d7f5d3SJohn Marino
190*86d7f5d3SJohn Marino if (se == NULL)
191*86d7f5d3SJohn Marino return -1;
192*86d7f5d3SJohn Marino
193*86d7f5d3SJohn Marino *port = (u_int) ntohs(se->s_port);
194*86d7f5d3SJohn Marino }
195*86d7f5d3SJohn Marino
196*86d7f5d3SJohn Marino return 0;
197*86d7f5d3SJohn Marino }
198*86d7f5d3SJohn Marino
199*86d7f5d3SJohn Marino void
RuleAdd(struct proxy_entry * entry)200*86d7f5d3SJohn Marino RuleAdd(struct proxy_entry *entry)
201*86d7f5d3SJohn Marino {
202*86d7f5d3SJohn Marino int rule_index;
203*86d7f5d3SJohn Marino struct proxy_entry *ptr;
204*86d7f5d3SJohn Marino struct proxy_entry *ptr_last;
205*86d7f5d3SJohn Marino
206*86d7f5d3SJohn Marino if (proxyList == NULL)
207*86d7f5d3SJohn Marino {
208*86d7f5d3SJohn Marino proxyList = entry;
209*86d7f5d3SJohn Marino entry->last = NULL;
210*86d7f5d3SJohn Marino entry->next = NULL;
211*86d7f5d3SJohn Marino return;
212*86d7f5d3SJohn Marino }
213*86d7f5d3SJohn Marino
214*86d7f5d3SJohn Marino rule_index = entry->rule_index;
215*86d7f5d3SJohn Marino ptr = proxyList;
216*86d7f5d3SJohn Marino ptr_last = NULL;
217*86d7f5d3SJohn Marino while (ptr != NULL)
218*86d7f5d3SJohn Marino {
219*86d7f5d3SJohn Marino if (ptr->rule_index >= rule_index)
220*86d7f5d3SJohn Marino {
221*86d7f5d3SJohn Marino if (ptr_last == NULL)
222*86d7f5d3SJohn Marino {
223*86d7f5d3SJohn Marino entry->next = proxyList;
224*86d7f5d3SJohn Marino entry->last = NULL;
225*86d7f5d3SJohn Marino proxyList->last = entry;
226*86d7f5d3SJohn Marino proxyList = entry;
227*86d7f5d3SJohn Marino return;
228*86d7f5d3SJohn Marino }
229*86d7f5d3SJohn Marino
230*86d7f5d3SJohn Marino ptr_last->next = entry;
231*86d7f5d3SJohn Marino ptr->last = entry;
232*86d7f5d3SJohn Marino entry->last = ptr->last;
233*86d7f5d3SJohn Marino entry->next = ptr;
234*86d7f5d3SJohn Marino return;
235*86d7f5d3SJohn Marino }
236*86d7f5d3SJohn Marino ptr_last = ptr;
237*86d7f5d3SJohn Marino ptr = ptr->next;
238*86d7f5d3SJohn Marino }
239*86d7f5d3SJohn Marino
240*86d7f5d3SJohn Marino ptr_last->next = entry;
241*86d7f5d3SJohn Marino entry->last = ptr_last;
242*86d7f5d3SJohn Marino entry->next = NULL;
243*86d7f5d3SJohn Marino }
244*86d7f5d3SJohn Marino
245*86d7f5d3SJohn Marino static void
RuleDelete(struct proxy_entry * entry)246*86d7f5d3SJohn Marino RuleDelete(struct proxy_entry *entry)
247*86d7f5d3SJohn Marino {
248*86d7f5d3SJohn Marino if (entry->last != NULL)
249*86d7f5d3SJohn Marino entry->last->next = entry->next;
250*86d7f5d3SJohn Marino else
251*86d7f5d3SJohn Marino proxyList = entry->next;
252*86d7f5d3SJohn Marino
253*86d7f5d3SJohn Marino if (entry->next != NULL)
254*86d7f5d3SJohn Marino entry->next->last = entry->last;
255*86d7f5d3SJohn Marino
256*86d7f5d3SJohn Marino free(entry);
257*86d7f5d3SJohn Marino }
258*86d7f5d3SJohn Marino
259*86d7f5d3SJohn Marino static int
RuleNumberDelete(int rule_index)260*86d7f5d3SJohn Marino RuleNumberDelete(int rule_index)
261*86d7f5d3SJohn Marino {
262*86d7f5d3SJohn Marino int err;
263*86d7f5d3SJohn Marino struct proxy_entry *ptr;
264*86d7f5d3SJohn Marino
265*86d7f5d3SJohn Marino err = -1;
266*86d7f5d3SJohn Marino ptr = proxyList;
267*86d7f5d3SJohn Marino while (ptr != NULL)
268*86d7f5d3SJohn Marino {
269*86d7f5d3SJohn Marino struct proxy_entry *ptr_next;
270*86d7f5d3SJohn Marino
271*86d7f5d3SJohn Marino ptr_next = ptr->next;
272*86d7f5d3SJohn Marino if (ptr->rule_index == rule_index)
273*86d7f5d3SJohn Marino {
274*86d7f5d3SJohn Marino err = 0;
275*86d7f5d3SJohn Marino RuleDelete(ptr);
276*86d7f5d3SJohn Marino }
277*86d7f5d3SJohn Marino
278*86d7f5d3SJohn Marino ptr = ptr_next;
279*86d7f5d3SJohn Marino }
280*86d7f5d3SJohn Marino
281*86d7f5d3SJohn Marino return err;
282*86d7f5d3SJohn Marino }
283*86d7f5d3SJohn Marino
284*86d7f5d3SJohn Marino static void
ProxyEncodeTcpStream(struct alias_link * link,struct ip * pip,int maxpacketsize)285*86d7f5d3SJohn Marino ProxyEncodeTcpStream(struct alias_link *link,
286*86d7f5d3SJohn Marino struct ip *pip,
287*86d7f5d3SJohn Marino int maxpacketsize)
288*86d7f5d3SJohn Marino {
289*86d7f5d3SJohn Marino int slen;
290*86d7f5d3SJohn Marino char buffer[40];
291*86d7f5d3SJohn Marino struct tcphdr *tc;
292*86d7f5d3SJohn Marino
293*86d7f5d3SJohn Marino /* Compute pointer to tcp header */
294*86d7f5d3SJohn Marino tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
295*86d7f5d3SJohn Marino
296*86d7f5d3SJohn Marino /* Don't modify if once already modified */
297*86d7f5d3SJohn Marino
298*86d7f5d3SJohn Marino if (GetAckModified (link))
299*86d7f5d3SJohn Marino return;
300*86d7f5d3SJohn Marino
301*86d7f5d3SJohn Marino /* Translate destination address and port to string form */
302*86d7f5d3SJohn Marino snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
303*86d7f5d3SJohn Marino inet_ntoa(GetProxyAddress (link)), (u_int) ntohs(GetProxyPort (link)));
304*86d7f5d3SJohn Marino
305*86d7f5d3SJohn Marino /* Pad string out to a multiple of two in length */
306*86d7f5d3SJohn Marino slen = strlen(buffer);
307*86d7f5d3SJohn Marino switch (slen % 2)
308*86d7f5d3SJohn Marino {
309*86d7f5d3SJohn Marino case 0:
310*86d7f5d3SJohn Marino strcat(buffer, " \n");
311*86d7f5d3SJohn Marino slen += 2;
312*86d7f5d3SJohn Marino break;
313*86d7f5d3SJohn Marino case 1:
314*86d7f5d3SJohn Marino strcat(buffer, "\n");
315*86d7f5d3SJohn Marino slen += 1;
316*86d7f5d3SJohn Marino }
317*86d7f5d3SJohn Marino
318*86d7f5d3SJohn Marino /* Check for packet overflow */
319*86d7f5d3SJohn Marino if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
320*86d7f5d3SJohn Marino return;
321*86d7f5d3SJohn Marino
322*86d7f5d3SJohn Marino /* Shift existing TCP data and insert destination string */
323*86d7f5d3SJohn Marino {
324*86d7f5d3SJohn Marino int dlen;
325*86d7f5d3SJohn Marino int hlen;
326*86d7f5d3SJohn Marino u_char *p;
327*86d7f5d3SJohn Marino
328*86d7f5d3SJohn Marino hlen = (pip->ip_hl + tc->th_off) << 2;
329*86d7f5d3SJohn Marino dlen = ntohs (pip->ip_len) - hlen;
330*86d7f5d3SJohn Marino
331*86d7f5d3SJohn Marino /* Modify first packet that has data in it */
332*86d7f5d3SJohn Marino
333*86d7f5d3SJohn Marino if (dlen == 0)
334*86d7f5d3SJohn Marino return;
335*86d7f5d3SJohn Marino
336*86d7f5d3SJohn Marino p = (char *) pip;
337*86d7f5d3SJohn Marino p += hlen;
338*86d7f5d3SJohn Marino
339*86d7f5d3SJohn Marino memmove(p + slen, p, dlen);
340*86d7f5d3SJohn Marino memcpy(p, buffer, slen);
341*86d7f5d3SJohn Marino }
342*86d7f5d3SJohn Marino
343*86d7f5d3SJohn Marino /* Save information about modfied sequence number */
344*86d7f5d3SJohn Marino {
345*86d7f5d3SJohn Marino int delta;
346*86d7f5d3SJohn Marino
347*86d7f5d3SJohn Marino SetAckModified(link);
348*86d7f5d3SJohn Marino delta = GetDeltaSeqOut(pip, link);
349*86d7f5d3SJohn Marino AddSeq(pip, link, delta+slen);
350*86d7f5d3SJohn Marino }
351*86d7f5d3SJohn Marino
352*86d7f5d3SJohn Marino /* Update IP header packet length and checksum */
353*86d7f5d3SJohn Marino {
354*86d7f5d3SJohn Marino int accumulate;
355*86d7f5d3SJohn Marino
356*86d7f5d3SJohn Marino accumulate = pip->ip_len;
357*86d7f5d3SJohn Marino pip->ip_len = htons(ntohs(pip->ip_len) + slen);
358*86d7f5d3SJohn Marino accumulate -= pip->ip_len;
359*86d7f5d3SJohn Marino
360*86d7f5d3SJohn Marino ADJUST_CHECKSUM(accumulate, pip->ip_sum);
361*86d7f5d3SJohn Marino }
362*86d7f5d3SJohn Marino
363*86d7f5d3SJohn Marino /* Update TCP checksum, Use TcpChecksum since so many things have
364*86d7f5d3SJohn Marino already changed. */
365*86d7f5d3SJohn Marino
366*86d7f5d3SJohn Marino tc->th_sum = 0;
367*86d7f5d3SJohn Marino tc->th_sum = TcpChecksum (pip);
368*86d7f5d3SJohn Marino }
369*86d7f5d3SJohn Marino
370*86d7f5d3SJohn Marino static void
ProxyEncodeIpHeader(struct ip * pip,int maxpacketsize)371*86d7f5d3SJohn Marino ProxyEncodeIpHeader(struct ip *pip,
372*86d7f5d3SJohn Marino int maxpacketsize)
373*86d7f5d3SJohn Marino {
374*86d7f5d3SJohn Marino #define OPTION_LEN_BYTES 8
375*86d7f5d3SJohn Marino #define OPTION_LEN_INT16 4
376*86d7f5d3SJohn Marino #define OPTION_LEN_INT32 2
377*86d7f5d3SJohn Marino u_char option[OPTION_LEN_BYTES];
378*86d7f5d3SJohn Marino
379*86d7f5d3SJohn Marino #ifdef DEBUG
380*86d7f5d3SJohn Marino fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
381*86d7f5d3SJohn Marino fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
382*86d7f5d3SJohn Marino #endif
383*86d7f5d3SJohn Marino
384*86d7f5d3SJohn Marino /* Check to see that there is room to add an IP option */
385*86d7f5d3SJohn Marino if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
386*86d7f5d3SJohn Marino return;
387*86d7f5d3SJohn Marino
388*86d7f5d3SJohn Marino /* Build option and copy into packet */
389*86d7f5d3SJohn Marino {
390*86d7f5d3SJohn Marino u_char *ptr;
391*86d7f5d3SJohn Marino struct tcphdr *tc;
392*86d7f5d3SJohn Marino
393*86d7f5d3SJohn Marino ptr = (u_char *) pip;
394*86d7f5d3SJohn Marino ptr += 20;
395*86d7f5d3SJohn Marino memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
396*86d7f5d3SJohn Marino
397*86d7f5d3SJohn Marino option[0] = 0x64; /* class: 3 (reserved), option 4 */
398*86d7f5d3SJohn Marino option[1] = OPTION_LEN_BYTES;
399*86d7f5d3SJohn Marino
400*86d7f5d3SJohn Marino memcpy(&option[2], (u_char *) &pip->ip_dst, 4);
401*86d7f5d3SJohn Marino
402*86d7f5d3SJohn Marino tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
403*86d7f5d3SJohn Marino memcpy(&option[6], (u_char *) &tc->th_sport, 2);
404*86d7f5d3SJohn Marino
405*86d7f5d3SJohn Marino memcpy(ptr, option, 8);
406*86d7f5d3SJohn Marino }
407*86d7f5d3SJohn Marino
408*86d7f5d3SJohn Marino /* Update checksum, header length and packet length */
409*86d7f5d3SJohn Marino {
410*86d7f5d3SJohn Marino int i;
411*86d7f5d3SJohn Marino int accumulate;
412*86d7f5d3SJohn Marino u_short *sptr;
413*86d7f5d3SJohn Marino
414*86d7f5d3SJohn Marino sptr = (u_short *) option;
415*86d7f5d3SJohn Marino accumulate = 0;
416*86d7f5d3SJohn Marino for (i=0; i<OPTION_LEN_INT16; i++)
417*86d7f5d3SJohn Marino accumulate -= *(sptr++);
418*86d7f5d3SJohn Marino
419*86d7f5d3SJohn Marino sptr = (u_short *) pip;
420*86d7f5d3SJohn Marino accumulate += *sptr;
421*86d7f5d3SJohn Marino pip->ip_hl += OPTION_LEN_INT32;
422*86d7f5d3SJohn Marino accumulate -= *sptr;
423*86d7f5d3SJohn Marino
424*86d7f5d3SJohn Marino accumulate += pip->ip_len;
425*86d7f5d3SJohn Marino pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
426*86d7f5d3SJohn Marino accumulate -= pip->ip_len;
427*86d7f5d3SJohn Marino
428*86d7f5d3SJohn Marino ADJUST_CHECKSUM(accumulate, pip->ip_sum);
429*86d7f5d3SJohn Marino }
430*86d7f5d3SJohn Marino #undef OPTION_LEN_BYTES
431*86d7f5d3SJohn Marino #undef OPTION_LEN_INT16
432*86d7f5d3SJohn Marino #undef OPTION_LEN_INT32
433*86d7f5d3SJohn Marino #ifdef DEBUG
434*86d7f5d3SJohn Marino fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
435*86d7f5d3SJohn Marino fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
436*86d7f5d3SJohn Marino #endif
437*86d7f5d3SJohn Marino }
438*86d7f5d3SJohn Marino
439*86d7f5d3SJohn Marino
440*86d7f5d3SJohn Marino /* Functions by other packet alias source files
441*86d7f5d3SJohn Marino
442*86d7f5d3SJohn Marino ProxyCheck() -- Checks whether an outgoing packet should
443*86d7f5d3SJohn Marino be proxied.
444*86d7f5d3SJohn Marino ProxyModify() -- Encodes the original destination address/port
445*86d7f5d3SJohn Marino for a packet which is to be redirected to
446*86d7f5d3SJohn Marino a proxy server.
447*86d7f5d3SJohn Marino */
448*86d7f5d3SJohn Marino
449*86d7f5d3SJohn Marino int
ProxyCheck(struct ip * pip,struct in_addr * proxy_server_addr,u_short * proxy_server_port)450*86d7f5d3SJohn Marino ProxyCheck(struct ip *pip,
451*86d7f5d3SJohn Marino struct in_addr *proxy_server_addr,
452*86d7f5d3SJohn Marino u_short *proxy_server_port)
453*86d7f5d3SJohn Marino {
454*86d7f5d3SJohn Marino u_short dst_port;
455*86d7f5d3SJohn Marino struct in_addr src_addr;
456*86d7f5d3SJohn Marino struct in_addr dst_addr;
457*86d7f5d3SJohn Marino struct proxy_entry *ptr;
458*86d7f5d3SJohn Marino
459*86d7f5d3SJohn Marino src_addr = pip->ip_src;
460*86d7f5d3SJohn Marino dst_addr = pip->ip_dst;
461*86d7f5d3SJohn Marino dst_port = ((struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)))
462*86d7f5d3SJohn Marino ->th_dport;
463*86d7f5d3SJohn Marino
464*86d7f5d3SJohn Marino ptr = proxyList;
465*86d7f5d3SJohn Marino while (ptr != NULL)
466*86d7f5d3SJohn Marino {
467*86d7f5d3SJohn Marino u_short proxy_port;
468*86d7f5d3SJohn Marino
469*86d7f5d3SJohn Marino proxy_port = ptr->proxy_port;
470*86d7f5d3SJohn Marino if ((dst_port == proxy_port || proxy_port == 0)
471*86d7f5d3SJohn Marino && pip->ip_p == ptr->proto
472*86d7f5d3SJohn Marino && src_addr.s_addr != ptr->server_addr.s_addr)
473*86d7f5d3SJohn Marino {
474*86d7f5d3SJohn Marino struct in_addr src_addr_masked;
475*86d7f5d3SJohn Marino struct in_addr dst_addr_masked;
476*86d7f5d3SJohn Marino
477*86d7f5d3SJohn Marino src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
478*86d7f5d3SJohn Marino dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
479*86d7f5d3SJohn Marino
480*86d7f5d3SJohn Marino if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
481*86d7f5d3SJohn Marino && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr))
482*86d7f5d3SJohn Marino {
483*86d7f5d3SJohn Marino if ((*proxy_server_port = ptr->server_port) == 0)
484*86d7f5d3SJohn Marino *proxy_server_port = dst_port;
485*86d7f5d3SJohn Marino *proxy_server_addr = ptr->server_addr;
486*86d7f5d3SJohn Marino return ptr->proxy_type;
487*86d7f5d3SJohn Marino }
488*86d7f5d3SJohn Marino }
489*86d7f5d3SJohn Marino ptr = ptr->next;
490*86d7f5d3SJohn Marino }
491*86d7f5d3SJohn Marino
492*86d7f5d3SJohn Marino return 0;
493*86d7f5d3SJohn Marino }
494*86d7f5d3SJohn Marino
495*86d7f5d3SJohn Marino void
ProxyModify(struct alias_link * link,struct ip * pip,int maxpacketsize,int proxy_type)496*86d7f5d3SJohn Marino ProxyModify(struct alias_link *link,
497*86d7f5d3SJohn Marino struct ip *pip,
498*86d7f5d3SJohn Marino int maxpacketsize,
499*86d7f5d3SJohn Marino int proxy_type)
500*86d7f5d3SJohn Marino {
501*86d7f5d3SJohn Marino switch (proxy_type)
502*86d7f5d3SJohn Marino {
503*86d7f5d3SJohn Marino case PROXY_TYPE_ENCODE_IPHDR:
504*86d7f5d3SJohn Marino ProxyEncodeIpHeader(pip, maxpacketsize);
505*86d7f5d3SJohn Marino break;
506*86d7f5d3SJohn Marino
507*86d7f5d3SJohn Marino case PROXY_TYPE_ENCODE_TCPSTREAM:
508*86d7f5d3SJohn Marino ProxyEncodeTcpStream(link, pip, maxpacketsize);
509*86d7f5d3SJohn Marino break;
510*86d7f5d3SJohn Marino }
511*86d7f5d3SJohn Marino }
512*86d7f5d3SJohn Marino
513*86d7f5d3SJohn Marino
514*86d7f5d3SJohn Marino /*
515*86d7f5d3SJohn Marino Public API functions
516*86d7f5d3SJohn Marino */
517*86d7f5d3SJohn Marino
518*86d7f5d3SJohn Marino int
PacketAliasProxyRule(const char * cmd)519*86d7f5d3SJohn Marino PacketAliasProxyRule(const char *cmd)
520*86d7f5d3SJohn Marino {
521*86d7f5d3SJohn Marino /*
522*86d7f5d3SJohn Marino * This function takes command strings of the form:
523*86d7f5d3SJohn Marino *
524*86d7f5d3SJohn Marino * server <addr>[:<port>]
525*86d7f5d3SJohn Marino * [port <port>]
526*86d7f5d3SJohn Marino * [rule n]
527*86d7f5d3SJohn Marino * [proto tcp|udp]
528*86d7f5d3SJohn Marino * [src <addr>[/n]]
529*86d7f5d3SJohn Marino * [dst <addr>[/n]]
530*86d7f5d3SJohn Marino * [type encode_tcp_stream|encode_ip_hdr|no_encode]
531*86d7f5d3SJohn Marino *
532*86d7f5d3SJohn Marino * delete <rule number>
533*86d7f5d3SJohn Marino *
534*86d7f5d3SJohn Marino * Subfields can be in arbitrary order. Port numbers and addresses
535*86d7f5d3SJohn Marino * must be in either numeric or symbolic form. An optional rule number
536*86d7f5d3SJohn Marino * is used to control the order in which rules are searched. If two
537*86d7f5d3SJohn Marino * rules have the same number, then search order cannot be guaranteed,
538*86d7f5d3SJohn Marino * and the rules should be disjoint. If no rule number is specified,
539*86d7f5d3SJohn Marino * then 0 is used, and group 0 rules are always checked before any
540*86d7f5d3SJohn Marino * others.
541*86d7f5d3SJohn Marino */
542*86d7f5d3SJohn Marino int i, n, len;
543*86d7f5d3SJohn Marino int cmd_len;
544*86d7f5d3SJohn Marino int token_count;
545*86d7f5d3SJohn Marino int state;
546*86d7f5d3SJohn Marino char *token;
547*86d7f5d3SJohn Marino char buffer[256];
548*86d7f5d3SJohn Marino char str_port[sizeof(buffer)];
549*86d7f5d3SJohn Marino char str_server_port[sizeof(buffer)];
550*86d7f5d3SJohn Marino char *res = buffer;
551*86d7f5d3SJohn Marino
552*86d7f5d3SJohn Marino int rule_index;
553*86d7f5d3SJohn Marino int proto;
554*86d7f5d3SJohn Marino int proxy_type;
555*86d7f5d3SJohn Marino int proxy_port;
556*86d7f5d3SJohn Marino int server_port;
557*86d7f5d3SJohn Marino struct in_addr server_addr;
558*86d7f5d3SJohn Marino struct in_addr src_addr, src_mask;
559*86d7f5d3SJohn Marino struct in_addr dst_addr, dst_mask;
560*86d7f5d3SJohn Marino struct proxy_entry *proxy_entry;
561*86d7f5d3SJohn Marino
562*86d7f5d3SJohn Marino /* Copy command line into a buffer */
563*86d7f5d3SJohn Marino cmd += strspn(cmd, " \t");
564*86d7f5d3SJohn Marino cmd_len = strlen(cmd);
565*86d7f5d3SJohn Marino if (cmd_len > (sizeof(buffer) - 1))
566*86d7f5d3SJohn Marino return -1;
567*86d7f5d3SJohn Marino strcpy(buffer, cmd);
568*86d7f5d3SJohn Marino
569*86d7f5d3SJohn Marino /* Convert to lower case */
570*86d7f5d3SJohn Marino len = strlen(buffer);
571*86d7f5d3SJohn Marino for (i=0; i<len; i++)
572*86d7f5d3SJohn Marino buffer[i] = tolower((unsigned char)buffer[i]);
573*86d7f5d3SJohn Marino
574*86d7f5d3SJohn Marino /* Set default proxy type */
575*86d7f5d3SJohn Marino
576*86d7f5d3SJohn Marino /* Set up default values */
577*86d7f5d3SJohn Marino rule_index = 0;
578*86d7f5d3SJohn Marino proxy_type = PROXY_TYPE_ENCODE_NONE;
579*86d7f5d3SJohn Marino proto = IPPROTO_TCP;
580*86d7f5d3SJohn Marino proxy_port = 0;
581*86d7f5d3SJohn Marino server_addr.s_addr = 0;
582*86d7f5d3SJohn Marino server_port = 0;
583*86d7f5d3SJohn Marino src_addr.s_addr = 0;
584*86d7f5d3SJohn Marino IpMask(0, &src_mask);
585*86d7f5d3SJohn Marino dst_addr.s_addr = 0;
586*86d7f5d3SJohn Marino IpMask(0, &dst_mask);
587*86d7f5d3SJohn Marino
588*86d7f5d3SJohn Marino str_port[0] = 0;
589*86d7f5d3SJohn Marino str_server_port[0] = 0;
590*86d7f5d3SJohn Marino
591*86d7f5d3SJohn Marino /* Parse command string with state machine */
592*86d7f5d3SJohn Marino #define STATE_READ_KEYWORD 0
593*86d7f5d3SJohn Marino #define STATE_READ_TYPE 1
594*86d7f5d3SJohn Marino #define STATE_READ_PORT 2
595*86d7f5d3SJohn Marino #define STATE_READ_SERVER 3
596*86d7f5d3SJohn Marino #define STATE_READ_RULE 4
597*86d7f5d3SJohn Marino #define STATE_READ_DELETE 5
598*86d7f5d3SJohn Marino #define STATE_READ_PROTO 6
599*86d7f5d3SJohn Marino #define STATE_READ_SRC 7
600*86d7f5d3SJohn Marino #define STATE_READ_DST 8
601*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
602*86d7f5d3SJohn Marino token = strsep(&res, " \t");
603*86d7f5d3SJohn Marino token_count = 0;
604*86d7f5d3SJohn Marino while (token != NULL)
605*86d7f5d3SJohn Marino {
606*86d7f5d3SJohn Marino token_count++;
607*86d7f5d3SJohn Marino switch (state)
608*86d7f5d3SJohn Marino {
609*86d7f5d3SJohn Marino case STATE_READ_KEYWORD:
610*86d7f5d3SJohn Marino if (strcmp(token, "type") == 0)
611*86d7f5d3SJohn Marino state = STATE_READ_TYPE;
612*86d7f5d3SJohn Marino else if (strcmp(token, "port") == 0)
613*86d7f5d3SJohn Marino state = STATE_READ_PORT;
614*86d7f5d3SJohn Marino else if (strcmp(token, "server") == 0)
615*86d7f5d3SJohn Marino state = STATE_READ_SERVER;
616*86d7f5d3SJohn Marino else if (strcmp(token, "rule") == 0)
617*86d7f5d3SJohn Marino state = STATE_READ_RULE;
618*86d7f5d3SJohn Marino else if (strcmp(token, "delete") == 0)
619*86d7f5d3SJohn Marino state = STATE_READ_DELETE;
620*86d7f5d3SJohn Marino else if (strcmp(token, "proto") == 0)
621*86d7f5d3SJohn Marino state = STATE_READ_PROTO;
622*86d7f5d3SJohn Marino else if (strcmp(token, "src") == 0)
623*86d7f5d3SJohn Marino state = STATE_READ_SRC;
624*86d7f5d3SJohn Marino else if (strcmp(token, "dst") == 0)
625*86d7f5d3SJohn Marino state = STATE_READ_DST;
626*86d7f5d3SJohn Marino else
627*86d7f5d3SJohn Marino return -1;
628*86d7f5d3SJohn Marino break;
629*86d7f5d3SJohn Marino
630*86d7f5d3SJohn Marino case STATE_READ_TYPE:
631*86d7f5d3SJohn Marino if (strcmp(token, "encode_ip_hdr") == 0)
632*86d7f5d3SJohn Marino proxy_type = PROXY_TYPE_ENCODE_IPHDR;
633*86d7f5d3SJohn Marino else if (strcmp(token, "encode_tcp_stream") == 0)
634*86d7f5d3SJohn Marino proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
635*86d7f5d3SJohn Marino else if (strcmp(token, "no_encode") == 0)
636*86d7f5d3SJohn Marino proxy_type = PROXY_TYPE_ENCODE_NONE;
637*86d7f5d3SJohn Marino else
638*86d7f5d3SJohn Marino return -1;
639*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
640*86d7f5d3SJohn Marino break;
641*86d7f5d3SJohn Marino
642*86d7f5d3SJohn Marino case STATE_READ_PORT:
643*86d7f5d3SJohn Marino strcpy(str_port, token);
644*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
645*86d7f5d3SJohn Marino break;
646*86d7f5d3SJohn Marino
647*86d7f5d3SJohn Marino case STATE_READ_SERVER:
648*86d7f5d3SJohn Marino {
649*86d7f5d3SJohn Marino int err;
650*86d7f5d3SJohn Marino char *p;
651*86d7f5d3SJohn Marino char s[sizeof(buffer)];
652*86d7f5d3SJohn Marino
653*86d7f5d3SJohn Marino p = token;
654*86d7f5d3SJohn Marino while (*p != ':' && *p != 0)
655*86d7f5d3SJohn Marino p++;
656*86d7f5d3SJohn Marino
657*86d7f5d3SJohn Marino if (*p != ':')
658*86d7f5d3SJohn Marino {
659*86d7f5d3SJohn Marino err = IpAddr(token, &server_addr);
660*86d7f5d3SJohn Marino if (err)
661*86d7f5d3SJohn Marino return -1;
662*86d7f5d3SJohn Marino }
663*86d7f5d3SJohn Marino else
664*86d7f5d3SJohn Marino {
665*86d7f5d3SJohn Marino *p = ' ';
666*86d7f5d3SJohn Marino
667*86d7f5d3SJohn Marino n = sscanf(token, "%s %s", s, str_server_port);
668*86d7f5d3SJohn Marino if (n != 2)
669*86d7f5d3SJohn Marino return -1;
670*86d7f5d3SJohn Marino
671*86d7f5d3SJohn Marino err = IpAddr(s, &server_addr);
672*86d7f5d3SJohn Marino if (err)
673*86d7f5d3SJohn Marino return -1;
674*86d7f5d3SJohn Marino }
675*86d7f5d3SJohn Marino }
676*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
677*86d7f5d3SJohn Marino break;
678*86d7f5d3SJohn Marino
679*86d7f5d3SJohn Marino case STATE_READ_RULE:
680*86d7f5d3SJohn Marino n = sscanf(token, "%d", &rule_index);
681*86d7f5d3SJohn Marino if (n != 1 || rule_index < 0)
682*86d7f5d3SJohn Marino return -1;
683*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
684*86d7f5d3SJohn Marino break;
685*86d7f5d3SJohn Marino
686*86d7f5d3SJohn Marino case STATE_READ_DELETE:
687*86d7f5d3SJohn Marino {
688*86d7f5d3SJohn Marino int err;
689*86d7f5d3SJohn Marino int rule_to_delete;
690*86d7f5d3SJohn Marino
691*86d7f5d3SJohn Marino if (token_count != 2)
692*86d7f5d3SJohn Marino return -1;
693*86d7f5d3SJohn Marino
694*86d7f5d3SJohn Marino n = sscanf(token, "%d", &rule_to_delete);
695*86d7f5d3SJohn Marino if (n != 1)
696*86d7f5d3SJohn Marino return -1;
697*86d7f5d3SJohn Marino err = RuleNumberDelete(rule_to_delete);
698*86d7f5d3SJohn Marino if (err)
699*86d7f5d3SJohn Marino return -1;
700*86d7f5d3SJohn Marino return 0;
701*86d7f5d3SJohn Marino }
702*86d7f5d3SJohn Marino
703*86d7f5d3SJohn Marino case STATE_READ_PROTO:
704*86d7f5d3SJohn Marino if (strcmp(token, "tcp") == 0)
705*86d7f5d3SJohn Marino proto = IPPROTO_TCP;
706*86d7f5d3SJohn Marino else if (strcmp(token, "udp") == 0)
707*86d7f5d3SJohn Marino proto = IPPROTO_UDP;
708*86d7f5d3SJohn Marino else
709*86d7f5d3SJohn Marino return -1;
710*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
711*86d7f5d3SJohn Marino break;
712*86d7f5d3SJohn Marino
713*86d7f5d3SJohn Marino case STATE_READ_SRC:
714*86d7f5d3SJohn Marino case STATE_READ_DST:
715*86d7f5d3SJohn Marino {
716*86d7f5d3SJohn Marino int err;
717*86d7f5d3SJohn Marino char *p;
718*86d7f5d3SJohn Marino struct in_addr mask;
719*86d7f5d3SJohn Marino struct in_addr addr;
720*86d7f5d3SJohn Marino
721*86d7f5d3SJohn Marino p = token;
722*86d7f5d3SJohn Marino while (*p != '/' && *p != 0)
723*86d7f5d3SJohn Marino p++;
724*86d7f5d3SJohn Marino
725*86d7f5d3SJohn Marino if (*p != '/')
726*86d7f5d3SJohn Marino {
727*86d7f5d3SJohn Marino IpMask(32, &mask);
728*86d7f5d3SJohn Marino err = IpAddr(token, &addr);
729*86d7f5d3SJohn Marino if (err)
730*86d7f5d3SJohn Marino return -1;
731*86d7f5d3SJohn Marino }
732*86d7f5d3SJohn Marino else
733*86d7f5d3SJohn Marino {
734*86d7f5d3SJohn Marino int nbits;
735*86d7f5d3SJohn Marino char s[sizeof(buffer)];
736*86d7f5d3SJohn Marino
737*86d7f5d3SJohn Marino *p = ' ';
738*86d7f5d3SJohn Marino n = sscanf(token, "%s %d", s, &nbits);
739*86d7f5d3SJohn Marino if (n != 2)
740*86d7f5d3SJohn Marino return -1;
741*86d7f5d3SJohn Marino
742*86d7f5d3SJohn Marino err = IpAddr(s, &addr);
743*86d7f5d3SJohn Marino if (err)
744*86d7f5d3SJohn Marino return -1;
745*86d7f5d3SJohn Marino
746*86d7f5d3SJohn Marino err = IpMask(nbits, &mask);
747*86d7f5d3SJohn Marino if (err)
748*86d7f5d3SJohn Marino return -1;
749*86d7f5d3SJohn Marino }
750*86d7f5d3SJohn Marino
751*86d7f5d3SJohn Marino if (state == STATE_READ_SRC)
752*86d7f5d3SJohn Marino {
753*86d7f5d3SJohn Marino src_addr = addr;
754*86d7f5d3SJohn Marino src_mask = mask;
755*86d7f5d3SJohn Marino }
756*86d7f5d3SJohn Marino else
757*86d7f5d3SJohn Marino {
758*86d7f5d3SJohn Marino dst_addr = addr;
759*86d7f5d3SJohn Marino dst_mask = mask;
760*86d7f5d3SJohn Marino }
761*86d7f5d3SJohn Marino }
762*86d7f5d3SJohn Marino state = STATE_READ_KEYWORD;
763*86d7f5d3SJohn Marino break;
764*86d7f5d3SJohn Marino
765*86d7f5d3SJohn Marino default:
766*86d7f5d3SJohn Marino return -1;
767*86d7f5d3SJohn Marino break;
768*86d7f5d3SJohn Marino }
769*86d7f5d3SJohn Marino
770*86d7f5d3SJohn Marino do {
771*86d7f5d3SJohn Marino token = strsep(&res, " \t");
772*86d7f5d3SJohn Marino } while (token != NULL && !*token);
773*86d7f5d3SJohn Marino }
774*86d7f5d3SJohn Marino #undef STATE_READ_KEYWORD
775*86d7f5d3SJohn Marino #undef STATE_READ_TYPE
776*86d7f5d3SJohn Marino #undef STATE_READ_PORT
777*86d7f5d3SJohn Marino #undef STATE_READ_SERVER
778*86d7f5d3SJohn Marino #undef STATE_READ_RULE
779*86d7f5d3SJohn Marino #undef STATE_READ_DELETE
780*86d7f5d3SJohn Marino #undef STATE_READ_PROTO
781*86d7f5d3SJohn Marino #undef STATE_READ_SRC
782*86d7f5d3SJohn Marino #undef STATE_READ_DST
783*86d7f5d3SJohn Marino
784*86d7f5d3SJohn Marino /* Convert port strings to numbers. This needs to be done after
785*86d7f5d3SJohn Marino the string is parsed, because the prototype might not be designated
786*86d7f5d3SJohn Marino before the ports (which might be symbolic entries in /etc/services) */
787*86d7f5d3SJohn Marino
788*86d7f5d3SJohn Marino if (strlen(str_port) != 0)
789*86d7f5d3SJohn Marino {
790*86d7f5d3SJohn Marino int err;
791*86d7f5d3SJohn Marino
792*86d7f5d3SJohn Marino err = IpPort(str_port, proto, &proxy_port);
793*86d7f5d3SJohn Marino if (err)
794*86d7f5d3SJohn Marino return -1;
795*86d7f5d3SJohn Marino }
796*86d7f5d3SJohn Marino else
797*86d7f5d3SJohn Marino {
798*86d7f5d3SJohn Marino proxy_port = 0;
799*86d7f5d3SJohn Marino }
800*86d7f5d3SJohn Marino
801*86d7f5d3SJohn Marino if (strlen(str_server_port) != 0)
802*86d7f5d3SJohn Marino {
803*86d7f5d3SJohn Marino int err;
804*86d7f5d3SJohn Marino
805*86d7f5d3SJohn Marino err = IpPort(str_server_port, proto, &server_port);
806*86d7f5d3SJohn Marino if (err)
807*86d7f5d3SJohn Marino return -1;
808*86d7f5d3SJohn Marino }
809*86d7f5d3SJohn Marino else
810*86d7f5d3SJohn Marino {
811*86d7f5d3SJohn Marino server_port = 0;
812*86d7f5d3SJohn Marino }
813*86d7f5d3SJohn Marino
814*86d7f5d3SJohn Marino /* Check that at least the server address has been defined */
815*86d7f5d3SJohn Marino if (server_addr.s_addr == 0)
816*86d7f5d3SJohn Marino return -1;
817*86d7f5d3SJohn Marino
818*86d7f5d3SJohn Marino /* Add to linked list */
819*86d7f5d3SJohn Marino proxy_entry = malloc(sizeof(struct proxy_entry));
820*86d7f5d3SJohn Marino if (proxy_entry == NULL)
821*86d7f5d3SJohn Marino return -1;
822*86d7f5d3SJohn Marino
823*86d7f5d3SJohn Marino proxy_entry->proxy_type = proxy_type;
824*86d7f5d3SJohn Marino proxy_entry->rule_index = rule_index;
825*86d7f5d3SJohn Marino proxy_entry->proto = proto;
826*86d7f5d3SJohn Marino proxy_entry->proxy_port = htons(proxy_port);
827*86d7f5d3SJohn Marino proxy_entry->server_port = htons(server_port);
828*86d7f5d3SJohn Marino proxy_entry->server_addr = server_addr;
829*86d7f5d3SJohn Marino proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
830*86d7f5d3SJohn Marino proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
831*86d7f5d3SJohn Marino proxy_entry->src_mask = src_mask;
832*86d7f5d3SJohn Marino proxy_entry->dst_mask = dst_mask;
833*86d7f5d3SJohn Marino
834*86d7f5d3SJohn Marino RuleAdd(proxy_entry);
835*86d7f5d3SJohn Marino
836*86d7f5d3SJohn Marino return 0;
837*86d7f5d3SJohn Marino }
838