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 */ 115struct 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 144static 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 166static int IpMask(int, struct in_addr *); 167static int IpAddr(char *, struct in_addr *); 168static int IpPort(char *, int, int *); 169static void RuleAdd(struct proxy_entry *); 170static void RuleDelete(struct proxy_entry *); 171static int RuleNumberDelete(int); 172static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int); 173static void ProxyEncodeIpHeader(struct ip *, int); 174 175static int 176IpMask(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 192static int 193IpAddr(char *s, struct in_addr *addr) 194{ 195 if (inet_aton(s, addr) == 0) 196 return -1; 197 else 198 return 0; 199} 200 201static int 202IpPort(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 227void 228RuleAdd(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 273static void 274RuleDelete(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 287static int 288RuleNumberDelete(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 312static void 313ProxyEncodeTcpStream(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 398static void 399ProxyEncodeIpHeader(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 477int 478ProxyCheck(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 523void 524ProxyModify(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 546int 547PacketAliasProxyRule(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} 866