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