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