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