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