1f987e1bdSBrian Somers /*- 2fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3fe267a55SPedro F. Giffuni * 4e83aaae3SBrian Somers * Copyright (c) 2001 Charles Mott <cm@linktel.net> 5f987e1bdSBrian Somers * All rights reserved. 6f987e1bdSBrian Somers * 7f987e1bdSBrian Somers * Redistribution and use in source and binary forms, with or without 8f987e1bdSBrian Somers * modification, are permitted provided that the following conditions 9f987e1bdSBrian Somers * are met: 10f987e1bdSBrian Somers * 1. Redistributions of source code must retain the above copyright 11f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer. 12f987e1bdSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 13f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer in the 14f987e1bdSBrian Somers * documentation and/or other materials provided with the distribution. 15f987e1bdSBrian Somers * 16f987e1bdSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17f987e1bdSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18f987e1bdSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19f987e1bdSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20f987e1bdSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21f987e1bdSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22f987e1bdSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23f987e1bdSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24f987e1bdSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25f987e1bdSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26f987e1bdSBrian Somers * SUCH DAMAGE. 27f987e1bdSBrian Somers */ 28f987e1bdSBrian Somers 29e2505aa6SMatthew Dillon #include <sys/cdefs.h> 30e2505aa6SMatthew Dillon __FBSDID("$FreeBSD$"); 31e2505aa6SMatthew Dillon 327d96f4efSBrian Somers /* file: alias_proxy.c 337d96f4efSBrian Somers 347d96f4efSBrian Somers This file encapsulates special operations related to transparent 357d96f4efSBrian Somers proxy redirection. This is where packets with a particular destination, 367d96f4efSBrian Somers usually tcp port 80, are redirected to a proxy server. 377d96f4efSBrian Somers 387d96f4efSBrian Somers When packets are proxied, the destination address and port are 397d96f4efSBrian Somers modified. In certain cases, it is necessary to somehow encode 407d96f4efSBrian Somers the original address/port info into the packet. Two methods are 417d96f4efSBrian Somers presently supported: addition of a [DEST addr port] string at the 429d5abbddSJens Schweikhardt beginning of a tcp stream, or inclusion of an optional field 437d96f4efSBrian Somers in the IP header. 447d96f4efSBrian Somers 457d96f4efSBrian Somers There is one public API function: 467d96f4efSBrian Somers 477d96f4efSBrian Somers PacketAliasProxyRule() -- Adds and deletes proxy 487d96f4efSBrian Somers rules. 497d96f4efSBrian Somers 507d96f4efSBrian Somers Rules are stored in a linear linked list, so lookup efficiency 517d96f4efSBrian Somers won't be too good for large lists. 527d96f4efSBrian Somers 537d96f4efSBrian Somers Initial development: April, 1998 (cjm) 547d96f4efSBrian Somers */ 557d96f4efSBrian Somers 567d96f4efSBrian Somers /* System includes */ 57c649a2e0SGleb Smirnoff #ifdef _KERNEL 58c649a2e0SGleb Smirnoff #include <sys/param.h> 59c649a2e0SGleb Smirnoff #include <sys/ctype.h> 60c649a2e0SGleb Smirnoff #include <sys/libkern.h> 61c649a2e0SGleb Smirnoff #include <sys/limits.h> 62c649a2e0SGleb Smirnoff #else 63c649a2e0SGleb Smirnoff #include <sys/types.h> 647d96f4efSBrian Somers #include <ctype.h> 657d96f4efSBrian Somers #include <stdio.h> 667d96f4efSBrian Somers #include <stdlib.h> 677d96f4efSBrian Somers #include <netdb.h> 68be4f3cd0SPaolo Pisati #include <string.h> 69c649a2e0SGleb Smirnoff #endif 707d96f4efSBrian Somers 717d96f4efSBrian Somers #include <netinet/tcp.h> 727d96f4efSBrian Somers 73c649a2e0SGleb Smirnoff #ifdef _KERNEL 74c649a2e0SGleb Smirnoff #include <netinet/libalias/alias.h> 7575bc2620SGleb Smirnoff #include <netinet/libalias/alias_local.h> 76be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_mod.h> 77c649a2e0SGleb Smirnoff #else 78be4f3cd0SPaolo Pisati #include <arpa/inet.h> 797d96f4efSBrian Somers #include "alias.h" /* Public API functions for libalias */ 8075bc2620SGleb Smirnoff #include "alias_local.h" /* Functions used by alias*.c */ 81c649a2e0SGleb Smirnoff #endif 827d96f4efSBrian Somers 837d96f4efSBrian Somers /* 847d96f4efSBrian Somers Data structures 857d96f4efSBrian Somers */ 867d96f4efSBrian Somers 877d96f4efSBrian Somers /* 887d96f4efSBrian Somers * A linked list of arbitrary length, based on struct proxy_entry is 897d96f4efSBrian Somers * used to store proxy rules. 907d96f4efSBrian Somers */ 91f0f93429SDag-Erling Smørgrav struct proxy_entry { 925e289f9eSPoul-Henning Kamp struct libalias *la; 937d96f4efSBrian Somers #define PROXY_TYPE_ENCODE_NONE 1 947d96f4efSBrian Somers #define PROXY_TYPE_ENCODE_TCPSTREAM 2 957d96f4efSBrian Somers #define PROXY_TYPE_ENCODE_IPHDR 3 967d96f4efSBrian Somers int rule_index; 977d96f4efSBrian Somers int proxy_type; 987d96f4efSBrian Somers u_char proto; 997d96f4efSBrian Somers u_short proxy_port; 1007d96f4efSBrian Somers u_short server_port; 1017d96f4efSBrian Somers 1027d96f4efSBrian Somers struct in_addr server_addr; 1037d96f4efSBrian Somers 1047d96f4efSBrian Somers struct in_addr src_addr; 1057d96f4efSBrian Somers struct in_addr src_mask; 1067d96f4efSBrian Somers 1077d96f4efSBrian Somers struct in_addr dst_addr; 1087d96f4efSBrian Somers struct in_addr dst_mask; 1097d96f4efSBrian Somers 1107d96f4efSBrian Somers struct proxy_entry *next; 1117d96f4efSBrian Somers struct proxy_entry *last; 1127d96f4efSBrian Somers }; 1137d96f4efSBrian Somers 1147d96f4efSBrian Somers /* 1157d96f4efSBrian Somers File scope variables 1167d96f4efSBrian Somers */ 1177d96f4efSBrian Somers 1187d96f4efSBrian Somers /* Local (static) functions: 1197d96f4efSBrian Somers 1207d96f4efSBrian Somers IpMask() -- Utility function for creating IP 1217d96f4efSBrian Somers masks from integer (1-32) specification. 1227d96f4efSBrian Somers IpAddr() -- Utility function for converting string 1237d96f4efSBrian Somers to IP address 1247d96f4efSBrian Somers IpPort() -- Utility function for converting string 1257d96f4efSBrian Somers to port number 1267d96f4efSBrian Somers RuleAdd() -- Adds an element to the rule list. 1277d96f4efSBrian Somers RuleDelete() -- Removes an element from the rule list. 1287d96f4efSBrian Somers RuleNumberDelete() -- Removes all elements from the rule list 1297d96f4efSBrian Somers having a certain rule number. 1307d96f4efSBrian Somers ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning 1317d96f4efSBrian Somers of a TCP stream. 1327d96f4efSBrian Somers ProxyEncodeIpHeader() -- Adds an IP option indicating the true 1337d96f4efSBrian Somers destination of a proxied IP packet 1347d96f4efSBrian Somers */ 1357d96f4efSBrian Somers 1367d96f4efSBrian Somers static int IpMask(int, struct in_addr *); 1377d96f4efSBrian Somers static int IpAddr(char *, struct in_addr *); 1387d96f4efSBrian Somers static int IpPort(char *, int, int *); 1395e289f9eSPoul-Henning Kamp static void RuleAdd(struct libalias *la, struct proxy_entry *); 1407d96f4efSBrian Somers static void RuleDelete(struct proxy_entry *); 1415e289f9eSPoul-Henning Kamp static int RuleNumberDelete(struct libalias *la, int); 1427d96f4efSBrian Somers static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int); 1437d96f4efSBrian Somers static void ProxyEncodeIpHeader(struct ip *, int); 1447d96f4efSBrian Somers 1457d96f4efSBrian Somers static int 1467d96f4efSBrian Somers IpMask(int nbits, struct in_addr *mask) 1477d96f4efSBrian Somers { 1487d96f4efSBrian Somers int i; 1497d96f4efSBrian Somers u_int imask; 1507d96f4efSBrian Somers 1517d96f4efSBrian Somers if (nbits < 0 || nbits > 32) 152ffcb611aSDag-Erling Smørgrav return (-1); 1537d96f4efSBrian Somers 1547d96f4efSBrian Somers imask = 0; 1557d96f4efSBrian Somers for (i = 0; i < nbits; i++) 1567d96f4efSBrian Somers imask = (imask >> 1) + 0x80000000; 1577d96f4efSBrian Somers mask->s_addr = htonl(imask); 1587d96f4efSBrian Somers 159ffcb611aSDag-Erling Smørgrav return (0); 1607d96f4efSBrian Somers } 1617d96f4efSBrian Somers 1627d96f4efSBrian Somers static int 1637d96f4efSBrian Somers IpAddr(char *s, struct in_addr *addr) 1647d96f4efSBrian Somers { 1657d96f4efSBrian Somers if (inet_aton(s, addr) == 0) 166ffcb611aSDag-Erling Smørgrav return (-1); 1677d96f4efSBrian Somers else 168ffcb611aSDag-Erling Smørgrav return (0); 1697d96f4efSBrian Somers } 1707d96f4efSBrian Somers 1717d96f4efSBrian Somers static int 1727d96f4efSBrian Somers IpPort(char *s, int proto, int *port) 1737d96f4efSBrian Somers { 1747d96f4efSBrian Somers int n; 1757d96f4efSBrian Somers 1767d96f4efSBrian Somers n = sscanf(s, "%d", port); 177e9d5db28SGleb Smirnoff if (n != 1) 178e9d5db28SGleb Smirnoff #ifndef _KERNEL /* XXX: we accept only numeric ports in kernel */ 179e9d5db28SGleb Smirnoff { 1807d96f4efSBrian Somers struct servent *se; 1817d96f4efSBrian Somers 1827d96f4efSBrian Somers if (proto == IPPROTO_TCP) 1837d96f4efSBrian Somers se = getservbyname(s, "tcp"); 1847d96f4efSBrian Somers else if (proto == IPPROTO_UDP) 1857d96f4efSBrian Somers se = getservbyname(s, "udp"); 1867d96f4efSBrian Somers else 187ffcb611aSDag-Erling Smørgrav return (-1); 1887d96f4efSBrian Somers 1897d96f4efSBrian Somers if (se == NULL) 190ffcb611aSDag-Erling Smørgrav return (-1); 1917d96f4efSBrian Somers 1927d96f4efSBrian Somers *port = (u_int) ntohs(se->s_port); 1937d96f4efSBrian Somers } 194e9d5db28SGleb Smirnoff #else 195e9d5db28SGleb Smirnoff return (-1); 196e9d5db28SGleb Smirnoff #endif 197ffcb611aSDag-Erling Smørgrav return (0); 1987d96f4efSBrian Somers } 1997d96f4efSBrian Somers 2007d96f4efSBrian Somers void 2015e289f9eSPoul-Henning Kamp RuleAdd(struct libalias *la, struct proxy_entry *entry) 2027d96f4efSBrian Somers { 2037d96f4efSBrian Somers int rule_index; 2047d96f4efSBrian Somers struct proxy_entry *ptr; 2057d96f4efSBrian Somers struct proxy_entry *ptr_last; 2067d96f4efSBrian Somers 207ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la); 208ccd57eeaSPaolo Pisati 20998373126SEd Maste entry->la = la; 210f0f93429SDag-Erling Smørgrav if (la->proxyList == NULL) { 2115e289f9eSPoul-Henning Kamp la->proxyList = entry; 2127d96f4efSBrian Somers entry->last = NULL; 2137d96f4efSBrian Somers entry->next = NULL; 2147d96f4efSBrian Somers return; 2157d96f4efSBrian Somers } 2167d96f4efSBrian Somers 2177d96f4efSBrian Somers rule_index = entry->rule_index; 2185e289f9eSPoul-Henning Kamp ptr = la->proxyList; 2197d96f4efSBrian Somers ptr_last = NULL; 220f0f93429SDag-Erling Smørgrav while (ptr != NULL) { 221f0f93429SDag-Erling Smørgrav if (ptr->rule_index >= rule_index) { 222f0f93429SDag-Erling Smørgrav if (ptr_last == NULL) { 2235e289f9eSPoul-Henning Kamp entry->next = la->proxyList; 2247d96f4efSBrian Somers entry->last = NULL; 2255e289f9eSPoul-Henning Kamp la->proxyList->last = entry; 2265e289f9eSPoul-Henning Kamp la->proxyList = entry; 2277d96f4efSBrian Somers return; 2287d96f4efSBrian Somers } 2297d96f4efSBrian Somers ptr_last->next = entry; 2307d96f4efSBrian Somers ptr->last = entry; 2317d96f4efSBrian Somers entry->last = ptr->last; 2327d96f4efSBrian Somers entry->next = ptr; 2337d96f4efSBrian Somers return; 2347d96f4efSBrian Somers } 2357d96f4efSBrian Somers ptr_last = ptr; 2367d96f4efSBrian Somers ptr = ptr->next; 2377d96f4efSBrian Somers } 2387d96f4efSBrian Somers 2397d96f4efSBrian Somers ptr_last->next = entry; 2407d96f4efSBrian Somers entry->last = ptr_last; 2417d96f4efSBrian Somers entry->next = NULL; 2427d96f4efSBrian Somers } 2437d96f4efSBrian Somers 2447d96f4efSBrian Somers static void 2457d96f4efSBrian Somers RuleDelete(struct proxy_entry *entry) 2467d96f4efSBrian Somers { 2475e289f9eSPoul-Henning Kamp struct libalias *la; 2485e289f9eSPoul-Henning Kamp 2495e289f9eSPoul-Henning Kamp la = entry->la; 250ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la); 2517d96f4efSBrian Somers if (entry->last != NULL) 2527d96f4efSBrian Somers entry->last->next = entry->next; 2537d96f4efSBrian Somers else 2545e289f9eSPoul-Henning Kamp la->proxyList = entry->next; 2557d96f4efSBrian Somers 2567d96f4efSBrian Somers if (entry->next != NULL) 2577d96f4efSBrian Somers entry->next->last = entry->last; 2587d96f4efSBrian Somers 2597d96f4efSBrian Somers free(entry); 2607d96f4efSBrian Somers } 2617d96f4efSBrian Somers 2627d96f4efSBrian Somers static int 2635e289f9eSPoul-Henning Kamp RuleNumberDelete(struct libalias *la, int rule_index) 2647d96f4efSBrian Somers { 2657d96f4efSBrian Somers int err; 2667d96f4efSBrian Somers struct proxy_entry *ptr; 2677d96f4efSBrian Somers 268ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la); 2697d96f4efSBrian Somers err = -1; 2705e289f9eSPoul-Henning Kamp ptr = la->proxyList; 271f0f93429SDag-Erling Smørgrav while (ptr != NULL) { 2727d96f4efSBrian Somers struct proxy_entry *ptr_next; 2737d96f4efSBrian Somers 2747d96f4efSBrian Somers ptr_next = ptr->next; 275f0f93429SDag-Erling Smørgrav if (ptr->rule_index == rule_index) { 2767d96f4efSBrian Somers err = 0; 2777d96f4efSBrian Somers RuleDelete(ptr); 2787d96f4efSBrian Somers } 2797d96f4efSBrian Somers ptr = ptr_next; 2807d96f4efSBrian Somers } 2817d96f4efSBrian Somers 282ffcb611aSDag-Erling Smørgrav return (err); 2837d96f4efSBrian Somers } 2847d96f4efSBrian Somers 2857d96f4efSBrian Somers static void 286ed01a582SDag-Erling Smørgrav ProxyEncodeTcpStream(struct alias_link *lnk, 2877d96f4efSBrian Somers struct ip *pip, 2887d96f4efSBrian Somers int maxpacketsize) 2897d96f4efSBrian Somers { 2907d96f4efSBrian Somers int slen; 2917d96f4efSBrian Somers char buffer[40]; 2927d96f4efSBrian Somers struct tcphdr *tc; 2938144690aSEric van Gyzen char addrbuf[INET_ADDRSTRLEN]; 2947d96f4efSBrian Somers 2957d96f4efSBrian Somers /* Compute pointer to tcp header */ 2969fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip); 2977d96f4efSBrian Somers 2987d96f4efSBrian Somers /* Don't modify if once already modified */ 2997d96f4efSBrian Somers 300ed01a582SDag-Erling Smørgrav if (GetAckModified(lnk)) 3017d96f4efSBrian Somers return; 3027d96f4efSBrian Somers 3037d96f4efSBrian Somers /* Translate destination address and port to string form */ 3047d96f4efSBrian Somers snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]", 3058144690aSEric van Gyzen inet_ntoa_r(GetProxyAddress(lnk), INET_NTOA_BUF(addrbuf)), 3068144690aSEric van Gyzen (u_int) ntohs(GetProxyPort(lnk))); 3077d96f4efSBrian Somers 3087d96f4efSBrian Somers /* Pad string out to a multiple of two in length */ 3097d96f4efSBrian Somers slen = strlen(buffer); 310f0f93429SDag-Erling Smørgrav switch (slen % 2) { 3117d96f4efSBrian Somers case 0: 3127d96f4efSBrian Somers strcat(buffer, " \n"); 3137d96f4efSBrian Somers slen += 2; 3147d96f4efSBrian Somers break; 3157d96f4efSBrian Somers case 1: 3167d96f4efSBrian Somers strcat(buffer, "\n"); 3177d96f4efSBrian Somers slen += 1; 3187d96f4efSBrian Somers } 3197d96f4efSBrian Somers 3207d96f4efSBrian Somers /* Check for packet overflow */ 321ed01a582SDag-Erling Smørgrav if ((int)(ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize) 3227d96f4efSBrian Somers return; 3237d96f4efSBrian Somers 3247d96f4efSBrian Somers /* Shift existing TCP data and insert destination string */ 3257d96f4efSBrian Somers { 3267d96f4efSBrian Somers int dlen; 3277d96f4efSBrian Somers int hlen; 3289160afeeSAlexander Kabaev char *p; 3297d96f4efSBrian Somers 3307d96f4efSBrian Somers hlen = (pip->ip_hl + tc->th_off) << 2; 3317d96f4efSBrian Somers dlen = ntohs(pip->ip_len) - hlen; 3327d96f4efSBrian Somers 3337d96f4efSBrian Somers /* Modify first packet that has data in it */ 3347d96f4efSBrian Somers 3357d96f4efSBrian Somers if (dlen == 0) 3367d96f4efSBrian Somers return; 3377d96f4efSBrian Somers 3387d96f4efSBrian Somers p = (char *)pip; 3397d96f4efSBrian Somers p += hlen; 3407d96f4efSBrian Somers 341c8d3ca72SGleb Smirnoff bcopy(p, p + slen, dlen); 3427d96f4efSBrian Somers memcpy(p, buffer, slen); 3437d96f4efSBrian Somers } 3447d96f4efSBrian Somers 3457d96f4efSBrian Somers /* Save information about modfied sequence number */ 3467d96f4efSBrian Somers { 3477d96f4efSBrian Somers int delta; 3487d96f4efSBrian Somers 349ed01a582SDag-Erling Smørgrav SetAckModified(lnk); 3504741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip); 3514741f3a1SPaolo Pisati delta = GetDeltaSeqOut(tc->th_seq, lnk); 3524741f3a1SPaolo Pisati AddSeq(lnk, delta + slen, pip->ip_hl, pip->ip_len, tc->th_seq, 3534741f3a1SPaolo Pisati tc->th_off); 3547d96f4efSBrian Somers } 3557d96f4efSBrian Somers 3567d96f4efSBrian Somers /* Update IP header packet length and checksum */ 3577d96f4efSBrian Somers { 3587d96f4efSBrian Somers int accumulate; 3597d96f4efSBrian Somers 3607d96f4efSBrian Somers accumulate = pip->ip_len; 3617d96f4efSBrian Somers pip->ip_len = htons(ntohs(pip->ip_len) + slen); 3627d96f4efSBrian Somers accumulate -= pip->ip_len; 3637d96f4efSBrian Somers 3647d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum); 3657d96f4efSBrian Somers } 3667d96f4efSBrian Somers 3677d96f4efSBrian Somers /* Update TCP checksum, Use TcpChecksum since so many things have 3687d96f4efSBrian Somers already changed. */ 3697d96f4efSBrian Somers 3707d96f4efSBrian Somers tc->th_sum = 0; 37159dde15eSGleb Smirnoff #ifdef _KERNEL 37259dde15eSGleb Smirnoff tc->th_x2 = 1; 37359dde15eSGleb Smirnoff #else 3747d96f4efSBrian Somers tc->th_sum = TcpChecksum(pip); 37559dde15eSGleb Smirnoff #endif 3767d96f4efSBrian Somers } 3777d96f4efSBrian Somers 3787d96f4efSBrian Somers static void 3797d96f4efSBrian Somers ProxyEncodeIpHeader(struct ip *pip, 3807d96f4efSBrian Somers int maxpacketsize) 3817d96f4efSBrian Somers { 3827d96f4efSBrian Somers #define OPTION_LEN_BYTES 8 3837d96f4efSBrian Somers #define OPTION_LEN_INT16 4 3847d96f4efSBrian Somers #define OPTION_LEN_INT32 2 385*bc596e56SAlex Richardson _Alignas(_Alignof(u_short)) u_char option[OPTION_LEN_BYTES]; 3867d96f4efSBrian Somers 3876293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG 3887d96f4efSBrian Somers fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip)); 3897d96f4efSBrian Somers fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip)); 3904c32f5d2SBrian Somers #endif 3917d96f4efSBrian Somers 392ed01a582SDag-Erling Smørgrav (void)maxpacketsize; 393ed01a582SDag-Erling Smørgrav 3947d96f4efSBrian Somers /* Check to see that there is room to add an IP option */ 3957d96f4efSBrian Somers if (pip->ip_hl > (0x0f - OPTION_LEN_INT32)) 3967d96f4efSBrian Somers return; 3977d96f4efSBrian Somers 3987d96f4efSBrian Somers /* Build option and copy into packet */ 3997d96f4efSBrian Somers { 4007d96f4efSBrian Somers u_char *ptr; 4017d96f4efSBrian Somers struct tcphdr *tc; 4027d96f4efSBrian Somers 4037d96f4efSBrian Somers ptr = (u_char *) pip; 4047d96f4efSBrian Somers ptr += 20; 4057d96f4efSBrian Somers memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20); 4067d96f4efSBrian Somers 4077d96f4efSBrian Somers option[0] = 0x64; /* class: 3 (reserved), option 4 */ 4087d96f4efSBrian Somers option[1] = OPTION_LEN_BYTES; 4097d96f4efSBrian Somers 4107d96f4efSBrian Somers memcpy(&option[2], (u_char *) & pip->ip_dst, 4); 4117d96f4efSBrian Somers 4129fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip); 4137d96f4efSBrian Somers memcpy(&option[6], (u_char *) & tc->th_sport, 2); 4147d96f4efSBrian Somers 4157d96f4efSBrian Somers memcpy(ptr, option, 8); 4167d96f4efSBrian Somers } 4177d96f4efSBrian Somers 4187d96f4efSBrian Somers /* Update checksum, header length and packet length */ 4197d96f4efSBrian Somers { 4207d96f4efSBrian Somers int i; 4217d96f4efSBrian Somers int accumulate; 4227d96f4efSBrian Somers u_short *sptr; 4237d96f4efSBrian Somers 4247d96f4efSBrian Somers sptr = (u_short *) option; 4257d96f4efSBrian Somers accumulate = 0; 4267d96f4efSBrian Somers for (i = 0; i < OPTION_LEN_INT16; i++) 4277d96f4efSBrian Somers accumulate -= *(sptr++); 4287d96f4efSBrian Somers 4297d96f4efSBrian Somers sptr = (u_short *) pip; 4307d96f4efSBrian Somers accumulate += *sptr; 4317d96f4efSBrian Somers pip->ip_hl += OPTION_LEN_INT32; 4327d96f4efSBrian Somers accumulate -= *sptr; 4337d96f4efSBrian Somers 4347d96f4efSBrian Somers accumulate += pip->ip_len; 4357d96f4efSBrian Somers pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES); 4367d96f4efSBrian Somers accumulate -= pip->ip_len; 4377d96f4efSBrian Somers 4387d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum); 4397d96f4efSBrian Somers } 4407d96f4efSBrian Somers #undef OPTION_LEN_BYTES 4417d96f4efSBrian Somers #undef OPTION_LEN_INT16 4427d96f4efSBrian Somers #undef OPTION_LEN_INT32 4436293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG 4447d96f4efSBrian Somers fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip)); 4457d96f4efSBrian Somers fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip)); 4464c32f5d2SBrian Somers #endif 4477d96f4efSBrian Somers } 4487d96f4efSBrian Somers 4497d96f4efSBrian Somers /* Functions by other packet alias source files 4507d96f4efSBrian Somers 4517d96f4efSBrian Somers ProxyCheck() -- Checks whether an outgoing packet should 4527d96f4efSBrian Somers be proxied. 4537d96f4efSBrian Somers ProxyModify() -- Encodes the original destination address/port 4547d96f4efSBrian Somers for a packet which is to be redirected to 4557d96f4efSBrian Somers a proxy server. 4567d96f4efSBrian Somers */ 4577d96f4efSBrian Somers 4587d96f4efSBrian Somers int 4594741f3a1SPaolo Pisati ProxyCheck(struct libalias *la, struct in_addr *proxy_server_addr, 4604741f3a1SPaolo Pisati u_short * proxy_server_port, struct in_addr src_addr, 4614741f3a1SPaolo Pisati struct in_addr dst_addr, u_short dst_port, u_char ip_p) 4627d96f4efSBrian Somers { 4637d96f4efSBrian Somers struct proxy_entry *ptr; 4647d96f4efSBrian Somers 465ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la); 4667d96f4efSBrian Somers 4675e289f9eSPoul-Henning Kamp ptr = la->proxyList; 468f0f93429SDag-Erling Smørgrav while (ptr != NULL) { 4697d96f4efSBrian Somers u_short proxy_port; 4707d96f4efSBrian Somers 4717d96f4efSBrian Somers proxy_port = ptr->proxy_port; 4727d96f4efSBrian Somers if ((dst_port == proxy_port || proxy_port == 0) 4734741f3a1SPaolo Pisati && ip_p == ptr->proto 474f0f93429SDag-Erling Smørgrav && src_addr.s_addr != ptr->server_addr.s_addr) { 4757d96f4efSBrian Somers struct in_addr src_addr_masked; 4767d96f4efSBrian Somers struct in_addr dst_addr_masked; 4777d96f4efSBrian Somers 4787d96f4efSBrian Somers src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr; 4797d96f4efSBrian Somers dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr; 4807d96f4efSBrian Somers 4817d96f4efSBrian Somers if ((src_addr_masked.s_addr == ptr->src_addr.s_addr) 482f0f93429SDag-Erling Smørgrav && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr)) { 4837d96f4efSBrian Somers if ((*proxy_server_port = ptr->server_port) == 0) 4847d96f4efSBrian Somers *proxy_server_port = dst_port; 4857d96f4efSBrian Somers *proxy_server_addr = ptr->server_addr; 486ffcb611aSDag-Erling Smørgrav return (ptr->proxy_type); 4877d96f4efSBrian Somers } 4887d96f4efSBrian Somers } 4897d96f4efSBrian Somers ptr = ptr->next; 4907d96f4efSBrian Somers } 4917d96f4efSBrian Somers 492ffcb611aSDag-Erling Smørgrav return (0); 4937d96f4efSBrian Somers } 4947d96f4efSBrian Somers 4957d96f4efSBrian Somers void 496ed01a582SDag-Erling Smørgrav ProxyModify(struct libalias *la, struct alias_link *lnk, 4977d96f4efSBrian Somers struct ip *pip, 4987d96f4efSBrian Somers int maxpacketsize, 4997d96f4efSBrian Somers int proxy_type) 5007d96f4efSBrian Somers { 501ed01a582SDag-Erling Smørgrav 502ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la); 503ed01a582SDag-Erling Smørgrav (void)la; 504ed01a582SDag-Erling Smørgrav 505f0f93429SDag-Erling Smørgrav switch (proxy_type) { 5067d96f4efSBrian Somers case PROXY_TYPE_ENCODE_IPHDR: 5077d96f4efSBrian Somers ProxyEncodeIpHeader(pip, maxpacketsize); 5087d96f4efSBrian Somers break; 5097d96f4efSBrian Somers 5107d96f4efSBrian Somers case PROXY_TYPE_ENCODE_TCPSTREAM: 511ed01a582SDag-Erling Smørgrav ProxyEncodeTcpStream(lnk, pip, maxpacketsize); 5127d96f4efSBrian Somers break; 5137d96f4efSBrian Somers } 5147d96f4efSBrian Somers } 5157d96f4efSBrian Somers 5167d96f4efSBrian Somers /* 5177d96f4efSBrian Somers Public API functions 5187d96f4efSBrian Somers */ 5197d96f4efSBrian Somers 5207d96f4efSBrian Somers int 5215e289f9eSPoul-Henning Kamp LibAliasProxyRule(struct libalias *la, const char *cmd) 5227d96f4efSBrian Somers { 5237d96f4efSBrian Somers /* 5247d96f4efSBrian Somers * This function takes command strings of the form: 5257d96f4efSBrian Somers * 5267d96f4efSBrian Somers * server <addr>[:<port>] 5277d96f4efSBrian Somers * [port <port>] 5287d96f4efSBrian Somers * [rule n] 5297d96f4efSBrian Somers * [proto tcp|udp] 5307d96f4efSBrian Somers * [src <addr>[/n]] 5317d96f4efSBrian Somers * [dst <addr>[/n]] 5327d96f4efSBrian Somers * [type encode_tcp_stream|encode_ip_hdr|no_encode] 5337d96f4efSBrian Somers * 5347d96f4efSBrian Somers * delete <rule number> 5357d96f4efSBrian Somers * 5367d96f4efSBrian Somers * Subfields can be in arbitrary order. Port numbers and addresses 5377d96f4efSBrian Somers * must be in either numeric or symbolic form. An optional rule number 5387d96f4efSBrian Somers * is used to control the order in which rules are searched. If two 5397d96f4efSBrian Somers * rules have the same number, then search order cannot be guaranteed, 5407d96f4efSBrian Somers * and the rules should be disjoint. If no rule number is specified, 5417d96f4efSBrian Somers * then 0 is used, and group 0 rules are always checked before any 5427d96f4efSBrian Somers * others. 5437d96f4efSBrian Somers */ 544ccd57eeaSPaolo Pisati int i, n, len, ret; 5457d96f4efSBrian Somers int cmd_len; 5467d96f4efSBrian Somers int token_count; 5477d96f4efSBrian Somers int state; 5487d96f4efSBrian Somers char *token; 5497d96f4efSBrian Somers char buffer[256]; 5507d96f4efSBrian Somers char str_port[sizeof(buffer)]; 5517d96f4efSBrian Somers char str_server_port[sizeof(buffer)]; 552d9e630b5SAndrey A. Chernov char *res = buffer; 5537d96f4efSBrian Somers 5547d96f4efSBrian Somers int rule_index; 5557d96f4efSBrian Somers int proto; 5567d96f4efSBrian Somers int proxy_type; 5577d96f4efSBrian Somers int proxy_port; 5587d96f4efSBrian Somers int server_port; 5597d96f4efSBrian Somers struct in_addr server_addr; 5607d96f4efSBrian Somers struct in_addr src_addr, src_mask; 5617d96f4efSBrian Somers struct in_addr dst_addr, dst_mask; 5627d96f4efSBrian Somers struct proxy_entry *proxy_entry; 5637d96f4efSBrian Somers 564ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la); 565ccd57eeaSPaolo Pisati ret = 0; 5667d96f4efSBrian Somers /* Copy command line into a buffer */ 5674834b77dSBrian Somers cmd += strspn(cmd, " \t"); 5687d96f4efSBrian Somers cmd_len = strlen(cmd); 569ccd57eeaSPaolo Pisati if (cmd_len > (int)(sizeof(buffer) - 1)) { 570ccd57eeaSPaolo Pisati ret = -1; 571ccd57eeaSPaolo Pisati goto getout; 572ccd57eeaSPaolo Pisati } 5737d96f4efSBrian Somers strcpy(buffer, cmd); 5747d96f4efSBrian Somers 5757d96f4efSBrian Somers /* Convert to lower case */ 5767d96f4efSBrian Somers len = strlen(buffer); 5777d96f4efSBrian Somers for (i = 0; i < len; i++) 578d9e630b5SAndrey A. Chernov buffer[i] = tolower((unsigned char)buffer[i]); 5797d96f4efSBrian Somers 5807d96f4efSBrian Somers /* Set default proxy type */ 5817d96f4efSBrian Somers 5827d96f4efSBrian Somers /* Set up default values */ 5837d96f4efSBrian Somers rule_index = 0; 5847d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_NONE; 5857d96f4efSBrian Somers proto = IPPROTO_TCP; 5867d96f4efSBrian Somers proxy_port = 0; 5877d96f4efSBrian Somers server_addr.s_addr = 0; 5887d96f4efSBrian Somers server_port = 0; 5897d96f4efSBrian Somers src_addr.s_addr = 0; 5907d96f4efSBrian Somers IpMask(0, &src_mask); 5917d96f4efSBrian Somers dst_addr.s_addr = 0; 5927d96f4efSBrian Somers IpMask(0, &dst_mask); 5937d96f4efSBrian Somers 5947d96f4efSBrian Somers str_port[0] = 0; 5957d96f4efSBrian Somers str_server_port[0] = 0; 5967d96f4efSBrian Somers 5977d96f4efSBrian Somers /* Parse command string with state machine */ 5987d96f4efSBrian Somers #define STATE_READ_KEYWORD 0 5997d96f4efSBrian Somers #define STATE_READ_TYPE 1 6007d96f4efSBrian Somers #define STATE_READ_PORT 2 6017d96f4efSBrian Somers #define STATE_READ_SERVER 3 6027d96f4efSBrian Somers #define STATE_READ_RULE 4 6037d96f4efSBrian Somers #define STATE_READ_DELETE 5 6047d96f4efSBrian Somers #define STATE_READ_PROTO 6 6057d96f4efSBrian Somers #define STATE_READ_SRC 7 6067d96f4efSBrian Somers #define STATE_READ_DST 8 6077d96f4efSBrian Somers state = STATE_READ_KEYWORD; 608d9e630b5SAndrey A. Chernov token = strsep(&res, " \t"); 6097d96f4efSBrian Somers token_count = 0; 610f0f93429SDag-Erling Smørgrav while (token != NULL) { 6117d96f4efSBrian Somers token_count++; 612f0f93429SDag-Erling Smørgrav switch (state) { 6137d96f4efSBrian Somers case STATE_READ_KEYWORD: 6147d96f4efSBrian Somers if (strcmp(token, "type") == 0) 6157d96f4efSBrian Somers state = STATE_READ_TYPE; 6167d96f4efSBrian Somers else if (strcmp(token, "port") == 0) 6177d96f4efSBrian Somers state = STATE_READ_PORT; 6187d96f4efSBrian Somers else if (strcmp(token, "server") == 0) 6197d96f4efSBrian Somers state = STATE_READ_SERVER; 6207d96f4efSBrian Somers else if (strcmp(token, "rule") == 0) 6217d96f4efSBrian Somers state = STATE_READ_RULE; 6227d96f4efSBrian Somers else if (strcmp(token, "delete") == 0) 6237d96f4efSBrian Somers state = STATE_READ_DELETE; 6247d96f4efSBrian Somers else if (strcmp(token, "proto") == 0) 6257d96f4efSBrian Somers state = STATE_READ_PROTO; 6267d96f4efSBrian Somers else if (strcmp(token, "src") == 0) 6277d96f4efSBrian Somers state = STATE_READ_SRC; 6287d96f4efSBrian Somers else if (strcmp(token, "dst") == 0) 6297d96f4efSBrian Somers state = STATE_READ_DST; 630ccd57eeaSPaolo Pisati else { 631ccd57eeaSPaolo Pisati ret = -1; 632ccd57eeaSPaolo Pisati goto getout; 633ccd57eeaSPaolo Pisati } 6347d96f4efSBrian Somers break; 6357d96f4efSBrian Somers 6367d96f4efSBrian Somers case STATE_READ_TYPE: 6377d96f4efSBrian Somers if (strcmp(token, "encode_ip_hdr") == 0) 6387d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_IPHDR; 6397d96f4efSBrian Somers else if (strcmp(token, "encode_tcp_stream") == 0) 6407d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM; 6417d96f4efSBrian Somers else if (strcmp(token, "no_encode") == 0) 6427d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_NONE; 643ccd57eeaSPaolo Pisati else { 644ccd57eeaSPaolo Pisati ret = -1; 645ccd57eeaSPaolo Pisati goto getout; 646ccd57eeaSPaolo Pisati } 6477d96f4efSBrian Somers state = STATE_READ_KEYWORD; 6487d96f4efSBrian Somers break; 6497d96f4efSBrian Somers 6507d96f4efSBrian Somers case STATE_READ_PORT: 6517d96f4efSBrian Somers strcpy(str_port, token); 6527d96f4efSBrian Somers state = STATE_READ_KEYWORD; 6537d96f4efSBrian Somers break; 6547d96f4efSBrian Somers 6557d96f4efSBrian Somers case STATE_READ_SERVER: 6567d96f4efSBrian Somers { 6577d96f4efSBrian Somers int err; 6587d96f4efSBrian Somers char *p; 6597d96f4efSBrian Somers char s[sizeof(buffer)]; 6607d96f4efSBrian Somers 6617d96f4efSBrian Somers p = token; 6627d96f4efSBrian Somers while (*p != ':' && *p != 0) 6637d96f4efSBrian Somers p++; 6647d96f4efSBrian Somers 665f0f93429SDag-Erling Smørgrav if (*p != ':') { 6667d96f4efSBrian Somers err = IpAddr(token, &server_addr); 667ccd57eeaSPaolo Pisati if (err) { 668ccd57eeaSPaolo Pisati ret = -1; 669ccd57eeaSPaolo Pisati goto getout; 670ccd57eeaSPaolo Pisati } 671f0f93429SDag-Erling Smørgrav } else { 6727d96f4efSBrian Somers *p = ' '; 6737d96f4efSBrian Somers 6747d96f4efSBrian Somers n = sscanf(token, "%s %s", s, str_server_port); 675ccd57eeaSPaolo Pisati if (n != 2) { 676ccd57eeaSPaolo Pisati ret = -1; 677ccd57eeaSPaolo Pisati goto getout; 678ccd57eeaSPaolo Pisati } 6797d96f4efSBrian Somers 6807d96f4efSBrian Somers err = IpAddr(s, &server_addr); 681ccd57eeaSPaolo Pisati if (err) { 682ccd57eeaSPaolo Pisati ret = -1; 683ccd57eeaSPaolo Pisati goto getout; 684ccd57eeaSPaolo Pisati } 6857d96f4efSBrian Somers } 6867d96f4efSBrian Somers } 6877d96f4efSBrian Somers state = STATE_READ_KEYWORD; 6887d96f4efSBrian Somers break; 6897d96f4efSBrian Somers 6907d96f4efSBrian Somers case STATE_READ_RULE: 6917d96f4efSBrian Somers n = sscanf(token, "%d", &rule_index); 692ccd57eeaSPaolo Pisati if (n != 1 || rule_index < 0) { 693ccd57eeaSPaolo Pisati ret = -1; 694ccd57eeaSPaolo Pisati goto getout; 695ccd57eeaSPaolo Pisati } 6967d96f4efSBrian Somers state = STATE_READ_KEYWORD; 6977d96f4efSBrian Somers break; 6987d96f4efSBrian Somers 6997d96f4efSBrian Somers case STATE_READ_DELETE: 7007d96f4efSBrian Somers { 7017d96f4efSBrian Somers int err; 7027d96f4efSBrian Somers int rule_to_delete; 7037d96f4efSBrian Somers 704ccd57eeaSPaolo Pisati if (token_count != 2) { 705ccd57eeaSPaolo Pisati ret = -1; 706ccd57eeaSPaolo Pisati goto getout; 707ccd57eeaSPaolo Pisati } 7087d96f4efSBrian Somers 7097d96f4efSBrian Somers n = sscanf(token, "%d", &rule_to_delete); 710ccd57eeaSPaolo Pisati if (n != 1) { 711ccd57eeaSPaolo Pisati ret = -1; 712ccd57eeaSPaolo Pisati goto getout; 713ccd57eeaSPaolo Pisati } 7145e289f9eSPoul-Henning Kamp err = RuleNumberDelete(la, rule_to_delete); 7157d96f4efSBrian Somers if (err) 716ccd57eeaSPaolo Pisati ret = -1; 717fdb727f4SConrad Meyer else 718ccd57eeaSPaolo Pisati ret = 0; 719ccd57eeaSPaolo Pisati goto getout; 7207d96f4efSBrian Somers } 7217d96f4efSBrian Somers 7227d96f4efSBrian Somers case STATE_READ_PROTO: 7237d96f4efSBrian Somers if (strcmp(token, "tcp") == 0) 7247d96f4efSBrian Somers proto = IPPROTO_TCP; 7257d96f4efSBrian Somers else if (strcmp(token, "udp") == 0) 7267d96f4efSBrian Somers proto = IPPROTO_UDP; 727ccd57eeaSPaolo Pisati else { 728ccd57eeaSPaolo Pisati ret = -1; 729ccd57eeaSPaolo Pisati goto getout; 730ccd57eeaSPaolo Pisati } 7317d96f4efSBrian Somers state = STATE_READ_KEYWORD; 7327d96f4efSBrian Somers break; 7337d96f4efSBrian Somers 7347d96f4efSBrian Somers case STATE_READ_SRC: 7357d96f4efSBrian Somers case STATE_READ_DST: 7367d96f4efSBrian Somers { 7377d96f4efSBrian Somers int err; 7387d96f4efSBrian Somers char *p; 7397d96f4efSBrian Somers struct in_addr mask; 7407d96f4efSBrian Somers struct in_addr addr; 7417d96f4efSBrian Somers 7427d96f4efSBrian Somers p = token; 7437d96f4efSBrian Somers while (*p != '/' && *p != 0) 7447d96f4efSBrian Somers p++; 7457d96f4efSBrian Somers 746f0f93429SDag-Erling Smørgrav if (*p != '/') { 7477d96f4efSBrian Somers IpMask(32, &mask); 7487d96f4efSBrian Somers err = IpAddr(token, &addr); 749ccd57eeaSPaolo Pisati if (err) { 750ccd57eeaSPaolo Pisati ret = -1; 751ccd57eeaSPaolo Pisati goto getout; 752ccd57eeaSPaolo Pisati } 753f0f93429SDag-Erling Smørgrav } else { 7547d96f4efSBrian Somers int nbits; 7557d96f4efSBrian Somers char s[sizeof(buffer)]; 7567d96f4efSBrian Somers 7577d96f4efSBrian Somers *p = ' '; 7587d96f4efSBrian Somers n = sscanf(token, "%s %d", s, &nbits); 759ccd57eeaSPaolo Pisati if (n != 2) { 760ccd57eeaSPaolo Pisati ret = -1; 761ccd57eeaSPaolo Pisati goto getout; 762ccd57eeaSPaolo Pisati } 7637d96f4efSBrian Somers 7647d96f4efSBrian Somers err = IpAddr(s, &addr); 765ccd57eeaSPaolo Pisati if (err) { 766ccd57eeaSPaolo Pisati ret = -1; 767ccd57eeaSPaolo Pisati goto getout; 768ccd57eeaSPaolo Pisati } 7697d96f4efSBrian Somers 7707d96f4efSBrian Somers err = IpMask(nbits, &mask); 771ccd57eeaSPaolo Pisati if (err) { 772ccd57eeaSPaolo Pisati ret = -1; 773ccd57eeaSPaolo Pisati goto getout; 774ccd57eeaSPaolo Pisati } 7757d96f4efSBrian Somers } 7767d96f4efSBrian Somers 777f0f93429SDag-Erling Smørgrav if (state == STATE_READ_SRC) { 7787d96f4efSBrian Somers src_addr = addr; 7797d96f4efSBrian Somers src_mask = mask; 780f0f93429SDag-Erling Smørgrav } else { 7817d96f4efSBrian Somers dst_addr = addr; 7827d96f4efSBrian Somers dst_mask = mask; 7837d96f4efSBrian Somers } 7847d96f4efSBrian Somers } 7857d96f4efSBrian Somers state = STATE_READ_KEYWORD; 7867d96f4efSBrian Somers break; 7877d96f4efSBrian Somers 7887d96f4efSBrian Somers default: 789ccd57eeaSPaolo Pisati ret = -1; 790ccd57eeaSPaolo Pisati goto getout; 7917d96f4efSBrian Somers break; 7927d96f4efSBrian Somers } 7937d96f4efSBrian Somers 794d9e630b5SAndrey A. Chernov do { 795d9e630b5SAndrey A. Chernov token = strsep(&res, " \t"); 796d9e630b5SAndrey A. Chernov } while (token != NULL && !*token); 7977d96f4efSBrian Somers } 7987d96f4efSBrian Somers #undef STATE_READ_KEYWORD 7997d96f4efSBrian Somers #undef STATE_READ_TYPE 8007d96f4efSBrian Somers #undef STATE_READ_PORT 8017d96f4efSBrian Somers #undef STATE_READ_SERVER 8027d96f4efSBrian Somers #undef STATE_READ_RULE 8037d96f4efSBrian Somers #undef STATE_READ_DELETE 8047d96f4efSBrian Somers #undef STATE_READ_PROTO 8057d96f4efSBrian Somers #undef STATE_READ_SRC 8067d96f4efSBrian Somers #undef STATE_READ_DST 8077d96f4efSBrian Somers 8087d96f4efSBrian Somers /* Convert port strings to numbers. This needs to be done after 8097d96f4efSBrian Somers the string is parsed, because the prototype might not be designated 8107d96f4efSBrian Somers before the ports (which might be symbolic entries in /etc/services) */ 8117d96f4efSBrian Somers 812f0f93429SDag-Erling Smørgrav if (strlen(str_port) != 0) { 8137d96f4efSBrian Somers int err; 8147d96f4efSBrian Somers 8157d96f4efSBrian Somers err = IpPort(str_port, proto, &proxy_port); 816ccd57eeaSPaolo Pisati if (err) { 817ccd57eeaSPaolo Pisati ret = -1; 818ccd57eeaSPaolo Pisati goto getout; 819ccd57eeaSPaolo Pisati } 820f0f93429SDag-Erling Smørgrav } else { 8217d96f4efSBrian Somers proxy_port = 0; 8227d96f4efSBrian Somers } 8237d96f4efSBrian Somers 824f0f93429SDag-Erling Smørgrav if (strlen(str_server_port) != 0) { 8257d96f4efSBrian Somers int err; 8267d96f4efSBrian Somers 8277d96f4efSBrian Somers err = IpPort(str_server_port, proto, &server_port); 828ccd57eeaSPaolo Pisati if (err) { 829ccd57eeaSPaolo Pisati ret = -1; 830ccd57eeaSPaolo Pisati goto getout; 831ccd57eeaSPaolo Pisati } 832f0f93429SDag-Erling Smørgrav } else { 8337d96f4efSBrian Somers server_port = 0; 8347d96f4efSBrian Somers } 8357d96f4efSBrian Somers 8367d96f4efSBrian Somers /* Check that at least the server address has been defined */ 837ccd57eeaSPaolo Pisati if (server_addr.s_addr == 0) { 838ccd57eeaSPaolo Pisati ret = -1; 839ccd57eeaSPaolo Pisati goto getout; 840ccd57eeaSPaolo Pisati } 8417d96f4efSBrian Somers 8427d96f4efSBrian Somers /* Add to linked list */ 8437d96f4efSBrian Somers proxy_entry = malloc(sizeof(struct proxy_entry)); 844ccd57eeaSPaolo Pisati if (proxy_entry == NULL) { 845ccd57eeaSPaolo Pisati ret = -1; 846ccd57eeaSPaolo Pisati goto getout; 847ccd57eeaSPaolo Pisati } 8487d96f4efSBrian Somers 8497d96f4efSBrian Somers proxy_entry->proxy_type = proxy_type; 8507d96f4efSBrian Somers proxy_entry->rule_index = rule_index; 8517d96f4efSBrian Somers proxy_entry->proto = proto; 8527d96f4efSBrian Somers proxy_entry->proxy_port = htons(proxy_port); 8537d96f4efSBrian Somers proxy_entry->server_port = htons(server_port); 8547d96f4efSBrian Somers proxy_entry->server_addr = server_addr; 8557d96f4efSBrian Somers proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr; 8567d96f4efSBrian Somers proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr; 8577d96f4efSBrian Somers proxy_entry->src_mask = src_mask; 8587d96f4efSBrian Somers proxy_entry->dst_mask = dst_mask; 8597d96f4efSBrian Somers 8605e289f9eSPoul-Henning Kamp RuleAdd(la, proxy_entry); 8617d96f4efSBrian Somers 862ccd57eeaSPaolo Pisati getout: 863ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la); 864ccd57eeaSPaolo Pisati return (ret); 8657d96f4efSBrian Somers } 866