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