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