Deleted Added
full compact
alias_proxy.c (124621) alias_proxy.c (127094)
1/*-
2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_proxy.c 124621 2004-01-17 10:52:21Z phk $");
28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_proxy.c 127094 2004-03-16 21:30:41Z des $");
29
30/* file: alias_proxy.c
31
32 This file encapsulates special operations related to transparent
33 proxy redirection. This is where packets with a particular destination,
34 usually tcp port 80, are redirected to a proxy server.
35
36 When packets are proxied, the destination address and port are

--- 29 unchanged lines hidden (view full) ---

66/* BSD IPV4 includes */
67#include <netinet/in_systm.h>
68#include <netinet/in.h>
69#include <netinet/ip.h>
70#include <netinet/tcp.h>
71
72#include <arpa/inet.h>
73
29
30/* file: alias_proxy.c
31
32 This file encapsulates special operations related to transparent
33 proxy redirection. This is where packets with a particular destination,
34 usually tcp port 80, are redirected to a proxy server.
35
36 When packets are proxied, the destination address and port are

--- 29 unchanged lines hidden (view full) ---

66/* BSD IPV4 includes */
67#include <netinet/in_systm.h>
68#include <netinet/in.h>
69#include <netinet/ip.h>
70#include <netinet/tcp.h>
71
72#include <arpa/inet.h>
73
74#include "alias_local.h" /* Functions used by alias*.c */
75#include "alias.h" /* Public API functions for libalias */
74#include "alias_local.h" /* Functions used by alias*.c */
75#include "alias.h" /* Public API functions for libalias */
76
77
78
79/*
80 Data structures
81 */
82
83/*
84 * A linked list of arbitrary length, based on struct proxy_entry is
85 * used to store proxy rules.
86 */
76
77
78
79/*
80 Data structures
81 */
82
83/*
84 * A linked list of arbitrary length, based on struct proxy_entry is
85 * used to store proxy rules.
86 */
87struct proxy_entry
88{
89 struct libalias *la;
87struct proxy_entry {
88 struct libalias *la;
90#define PROXY_TYPE_ENCODE_NONE 1
91#define PROXY_TYPE_ENCODE_TCPSTREAM 2
92#define PROXY_TYPE_ENCODE_IPHDR 3
89#define PROXY_TYPE_ENCODE_NONE 1
90#define PROXY_TYPE_ENCODE_TCPSTREAM 2
91#define PROXY_TYPE_ENCODE_IPHDR 3
93 int rule_index;
94 int proxy_type;
95 u_char proto;
96 u_short proxy_port;
97 u_short server_port;
92 int rule_index;
93 int proxy_type;
94 u_char proto;
95 u_short proxy_port;
96 u_short server_port;
98
97
99 struct in_addr server_addr;
98 struct in_addr server_addr;
100
99
101 struct in_addr src_addr;
102 struct in_addr src_mask;
100 struct in_addr src_addr;
101 struct in_addr src_mask;
103
102
104 struct in_addr dst_addr;
105 struct in_addr dst_mask;
103 struct in_addr dst_addr;
104 struct in_addr dst_mask;
106
105
107 struct proxy_entry *next;
108 struct proxy_entry *last;
106 struct proxy_entry *next;
107 struct proxy_entry *last;
109};
110
111
112
113/*
114 File scope variables
115*/
116

--- 12 unchanged lines hidden (view full) ---

129 RuleNumberDelete() -- Removes all elements from the rule list
130 having a certain rule number.
131 ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
132 of a TCP stream.
133 ProxyEncodeIpHeader() -- Adds an IP option indicating the true
134 destination of a proxied IP packet
135*/
136
108};
109
110
111
112/*
113 File scope variables
114*/
115

--- 12 unchanged lines hidden (view full) ---

128 RuleNumberDelete() -- Removes all elements from the rule list
129 having a certain rule number.
130 ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
131 of a TCP stream.
132 ProxyEncodeIpHeader() -- Adds an IP option indicating the true
133 destination of a proxied IP packet
134*/
135
137static int IpMask(int, struct in_addr *);
138static int IpAddr(char *, struct in_addr *);
139static int IpPort(char *, int, int *);
140static void RuleAdd(struct libalias *la, struct proxy_entry *);
141static void RuleDelete(struct proxy_entry *);
142static int RuleNumberDelete(struct libalias *la, int);
143static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
144static void ProxyEncodeIpHeader(struct ip *, int);
136static int IpMask(int, struct in_addr *);
137static int IpAddr(char *, struct in_addr *);
138static int IpPort(char *, int, int *);
139static void RuleAdd(struct libalias *la, struct proxy_entry *);
140static void RuleDelete(struct proxy_entry *);
141static int RuleNumberDelete(struct libalias *la, int);
142static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
143static void ProxyEncodeIpHeader(struct ip *, int);
145
146static int
147IpMask(int nbits, struct in_addr *mask)
148{
144
145static int
146IpMask(int nbits, struct in_addr *mask)
147{
149 int i;
150 u_int imask;
148 int i;
149 u_int imask;
151
150
152 if (nbits < 0 || nbits > 32)
153 return -1;
151 if (nbits < 0 || nbits > 32)
152 return -1;
154
153
155 imask = 0;
156 for (i=0; i<nbits; i++)
157 imask = (imask >> 1) + 0x80000000;
158 mask->s_addr = htonl(imask);
154 imask = 0;
155 for (i = 0; i < nbits; i++)
156 imask = (imask >> 1) + 0x80000000;
157 mask->s_addr = htonl(imask);
159
158
160 return 0;
159 return 0;
161}
162
163static int
164IpAddr(char *s, struct in_addr *addr)
165{
160}
161
162static int
163IpAddr(char *s, struct in_addr *addr)
164{
166 if (inet_aton(s, addr) == 0)
167 return -1;
168 else
169 return 0;
165 if (inet_aton(s, addr) == 0)
166 return -1;
167 else
168 return 0;
170}
171
172static int
173IpPort(char *s, int proto, int *port)
174{
169}
170
171static int
172IpPort(char *s, int proto, int *port)
173{
175 int n;
174 int n;
176
175
177 n = sscanf(s, "%d", port);
178 if (n != 1)
179 {
180 struct servent *se;
176 n = sscanf(s, "%d", port);
177 if (n != 1) {
178 struct servent *se;
181
179
182 if (proto == IPPROTO_TCP)
183 se = getservbyname(s, "tcp");
184 else if (proto == IPPROTO_UDP)
185 se = getservbyname(s, "udp");
186 else
187 return -1;
180 if (proto == IPPROTO_TCP)
181 se = getservbyname(s, "tcp");
182 else if (proto == IPPROTO_UDP)
183 se = getservbyname(s, "udp");
184 else
185 return -1;
188
186
189 if (se == NULL)
190 return -1;
187 if (se == NULL)
188 return -1;
191
189
192 *port = (u_int) ntohs(se->s_port);
193 }
194
195 return 0;
190 *port = (u_int) ntohs(se->s_port);
191 }
192 return 0;
196}
197
198void
199RuleAdd(struct libalias *la, struct proxy_entry *entry)
200{
193}
194
195void
196RuleAdd(struct libalias *la, struct proxy_entry *entry)
197{
201 int rule_index;
202 struct proxy_entry *ptr;
203 struct proxy_entry *ptr_last;
198 int rule_index;
199 struct proxy_entry *ptr;
200 struct proxy_entry *ptr_last;
204
201
205 if (la->proxyList == NULL)
206 {
207 la->proxyList = entry;
208 entry->last = NULL;
209 entry->next = NULL;
210 return;
211 }
212 entry->la = la;
202 if (la->proxyList == NULL) {
203 la->proxyList = entry;
204 entry->last = NULL;
205 entry->next = NULL;
206 return;
207 }
208 entry->la = la;
213
209
214 rule_index = entry->rule_index;
215 ptr = la->proxyList;
216 ptr_last = NULL;
217 while (ptr != NULL)
218 {
219 if (ptr->rule_index >= rule_index)
220 {
221 if (ptr_last == NULL)
222 {
223 entry->next = la->proxyList;
224 entry->last = NULL;
225 la->proxyList->last = entry;
226 la->proxyList = entry;
227 return;
228 }
210 rule_index = entry->rule_index;
211 ptr = la->proxyList;
212 ptr_last = NULL;
213 while (ptr != NULL) {
214 if (ptr->rule_index >= rule_index) {
215 if (ptr_last == NULL) {
216 entry->next = la->proxyList;
217 entry->last = NULL;
218 la->proxyList->last = entry;
219 la->proxyList = entry;
220 return;
221 }
222 ptr_last->next = entry;
223 ptr->last = entry;
224 entry->last = ptr->last;
225 entry->next = ptr;
226 return;
227 }
228 ptr_last = ptr;
229 ptr = ptr->next;
230 }
229
231
230 ptr_last->next = entry;
231 ptr->last = entry;
232 entry->last = ptr->last;
233 entry->next = ptr;
234 return;
235 }
236 ptr_last = ptr;
237 ptr = ptr->next;
238 }
239
240 ptr_last->next = entry;
241 entry->last = ptr_last;
242 entry->next = NULL;
232 ptr_last->next = entry;
233 entry->last = ptr_last;
234 entry->next = NULL;
243}
244
245static void
246RuleDelete(struct proxy_entry *entry)
247{
235}
236
237static void
238RuleDelete(struct proxy_entry *entry)
239{
248 struct libalias *la;
249
250 la = entry->la;
251 if (entry->last != NULL)
252 entry->last->next = entry->next;
253 else
254 la->proxyList = entry->next;
240 struct libalias *la;
255
241
256 if (entry->next != NULL)
257 entry->next->last = entry->last;
242 la = entry->la;
243 if (entry->last != NULL)
244 entry->last->next = entry->next;
245 else
246 la->proxyList = entry->next;
258
247
259 free(entry);
248 if (entry->next != NULL)
249 entry->next->last = entry->last;
250
251 free(entry);
260}
261
262static int
263RuleNumberDelete(struct libalias *la, int rule_index)
264{
252}
253
254static int
255RuleNumberDelete(struct libalias *la, int rule_index)
256{
265 int err;
266 struct proxy_entry *ptr;
257 int err;
258 struct proxy_entry *ptr;
267
259
268 err = -1;
269 ptr = la->proxyList;
270 while (ptr != NULL)
271 {
272 struct proxy_entry *ptr_next;
260 err = -1;
261 ptr = la->proxyList;
262 while (ptr != NULL) {
263 struct proxy_entry *ptr_next;
273
264
274 ptr_next = ptr->next;
275 if (ptr->rule_index == rule_index)
276 {
277 err = 0;
278 RuleDelete(ptr);
279 }
265 ptr_next = ptr->next;
266 if (ptr->rule_index == rule_index) {
267 err = 0;
268 RuleDelete(ptr);
269 }
270 ptr = ptr_next;
271 }
280
272
281 ptr = ptr_next;
282 }
283
284 return err;
273 return err;
285}
286
287static void
288ProxyEncodeTcpStream(struct alias_link *link,
274}
275
276static void
277ProxyEncodeTcpStream(struct alias_link *link,
289 struct ip *pip,
290 int maxpacketsize)
278 struct ip *pip,
279 int maxpacketsize)
291{
280{
292 int slen;
293 char buffer[40];
294 struct tcphdr *tc;
281 int slen;
282 char buffer[40];
283 struct tcphdr *tc;
295
296/* Compute pointer to tcp header */
284
285/* Compute pointer to tcp header */
297 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
286 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2));
298
299/* Don't modify if once already modified */
300
287
288/* Don't modify if once already modified */
289
301 if (GetAckModified (link))
302 return;
290 if (GetAckModified(link))
291 return;
303
304/* Translate destination address and port to string form */
292
293/* Translate destination address and port to string form */
305 snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
306 inet_ntoa(GetProxyAddress (link)), (u_int) ntohs(GetProxyPort (link)));
294 snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
295 inet_ntoa(GetProxyAddress(link)), (u_int) ntohs(GetProxyPort(link)));
307
308/* Pad string out to a multiple of two in length */
296
297/* Pad string out to a multiple of two in length */
309 slen = strlen(buffer);
310 switch (slen % 2)
311 {
312 case 0:
313 strcat(buffer, " \n");
314 slen += 2;
315 break;
316 case 1:
317 strcat(buffer, "\n");
318 slen += 1;
319 }
298 slen = strlen(buffer);
299 switch (slen % 2) {
300 case 0:
301 strcat(buffer, " \n");
302 slen += 2;
303 break;
304 case 1:
305 strcat(buffer, "\n");
306 slen += 1;
307 }
320
321/* Check for packet overflow */
308
309/* Check for packet overflow */
322 if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
323 return;
310 if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
311 return;
324
325/* Shift existing TCP data and insert destination string */
312
313/* Shift existing TCP data and insert destination string */
326 {
327 int dlen;
328 int hlen;
329 u_char *p;
314 {
315 int dlen;
316 int hlen;
317 u_char *p;
330
318
331 hlen = (pip->ip_hl + tc->th_off) << 2;
332 dlen = ntohs (pip->ip_len) - hlen;
319 hlen = (pip->ip_hl + tc->th_off) << 2;
320 dlen = ntohs(pip->ip_len) - hlen;
333
334/* Modify first packet that has data in it */
335
321
322/* Modify first packet that has data in it */
323
336 if (dlen == 0)
337 return;
324 if (dlen == 0)
325 return;
338
326
339 p = (char *) pip;
340 p += hlen;
327 p = (char *)pip;
328 p += hlen;
341
329
342 memmove(p + slen, p, dlen);
343 memcpy(p, buffer, slen);
344 }
330 memmove(p + slen, p, dlen);
331 memcpy(p, buffer, slen);
332 }
345
346/* Save information about modfied sequence number */
333
334/* Save information about modfied sequence number */
347 {
348 int delta;
335 {
336 int delta;
349
337
350 SetAckModified(link);
351 delta = GetDeltaSeqOut(pip, link);
352 AddSeq(pip, link, delta+slen);
353 }
338 SetAckModified(link);
339 delta = GetDeltaSeqOut(pip, link);
340 AddSeq(pip, link, delta + slen);
341 }
354
355/* Update IP header packet length and checksum */
342
343/* Update IP header packet length and checksum */
356 {
357 int accumulate;
344 {
345 int accumulate;
358
346
359 accumulate = pip->ip_len;
360 pip->ip_len = htons(ntohs(pip->ip_len) + slen);
361 accumulate -= pip->ip_len;
347 accumulate = pip->ip_len;
348 pip->ip_len = htons(ntohs(pip->ip_len) + slen);
349 accumulate -= pip->ip_len;
362
350
363 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
364 }
351 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
352 }
365
366/* Update TCP checksum, Use TcpChecksum since so many things have
367 already changed. */
368
353
354/* Update TCP checksum, Use TcpChecksum since so many things have
355 already changed. */
356
369 tc->th_sum = 0;
370 tc->th_sum = TcpChecksum (pip);
357 tc->th_sum = 0;
358 tc->th_sum = TcpChecksum(pip);
371}
372
373static void
374ProxyEncodeIpHeader(struct ip *pip,
359}
360
361static void
362ProxyEncodeIpHeader(struct ip *pip,
375 int maxpacketsize)
363 int maxpacketsize)
376{
377#define OPTION_LEN_BYTES 8
378#define OPTION_LEN_INT16 4
379#define OPTION_LEN_INT32 2
364{
365#define OPTION_LEN_BYTES 8
366#define OPTION_LEN_INT16 4
367#define OPTION_LEN_INT32 2
380 u_char option[OPTION_LEN_BYTES];
368 u_char option[OPTION_LEN_BYTES];
381
382#ifdef DEBUG
369
370#ifdef DEBUG
383 fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
384 fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
371 fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip));
372 fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip));
385#endif
386
387/* Check to see that there is room to add an IP option */
373#endif
374
375/* Check to see that there is room to add an IP option */
388 if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
389 return;
376 if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
377 return;
390
391/* Build option and copy into packet */
378
379/* Build option and copy into packet */
392 {
393 u_char *ptr;
394 struct tcphdr *tc;
380 {
381 u_char *ptr;
382 struct tcphdr *tc;
395
383
396 ptr = (u_char *) pip;
397 ptr += 20;
398 memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
384 ptr = (u_char *) pip;
385 ptr += 20;
386 memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
399
387
400 option[0] = 0x64; /* class: 3 (reserved), option 4 */
401 option[1] = OPTION_LEN_BYTES;
388 option[0] = 0x64; /* class: 3 (reserved), option 4 */
389 option[1] = OPTION_LEN_BYTES;
402
390
403 memcpy(&option[2], (u_char *) &pip->ip_dst, 4);
391 memcpy(&option[2], (u_char *) & pip->ip_dst, 4);
404
392
405 tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
406 memcpy(&option[6], (u_char *) &tc->th_sport, 2);
393 tc = (struct tcphdr *)((char *)pip + (pip->ip_hl << 2));
394 memcpy(&option[6], (u_char *) & tc->th_sport, 2);
407
395
408 memcpy(ptr, option, 8);
409 }
396 memcpy(ptr, option, 8);
397 }
410
411/* Update checksum, header length and packet length */
398
399/* Update checksum, header length and packet length */
412 {
413 int i;
414 int accumulate;
415 u_short *sptr;
400 {
401 int i;
402 int accumulate;
403 u_short *sptr;
416
404
417 sptr = (u_short *) option;
418 accumulate = 0;
419 for (i=0; i<OPTION_LEN_INT16; i++)
420 accumulate -= *(sptr++);
405 sptr = (u_short *) option;
406 accumulate = 0;
407 for (i = 0; i < OPTION_LEN_INT16; i++)
408 accumulate -= *(sptr++);
421
409
422 sptr = (u_short *) pip;
423 accumulate += *sptr;
424 pip->ip_hl += OPTION_LEN_INT32;
425 accumulate -= *sptr;
410 sptr = (u_short *) pip;
411 accumulate += *sptr;
412 pip->ip_hl += OPTION_LEN_INT32;
413 accumulate -= *sptr;
426
414
427 accumulate += pip->ip_len;
428 pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
429 accumulate -= pip->ip_len;
415 accumulate += pip->ip_len;
416 pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
417 accumulate -= pip->ip_len;
430
418
431 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
432 }
419 ADJUST_CHECKSUM(accumulate, pip->ip_sum);
420 }
433#undef OPTION_LEN_BYTES
434#undef OPTION_LEN_INT16
435#undef OPTION_LEN_INT32
436#ifdef DEBUG
421#undef OPTION_LEN_BYTES
422#undef OPTION_LEN_INT16
423#undef OPTION_LEN_INT32
424#ifdef DEBUG
437 fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
438 fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
425 fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip));
426 fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip));
439#endif
440}
441
442
443/* Functions by other packet alias source files
444
445 ProxyCheck() -- Checks whether an outgoing packet should
446 be proxied.
447 ProxyModify() -- Encodes the original destination address/port
448 for a packet which is to be redirected to
449 a proxy server.
450*/
451
452int
453ProxyCheck(struct libalias *la, struct ip *pip,
427#endif
428}
429
430
431/* Functions by other packet alias source files
432
433 ProxyCheck() -- Checks whether an outgoing packet should
434 be proxied.
435 ProxyModify() -- Encodes the original destination address/port
436 for a packet which is to be redirected to
437 a proxy server.
438*/
439
440int
441ProxyCheck(struct libalias *la, struct ip *pip,
454 struct in_addr *proxy_server_addr,
455 u_short *proxy_server_port)
442 struct in_addr *proxy_server_addr,
443 u_short * proxy_server_port)
456{
444{
457 u_short dst_port;
458 struct in_addr src_addr;
459 struct in_addr dst_addr;
460 struct proxy_entry *ptr;
445 u_short dst_port;
446 struct in_addr src_addr;
447 struct in_addr dst_addr;
448 struct proxy_entry *ptr;
461
449
462 src_addr = pip->ip_src;
463 dst_addr = pip->ip_dst;
464 dst_port = ((struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)))
465 ->th_dport;
450 src_addr = pip->ip_src;
451 dst_addr = pip->ip_dst;
452 dst_port = ((struct tcphdr *)((char *)pip + (pip->ip_hl << 2)))
453 ->th_dport;
466
454
467 ptr = la->proxyList;
468 while (ptr != NULL)
469 {
470 u_short proxy_port;
455 ptr = la->proxyList;
456 while (ptr != NULL) {
457 u_short proxy_port;
471
458
472 proxy_port = ptr->proxy_port;
473 if ((dst_port == proxy_port || proxy_port == 0)
474 && pip->ip_p == ptr->proto
475 && src_addr.s_addr != ptr->server_addr.s_addr)
476 {
477 struct in_addr src_addr_masked;
478 struct in_addr dst_addr_masked;
459 proxy_port = ptr->proxy_port;
460 if ((dst_port == proxy_port || proxy_port == 0)
461 && pip->ip_p == ptr->proto
462 && src_addr.s_addr != ptr->server_addr.s_addr) {
463 struct in_addr src_addr_masked;
464 struct in_addr dst_addr_masked;
479
465
480 src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
481 dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
466 src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
467 dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
482
468
483 if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
484 && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr))
485 {
486 if ((*proxy_server_port = ptr->server_port) == 0)
487 *proxy_server_port = dst_port;
488 *proxy_server_addr = ptr->server_addr;
489 return ptr->proxy_type;
490 }
491 }
492 ptr = ptr->next;
493 }
469 if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
470 && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr)) {
471 if ((*proxy_server_port = ptr->server_port) == 0)
472 *proxy_server_port = dst_port;
473 *proxy_server_addr = ptr->server_addr;
474 return ptr->proxy_type;
475 }
476 }
477 ptr = ptr->next;
478 }
494
479
495 return 0;
480 return 0;
496}
497
498void
499ProxyModify(struct libalias *la, struct alias_link *link,
481}
482
483void
484ProxyModify(struct libalias *la, struct alias_link *link,
500 struct ip *pip,
501 int maxpacketsize,
502 int proxy_type)
485 struct ip *pip,
486 int maxpacketsize,
487 int proxy_type)
503{
488{
504 switch (proxy_type)
505 {
506 case PROXY_TYPE_ENCODE_IPHDR:
507 ProxyEncodeIpHeader(pip, maxpacketsize);
508 break;
489 switch (proxy_type) {
490 case PROXY_TYPE_ENCODE_IPHDR:
491 ProxyEncodeIpHeader(pip, maxpacketsize);
492 break;
509
493
510 case PROXY_TYPE_ENCODE_TCPSTREAM:
511 ProxyEncodeTcpStream(link, pip, maxpacketsize);
512 break;
513 }
494 case PROXY_TYPE_ENCODE_TCPSTREAM:
495 ProxyEncodeTcpStream(link, pip, maxpacketsize);
496 break;
497 }
514}
515
516
517/*
518 Public API functions
519*/
520
521int

--- 15 unchanged lines hidden (view full) ---

537 * Subfields can be in arbitrary order. Port numbers and addresses
538 * must be in either numeric or symbolic form. An optional rule number
539 * is used to control the order in which rules are searched. If two
540 * rules have the same number, then search order cannot be guaranteed,
541 * and the rules should be disjoint. If no rule number is specified,
542 * then 0 is used, and group 0 rules are always checked before any
543 * others.
544 */
498}
499
500
501/*
502 Public API functions
503*/
504
505int

--- 15 unchanged lines hidden (view full) ---

521 * Subfields can be in arbitrary order. Port numbers and addresses
522 * must be in either numeric or symbolic form. An optional rule number
523 * is used to control the order in which rules are searched. If two
524 * rules have the same number, then search order cannot be guaranteed,
525 * and the rules should be disjoint. If no rule number is specified,
526 * then 0 is used, and group 0 rules are always checked before any
527 * others.
528 */
545 int i, n, len;
546 int cmd_len;
547 int token_count;
548 int state;
549 char *token;
550 char buffer[256];
551 char str_port[sizeof(buffer)];
552 char str_server_port[sizeof(buffer)];
553 char *res = buffer;
529 int i, n, len;
530 int cmd_len;
531 int token_count;
532 int state;
533 char *token;
534 char buffer[256];
535 char str_port[sizeof(buffer)];
536 char str_server_port[sizeof(buffer)];
537 char *res = buffer;
554
538
555 int rule_index;
556 int proto;
557 int proxy_type;
558 int proxy_port;
559 int server_port;
560 struct in_addr server_addr;
561 struct in_addr src_addr, src_mask;
562 struct in_addr dst_addr, dst_mask;
563 struct proxy_entry *proxy_entry;
539 int rule_index;
540 int proto;
541 int proxy_type;
542 int proxy_port;
543 int server_port;
544 struct in_addr server_addr;
545 struct in_addr src_addr, src_mask;
546 struct in_addr dst_addr, dst_mask;
547 struct proxy_entry *proxy_entry;
564
565/* Copy command line into a buffer */
548
549/* Copy command line into a buffer */
566 cmd += strspn(cmd, " \t");
567 cmd_len = strlen(cmd);
568 if (cmd_len > (sizeof(buffer) - 1))
569 return -1;
570 strcpy(buffer, cmd);
550 cmd += strspn(cmd, " \t");
551 cmd_len = strlen(cmd);
552 if (cmd_len > (sizeof(buffer) - 1))
553 return -1;
554 strcpy(buffer, cmd);
571
572/* Convert to lower case */
555
556/* Convert to lower case */
573 len = strlen(buffer);
574 for (i=0; i<len; i++)
575 buffer[i] = tolower((unsigned char)buffer[i]);
557 len = strlen(buffer);
558 for (i = 0; i < len; i++)
559 buffer[i] = tolower((unsigned char)buffer[i]);
576
577/* Set default proxy type */
578
579/* Set up default values */
560
561/* Set default proxy type */
562
563/* Set up default values */
580 rule_index = 0;
581 proxy_type = PROXY_TYPE_ENCODE_NONE;
582 proto = IPPROTO_TCP;
583 proxy_port = 0;
584 server_addr.s_addr = 0;
585 server_port = 0;
586 src_addr.s_addr = 0;
587 IpMask(0, &src_mask);
588 dst_addr.s_addr = 0;
589 IpMask(0, &dst_mask);
564 rule_index = 0;
565 proxy_type = PROXY_TYPE_ENCODE_NONE;
566 proto = IPPROTO_TCP;
567 proxy_port = 0;
568 server_addr.s_addr = 0;
569 server_port = 0;
570 src_addr.s_addr = 0;
571 IpMask(0, &src_mask);
572 dst_addr.s_addr = 0;
573 IpMask(0, &dst_mask);
590
574
591 str_port[0] = 0;
592 str_server_port[0] = 0;
575 str_port[0] = 0;
576 str_server_port[0] = 0;
593
594/* Parse command string with state machine */
595#define STATE_READ_KEYWORD 0
596#define STATE_READ_TYPE 1
597#define STATE_READ_PORT 2
598#define STATE_READ_SERVER 3
599#define STATE_READ_RULE 4
600#define STATE_READ_DELETE 5
601#define STATE_READ_PROTO 6
602#define STATE_READ_SRC 7
603#define STATE_READ_DST 8
577
578/* Parse command string with state machine */
579#define STATE_READ_KEYWORD 0
580#define STATE_READ_TYPE 1
581#define STATE_READ_PORT 2
582#define STATE_READ_SERVER 3
583#define STATE_READ_RULE 4
584#define STATE_READ_DELETE 5
585#define STATE_READ_PROTO 6
586#define STATE_READ_SRC 7
587#define STATE_READ_DST 8
604 state = STATE_READ_KEYWORD;
605 token = strsep(&res, " \t");
606 token_count = 0;
607 while (token != NULL)
608 {
609 token_count++;
610 switch (state)
611 {
612 case STATE_READ_KEYWORD:
613 if (strcmp(token, "type") == 0)
614 state = STATE_READ_TYPE;
615 else if (strcmp(token, "port") == 0)
616 state = STATE_READ_PORT;
617 else if (strcmp(token, "server") == 0)
618 state = STATE_READ_SERVER;
619 else if (strcmp(token, "rule") == 0)
620 state = STATE_READ_RULE;
621 else if (strcmp(token, "delete") == 0)
622 state = STATE_READ_DELETE;
623 else if (strcmp(token, "proto") == 0)
624 state = STATE_READ_PROTO;
625 else if (strcmp(token, "src") == 0)
626 state = STATE_READ_SRC;
627 else if (strcmp(token, "dst") == 0)
628 state = STATE_READ_DST;
629 else
630 return -1;
631 break;
588 state = STATE_READ_KEYWORD;
589 token = strsep(&res, " \t");
590 token_count = 0;
591 while (token != NULL) {
592 token_count++;
593 switch (state) {
594 case STATE_READ_KEYWORD:
595 if (strcmp(token, "type") == 0)
596 state = STATE_READ_TYPE;
597 else if (strcmp(token, "port") == 0)
598 state = STATE_READ_PORT;
599 else if (strcmp(token, "server") == 0)
600 state = STATE_READ_SERVER;
601 else if (strcmp(token, "rule") == 0)
602 state = STATE_READ_RULE;
603 else if (strcmp(token, "delete") == 0)
604 state = STATE_READ_DELETE;
605 else if (strcmp(token, "proto") == 0)
606 state = STATE_READ_PROTO;
607 else if (strcmp(token, "src") == 0)
608 state = STATE_READ_SRC;
609 else if (strcmp(token, "dst") == 0)
610 state = STATE_READ_DST;
611 else
612 return -1;
613 break;
632
614
633 case STATE_READ_TYPE:
634 if (strcmp(token, "encode_ip_hdr") == 0)
635 proxy_type = PROXY_TYPE_ENCODE_IPHDR;
636 else if (strcmp(token, "encode_tcp_stream") == 0)
637 proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
638 else if (strcmp(token, "no_encode") == 0)
639 proxy_type = PROXY_TYPE_ENCODE_NONE;
640 else
641 return -1;
642 state = STATE_READ_KEYWORD;
643 break;
615 case STATE_READ_TYPE:
616 if (strcmp(token, "encode_ip_hdr") == 0)
617 proxy_type = PROXY_TYPE_ENCODE_IPHDR;
618 else if (strcmp(token, "encode_tcp_stream") == 0)
619 proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
620 else if (strcmp(token, "no_encode") == 0)
621 proxy_type = PROXY_TYPE_ENCODE_NONE;
622 else
623 return -1;
624 state = STATE_READ_KEYWORD;
625 break;
644
626
645 case STATE_READ_PORT:
646 strcpy(str_port, token);
647 state = STATE_READ_KEYWORD;
648 break;
627 case STATE_READ_PORT:
628 strcpy(str_port, token);
629 state = STATE_READ_KEYWORD;
630 break;
649
631
650 case STATE_READ_SERVER:
651 {
652 int err;
653 char *p;
654 char s[sizeof(buffer)];
632 case STATE_READ_SERVER:
633 {
634 int err;
635 char *p;
636 char s[sizeof(buffer)];
655
637
656 p = token;
657 while (*p != ':' && *p != 0)
658 p++;
638 p = token;
639 while (*p != ':' && *p != 0)
640 p++;
659
641
660 if (*p != ':')
661 {
662 err = IpAddr(token, &server_addr);
663 if (err)
664 return -1;
665 }
666 else
667 {
668 *p = ' ';
642 if (*p != ':') {
643 err = IpAddr(token, &server_addr);
644 if (err)
645 return -1;
646 } else {
647 *p = ' ';
669
648
670 n = sscanf(token, "%s %s", s, str_server_port);
671 if (n != 2)
672 return -1;
649 n = sscanf(token, "%s %s", s, str_server_port);
650 if (n != 2)
651 return -1;
673
652
674 err = IpAddr(s, &server_addr);
675 if (err)
676 return -1;
677 }
678 }
679 state = STATE_READ_KEYWORD;
680 break;
653 err = IpAddr(s, &server_addr);
654 if (err)
655 return -1;
656 }
657 }
658 state = STATE_READ_KEYWORD;
659 break;
681
660
682 case STATE_READ_RULE:
683 n = sscanf(token, "%d", &rule_index);
684 if (n != 1 || rule_index < 0)
685 return -1;
686 state = STATE_READ_KEYWORD;
687 break;
661 case STATE_READ_RULE:
662 n = sscanf(token, "%d", &rule_index);
663 if (n != 1 || rule_index < 0)
664 return -1;
665 state = STATE_READ_KEYWORD;
666 break;
688
667
689 case STATE_READ_DELETE:
690 {
691 int err;
692 int rule_to_delete;
668 case STATE_READ_DELETE:
669 {
670 int err;
671 int rule_to_delete;
693
672
694 if (token_count != 2)
695 return -1;
673 if (token_count != 2)
674 return -1;
696
675
697 n = sscanf(token, "%d", &rule_to_delete);
698 if (n != 1)
699 return -1;
700 err = RuleNumberDelete(la, rule_to_delete);
701 if (err)
702 return -1;
703 return 0;
704 }
676 n = sscanf(token, "%d", &rule_to_delete);
677 if (n != 1)
678 return -1;
679 err = RuleNumberDelete(la, rule_to_delete);
680 if (err)
681 return -1;
682 return 0;
683 }
705
684
706 case STATE_READ_PROTO:
707 if (strcmp(token, "tcp") == 0)
708 proto = IPPROTO_TCP;
709 else if (strcmp(token, "udp") == 0)
710 proto = IPPROTO_UDP;
711 else
712 return -1;
713 state = STATE_READ_KEYWORD;
714 break;
685 case STATE_READ_PROTO:
686 if (strcmp(token, "tcp") == 0)
687 proto = IPPROTO_TCP;
688 else if (strcmp(token, "udp") == 0)
689 proto = IPPROTO_UDP;
690 else
691 return -1;
692 state = STATE_READ_KEYWORD;
693 break;
715
694
716 case STATE_READ_SRC:
717 case STATE_READ_DST:
718 {
719 int err;
720 char *p;
721 struct in_addr mask;
722 struct in_addr addr;
695 case STATE_READ_SRC:
696 case STATE_READ_DST:
697 {
698 int err;
699 char *p;
700 struct in_addr mask;
701 struct in_addr addr;
723
702
724 p = token;
725 while (*p != '/' && *p != 0)
726 p++;
703 p = token;
704 while (*p != '/' && *p != 0)
705 p++;
727
706
728 if (*p != '/')
729 {
730 IpMask(32, &mask);
731 err = IpAddr(token, &addr);
732 if (err)
733 return -1;
734 }
735 else
736 {
737 int nbits;
738 char s[sizeof(buffer)];
707 if (*p != '/') {
708 IpMask(32, &mask);
709 err = IpAddr(token, &addr);
710 if (err)
711 return -1;
712 } else {
713 int nbits;
714 char s[sizeof(buffer)];
739
715
740 *p = ' ';
741 n = sscanf(token, "%s %d", s, &nbits);
742 if (n != 2)
743 return -1;
716 *p = ' ';
717 n = sscanf(token, "%s %d", s, &nbits);
718 if (n != 2)
719 return -1;
744
720
745 err = IpAddr(s, &addr);
746 if (err)
747 return -1;
721 err = IpAddr(s, &addr);
722 if (err)
723 return -1;
748
724
749 err = IpMask(nbits, &mask);
750 if (err)
751 return -1;
752 }
725 err = IpMask(nbits, &mask);
726 if (err)
727 return -1;
728 }
753
729
754 if (state == STATE_READ_SRC)
755 {
756 src_addr = addr;
757 src_mask = mask;
758 }
759 else
760 {
761 dst_addr = addr;
762 dst_mask = mask;
763 }
764 }
765 state = STATE_READ_KEYWORD;
766 break;
730 if (state == STATE_READ_SRC) {
731 src_addr = addr;
732 src_mask = mask;
733 } else {
734 dst_addr = addr;
735 dst_mask = mask;
736 }
737 }
738 state = STATE_READ_KEYWORD;
739 break;
767
740
768 default:
769 return -1;
770 break;
771 }
741 default:
742 return -1;
743 break;
744 }
772
745
773 do {
774 token = strsep(&res, " \t");
775 } while (token != NULL && !*token);
776 }
746 do {
747 token = strsep(&res, " \t");
748 } while (token != NULL && !*token);
749 }
777#undef STATE_READ_KEYWORD
778#undef STATE_READ_TYPE
779#undef STATE_READ_PORT
780#undef STATE_READ_SERVER
781#undef STATE_READ_RULE
782#undef STATE_READ_DELETE
783#undef STATE_READ_PROTO
784#undef STATE_READ_SRC
785#undef STATE_READ_DST
786
787/* Convert port strings to numbers. This needs to be done after
788 the string is parsed, because the prototype might not be designated
789 before the ports (which might be symbolic entries in /etc/services) */
790
750#undef STATE_READ_KEYWORD
751#undef STATE_READ_TYPE
752#undef STATE_READ_PORT
753#undef STATE_READ_SERVER
754#undef STATE_READ_RULE
755#undef STATE_READ_DELETE
756#undef STATE_READ_PROTO
757#undef STATE_READ_SRC
758#undef STATE_READ_DST
759
760/* Convert port strings to numbers. This needs to be done after
761 the string is parsed, because the prototype might not be designated
762 before the ports (which might be symbolic entries in /etc/services) */
763
791 if (strlen(str_port) != 0)
792 {
793 int err;
764 if (strlen(str_port) != 0) {
765 int err;
794
766
795 err = IpPort(str_port, proto, &proxy_port);
796 if (err)
797 return -1;
798 }
799 else
800 {
801 proxy_port = 0;
802 }
767 err = IpPort(str_port, proto, &proxy_port);
768 if (err)
769 return -1;
770 } else {
771 proxy_port = 0;
772 }
803
773
804 if (strlen(str_server_port) != 0)
805 {
806 int err;
774 if (strlen(str_server_port) != 0) {
775 int err;
807
776
808 err = IpPort(str_server_port, proto, &server_port);
809 if (err)
810 return -1;
811 }
812 else
813 {
814 server_port = 0;
815 }
777 err = IpPort(str_server_port, proto, &server_port);
778 if (err)
779 return -1;
780 } else {
781 server_port = 0;
782 }
816
817/* Check that at least the server address has been defined */
783
784/* Check that at least the server address has been defined */
818 if (server_addr.s_addr == 0)
819 return -1;
785 if (server_addr.s_addr == 0)
786 return -1;
820
821/* Add to linked list */
787
788/* Add to linked list */
822 proxy_entry = malloc(sizeof(struct proxy_entry));
823 if (proxy_entry == NULL)
824 return -1;
789 proxy_entry = malloc(sizeof(struct proxy_entry));
790 if (proxy_entry == NULL)
791 return -1;
825
792
826 proxy_entry->proxy_type = proxy_type;
827 proxy_entry->rule_index = rule_index;
828 proxy_entry->proto = proto;
829 proxy_entry->proxy_port = htons(proxy_port);
830 proxy_entry->server_port = htons(server_port);
831 proxy_entry->server_addr = server_addr;
832 proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
833 proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
834 proxy_entry->src_mask = src_mask;
835 proxy_entry->dst_mask = dst_mask;
793 proxy_entry->proxy_type = proxy_type;
794 proxy_entry->rule_index = rule_index;
795 proxy_entry->proto = proto;
796 proxy_entry->proxy_port = htons(proxy_port);
797 proxy_entry->server_port = htons(server_port);
798 proxy_entry->server_addr = server_addr;
799 proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
800 proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
801 proxy_entry->src_mask = src_mask;
802 proxy_entry->dst_mask = dst_mask;
836
803
837 RuleAdd(la, proxy_entry);
804 RuleAdd(la, proxy_entry);
838
805
839 return 0;
806 return 0;
840}
807}