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