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