1f987e1bdSBrian Somers /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
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>
307d96f4efSBrian Somers /* file: alias_proxy.c
317d96f4efSBrian Somers
327d96f4efSBrian Somers This file encapsulates special operations related to transparent
337d96f4efSBrian Somers proxy redirection. This is where packets with a particular destination,
347d96f4efSBrian Somers usually tcp port 80, are redirected to a proxy server.
357d96f4efSBrian Somers
367d96f4efSBrian Somers When packets are proxied, the destination address and port are
377d96f4efSBrian Somers modified. In certain cases, it is necessary to somehow encode
387d96f4efSBrian Somers the original address/port info into the packet. Two methods are
397d96f4efSBrian Somers presently supported: addition of a [DEST addr port] string at the
409d5abbddSJens Schweikhardt beginning of a tcp stream, or inclusion of an optional field
417d96f4efSBrian Somers in the IP header.
427d96f4efSBrian Somers
437d96f4efSBrian Somers There is one public API function:
447d96f4efSBrian Somers
457d96f4efSBrian Somers PacketAliasProxyRule() -- Adds and deletes proxy
467d96f4efSBrian Somers rules.
477d96f4efSBrian Somers
487d96f4efSBrian Somers Rules are stored in a linear linked list, so lookup efficiency
497d96f4efSBrian Somers won't be too good for large lists.
507d96f4efSBrian Somers
517d96f4efSBrian Somers Initial development: April, 1998 (cjm)
527d96f4efSBrian Somers */
537d96f4efSBrian Somers
547d96f4efSBrian Somers /* System includes */
55c649a2e0SGleb Smirnoff #ifdef _KERNEL
56c649a2e0SGleb Smirnoff #include <sys/param.h>
57c649a2e0SGleb Smirnoff #include <sys/ctype.h>
58c649a2e0SGleb Smirnoff #include <sys/libkern.h>
59c649a2e0SGleb Smirnoff #include <sys/limits.h>
60c649a2e0SGleb Smirnoff #else
61c649a2e0SGleb Smirnoff #include <sys/types.h>
627d96f4efSBrian Somers #include <ctype.h>
637d96f4efSBrian Somers #include <stdio.h>
647d96f4efSBrian Somers #include <stdlib.h>
657d96f4efSBrian Somers #include <netdb.h>
66be4f3cd0SPaolo Pisati #include <string.h>
67c649a2e0SGleb Smirnoff #endif
687d96f4efSBrian Somers
697d96f4efSBrian Somers #include <netinet/tcp.h>
707d96f4efSBrian Somers
71c649a2e0SGleb Smirnoff #ifdef _KERNEL
72c649a2e0SGleb Smirnoff #include <netinet/libalias/alias.h>
7375bc2620SGleb Smirnoff #include <netinet/libalias/alias_local.h>
74be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_mod.h>
75c649a2e0SGleb Smirnoff #else
76be4f3cd0SPaolo Pisati #include <arpa/inet.h>
77effc8e57SLutz Donnerhacke
787d96f4efSBrian Somers #include "alias.h" /* Public API functions for libalias */
7975bc2620SGleb Smirnoff #include "alias_local.h" /* Functions used by alias*.c */
80c649a2e0SGleb Smirnoff #endif
817d96f4efSBrian Somers
827d96f4efSBrian Somers /*
837d96f4efSBrian Somers Data structures
847d96f4efSBrian Somers */
857d96f4efSBrian Somers
867d96f4efSBrian Somers /*
877d96f4efSBrian Somers * A linked list of arbitrary length, based on struct proxy_entry is
887d96f4efSBrian Somers * used to store proxy rules.
897d96f4efSBrian Somers */
90f0f93429SDag-Erling Smørgrav struct proxy_entry {
915e289f9eSPoul-Henning Kamp struct libalias *la;
927d96f4efSBrian Somers #define PROXY_TYPE_ENCODE_NONE 1
937d96f4efSBrian Somers #define PROXY_TYPE_ENCODE_TCPSTREAM 2
947d96f4efSBrian Somers #define PROXY_TYPE_ENCODE_IPHDR 3
957d96f4efSBrian Somers int rule_index;
967d96f4efSBrian Somers int proxy_type;
977d96f4efSBrian Somers u_char proto;
987d96f4efSBrian Somers u_short proxy_port;
997d96f4efSBrian Somers u_short server_port;
1007d96f4efSBrian Somers
1017d96f4efSBrian Somers struct in_addr server_addr;
1027d96f4efSBrian Somers
1037d96f4efSBrian Somers struct in_addr src_addr;
1047d96f4efSBrian Somers struct in_addr src_mask;
1057d96f4efSBrian Somers
1067d96f4efSBrian Somers struct in_addr dst_addr;
1077d96f4efSBrian Somers struct in_addr dst_mask;
1087d96f4efSBrian Somers
1097d96f4efSBrian Somers struct proxy_entry *next;
1107d96f4efSBrian Somers struct proxy_entry *last;
1117d96f4efSBrian Somers };
1127d96f4efSBrian Somers
1137d96f4efSBrian Somers /*
1147d96f4efSBrian Somers File scope variables
1157d96f4efSBrian Somers */
1167d96f4efSBrian Somers
1177d96f4efSBrian Somers /* Local (static) functions:
1187d96f4efSBrian Somers
1197d96f4efSBrian Somers IpMask() -- Utility function for creating IP
1207d96f4efSBrian Somers masks from integer (1-32) specification.
1217d96f4efSBrian Somers IpAddr() -- Utility function for converting string
1227d96f4efSBrian Somers to IP address
1237d96f4efSBrian Somers IpPort() -- Utility function for converting string
1247d96f4efSBrian Somers to port number
1257d96f4efSBrian Somers RuleAdd() -- Adds an element to the rule list.
1267d96f4efSBrian Somers RuleDelete() -- Removes an element from the rule list.
1277d96f4efSBrian Somers RuleNumberDelete() -- Removes all elements from the rule list
1287d96f4efSBrian Somers having a certain rule number.
1297d96f4efSBrian Somers ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning
1307d96f4efSBrian Somers of a TCP stream.
1317d96f4efSBrian Somers ProxyEncodeIpHeader() -- Adds an IP option indicating the true
1327d96f4efSBrian Somers destination of a proxied IP packet
1337d96f4efSBrian Somers */
1347d96f4efSBrian Somers
1357d96f4efSBrian Somers static int IpMask(int, struct in_addr *);
1367d96f4efSBrian Somers static int IpAddr(char *, struct in_addr *);
1377d96f4efSBrian Somers static int IpPort(char *, int, int *);
1385e289f9eSPoul-Henning Kamp static void RuleAdd(struct libalias *la, struct proxy_entry *);
1397d96f4efSBrian Somers static void RuleDelete(struct proxy_entry *);
1405e289f9eSPoul-Henning Kamp static int RuleNumberDelete(struct libalias *la, int);
1417d96f4efSBrian Somers static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int);
1427d96f4efSBrian Somers static void ProxyEncodeIpHeader(struct ip *, int);
1437d96f4efSBrian Somers
1447d96f4efSBrian Somers static int
IpMask(int nbits,struct in_addr * mask)1457d96f4efSBrian Somers IpMask(int nbits, struct in_addr *mask)
1467d96f4efSBrian Somers {
1477d96f4efSBrian Somers int i;
1487d96f4efSBrian Somers u_int imask;
1497d96f4efSBrian Somers
1507d96f4efSBrian Somers if (nbits < 0 || nbits > 32)
151ffcb611aSDag-Erling Smørgrav return (-1);
1527d96f4efSBrian Somers
1537d96f4efSBrian Somers imask = 0;
1547d96f4efSBrian Somers for (i = 0; i < nbits; i++)
1557d96f4efSBrian Somers imask = (imask >> 1) + 0x80000000;
1567d96f4efSBrian Somers mask->s_addr = htonl(imask);
1577d96f4efSBrian Somers
158ffcb611aSDag-Erling Smørgrav return (0);
1597d96f4efSBrian Somers }
1607d96f4efSBrian Somers
1617d96f4efSBrian Somers static int
IpAddr(char * s,struct in_addr * addr)1627d96f4efSBrian Somers IpAddr(char *s, struct in_addr *addr)
1637d96f4efSBrian Somers {
1647d96f4efSBrian Somers if (inet_aton(s, addr) == 0)
165ffcb611aSDag-Erling Smørgrav return (-1);
1667d96f4efSBrian Somers else
167ffcb611aSDag-Erling Smørgrav return (0);
1687d96f4efSBrian Somers }
1697d96f4efSBrian Somers
1707d96f4efSBrian Somers static int
IpPort(char * s,int proto,int * port)1717d96f4efSBrian Somers IpPort(char *s, int proto, int *port)
1727d96f4efSBrian Somers {
1737d96f4efSBrian Somers int n;
1747d96f4efSBrian Somers
1757d96f4efSBrian Somers n = sscanf(s, "%d", port);
176e9d5db28SGleb Smirnoff if (n != 1)
177e9d5db28SGleb Smirnoff #ifndef _KERNEL /* XXX: we accept only numeric ports in kernel */
178e9d5db28SGleb Smirnoff {
1797d96f4efSBrian Somers struct servent *se;
1807d96f4efSBrian Somers
1817d96f4efSBrian Somers if (proto == IPPROTO_TCP)
1827d96f4efSBrian Somers se = getservbyname(s, "tcp");
1837d96f4efSBrian Somers else if (proto == IPPROTO_UDP)
1847d96f4efSBrian Somers se = getservbyname(s, "udp");
1857d96f4efSBrian Somers else
186ffcb611aSDag-Erling Smørgrav return (-1);
1877d96f4efSBrian Somers
1887d96f4efSBrian Somers if (se == NULL)
189ffcb611aSDag-Erling Smørgrav return (-1);
1907d96f4efSBrian Somers
1917d96f4efSBrian Somers *port = (u_int)ntohs(se->s_port);
1927d96f4efSBrian Somers }
193e9d5db28SGleb Smirnoff #else
194e9d5db28SGleb Smirnoff return (-1);
195e9d5db28SGleb Smirnoff #endif
196ffcb611aSDag-Erling Smørgrav return (0);
1977d96f4efSBrian Somers }
1987d96f4efSBrian Somers
1997d96f4efSBrian Somers void
RuleAdd(struct libalias * la,struct proxy_entry * entry)2005e289f9eSPoul-Henning Kamp RuleAdd(struct libalias *la, struct proxy_entry *entry)
2017d96f4efSBrian Somers {
2027d96f4efSBrian Somers int rule_index;
2037d96f4efSBrian Somers struct proxy_entry *ptr;
2047d96f4efSBrian Somers struct proxy_entry *ptr_last;
2057d96f4efSBrian Somers
206ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
207ccd57eeaSPaolo Pisati
20898373126SEd Maste entry->la = la;
209f0f93429SDag-Erling Smørgrav if (la->proxyList == NULL) {
2105e289f9eSPoul-Henning Kamp la->proxyList = entry;
2117d96f4efSBrian Somers entry->last = NULL;
2127d96f4efSBrian Somers entry->next = NULL;
2137d96f4efSBrian Somers return;
2147d96f4efSBrian Somers }
2157d96f4efSBrian Somers
2167d96f4efSBrian Somers rule_index = entry->rule_index;
2175e289f9eSPoul-Henning Kamp ptr = la->proxyList;
2187d96f4efSBrian Somers ptr_last = NULL;
219f0f93429SDag-Erling Smørgrav while (ptr != NULL) {
220f0f93429SDag-Erling Smørgrav if (ptr->rule_index >= rule_index) {
221f0f93429SDag-Erling Smørgrav if (ptr_last == NULL) {
2225e289f9eSPoul-Henning Kamp entry->next = la->proxyList;
2237d96f4efSBrian Somers entry->last = NULL;
2245e289f9eSPoul-Henning Kamp la->proxyList->last = entry;
2255e289f9eSPoul-Henning Kamp la->proxyList = entry;
2267d96f4efSBrian Somers return;
2277d96f4efSBrian Somers }
2287d96f4efSBrian Somers ptr_last->next = entry;
2297d96f4efSBrian Somers ptr->last = entry;
2307d96f4efSBrian Somers entry->last = ptr->last;
2317d96f4efSBrian Somers entry->next = ptr;
2327d96f4efSBrian Somers return;
2337d96f4efSBrian Somers }
2347d96f4efSBrian Somers ptr_last = ptr;
2357d96f4efSBrian Somers ptr = ptr->next;
2367d96f4efSBrian Somers }
2377d96f4efSBrian Somers
2387d96f4efSBrian Somers ptr_last->next = entry;
2397d96f4efSBrian Somers entry->last = ptr_last;
2407d96f4efSBrian Somers entry->next = NULL;
2417d96f4efSBrian Somers }
2427d96f4efSBrian Somers
2437d96f4efSBrian Somers static void
RuleDelete(struct proxy_entry * entry)2447d96f4efSBrian Somers RuleDelete(struct proxy_entry *entry)
2457d96f4efSBrian Somers {
2465e289f9eSPoul-Henning Kamp struct libalias *la;
2475e289f9eSPoul-Henning Kamp
2485e289f9eSPoul-Henning Kamp la = entry->la;
249ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
2507d96f4efSBrian Somers if (entry->last != NULL)
2517d96f4efSBrian Somers entry->last->next = entry->next;
2527d96f4efSBrian Somers else
2535e289f9eSPoul-Henning Kamp la->proxyList = entry->next;
2547d96f4efSBrian Somers
2557d96f4efSBrian Somers if (entry->next != NULL)
2567d96f4efSBrian Somers entry->next->last = entry->last;
2577d96f4efSBrian Somers
2587d96f4efSBrian Somers free(entry);
2597d96f4efSBrian Somers }
2607d96f4efSBrian Somers
2617d96f4efSBrian Somers static int
RuleNumberDelete(struct libalias * la,int rule_index)2625e289f9eSPoul-Henning Kamp RuleNumberDelete(struct libalias *la, int rule_index)
2637d96f4efSBrian Somers {
2647d96f4efSBrian Somers int err;
2657d96f4efSBrian Somers struct proxy_entry *ptr;
2667d96f4efSBrian Somers
267ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
2687d96f4efSBrian Somers err = -1;
2695e289f9eSPoul-Henning Kamp ptr = la->proxyList;
270f0f93429SDag-Erling Smørgrav while (ptr != NULL) {
2717d96f4efSBrian Somers struct proxy_entry *ptr_next;
2727d96f4efSBrian Somers
2737d96f4efSBrian Somers ptr_next = ptr->next;
274f0f93429SDag-Erling Smørgrav if (ptr->rule_index == rule_index) {
2757d96f4efSBrian Somers err = 0;
2767d96f4efSBrian Somers RuleDelete(ptr);
2777d96f4efSBrian Somers }
2787d96f4efSBrian Somers ptr = ptr_next;
2797d96f4efSBrian Somers }
2807d96f4efSBrian Somers
281ffcb611aSDag-Erling Smørgrav return (err);
2827d96f4efSBrian Somers }
2837d96f4efSBrian Somers
2847d96f4efSBrian Somers static void
ProxyEncodeTcpStream(struct alias_link * lnk,struct ip * pip,int maxpacketsize)285ed01a582SDag-Erling Smørgrav ProxyEncodeTcpStream(struct alias_link *lnk,
2867d96f4efSBrian Somers struct ip *pip,
2877d96f4efSBrian Somers int maxpacketsize)
2887d96f4efSBrian Somers {
2897d96f4efSBrian Somers int slen;
2907d96f4efSBrian Somers char buffer[40];
2917d96f4efSBrian Somers struct tcphdr *tc;
2928144690aSEric van Gyzen char addrbuf[INET_ADDRSTRLEN];
2937d96f4efSBrian Somers
2947d96f4efSBrian Somers /* Compute pointer to tcp header */
2959fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
2967d96f4efSBrian Somers
2977d96f4efSBrian Somers /* Don't modify if once already modified */
298ed01a582SDag-Erling Smørgrav if (GetAckModified(lnk))
2997d96f4efSBrian Somers return;
3007d96f4efSBrian Somers
3017d96f4efSBrian Somers /* Translate destination address and port to string form */
3027d96f4efSBrian Somers snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]",
3038144690aSEric van Gyzen inet_ntoa_r(GetProxyAddress(lnk), INET_NTOA_BUF(addrbuf)),
3048144690aSEric van Gyzen (u_int)ntohs(GetProxyPort(lnk)));
3057d96f4efSBrian Somers
3067d96f4efSBrian Somers /* Pad string out to a multiple of two in length */
3077d96f4efSBrian Somers slen = strlen(buffer);
308f0f93429SDag-Erling Smørgrav switch (slen % 2) {
3097d96f4efSBrian Somers case 0:
3107d96f4efSBrian Somers strcat(buffer, " \n");
3117d96f4efSBrian Somers slen += 2;
3127d96f4efSBrian Somers break;
3137d96f4efSBrian Somers case 1:
3147d96f4efSBrian Somers strcat(buffer, "\n");
3157d96f4efSBrian Somers slen += 1;
3167d96f4efSBrian Somers }
3177d96f4efSBrian Somers
3187d96f4efSBrian Somers /* Check for packet overflow */
319ed01a582SDag-Erling Smørgrav if ((int)(ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize)
3207d96f4efSBrian Somers return;
3217d96f4efSBrian Somers
3227d96f4efSBrian Somers /* Shift existing TCP data and insert destination string */
3237d96f4efSBrian Somers {
3247d96f4efSBrian Somers int dlen;
3257d96f4efSBrian Somers int hlen;
3269160afeeSAlexander Kabaev char *p;
3277d96f4efSBrian Somers
3287d96f4efSBrian Somers hlen = (pip->ip_hl + tc->th_off) << 2;
3297d96f4efSBrian Somers dlen = ntohs(pip->ip_len) - hlen;
3307d96f4efSBrian Somers
3317d96f4efSBrian Somers /* Modify first packet that has data in it */
3327d96f4efSBrian Somers if (dlen == 0)
3337d96f4efSBrian Somers return;
3347d96f4efSBrian Somers
3357d96f4efSBrian Somers p = (char *)pip;
3367d96f4efSBrian Somers p += hlen;
3377d96f4efSBrian Somers
338c8d3ca72SGleb Smirnoff bcopy(p, p + slen, dlen);
3397d96f4efSBrian Somers memcpy(p, buffer, slen);
3407d96f4efSBrian Somers }
3417d96f4efSBrian Somers
3421cfd924fSGordon Bergling /* Save information about modified sequence number */
3437d96f4efSBrian Somers {
3447d96f4efSBrian Somers int delta;
3457d96f4efSBrian Somers
346ed01a582SDag-Erling Smørgrav SetAckModified(lnk);
3474741f3a1SPaolo Pisati tc = (struct tcphdr *)ip_next(pip);
3484741f3a1SPaolo Pisati delta = GetDeltaSeqOut(tc->th_seq, lnk);
3494741f3a1SPaolo Pisati AddSeq(lnk, delta + slen, pip->ip_hl, pip->ip_len, tc->th_seq,
3504741f3a1SPaolo Pisati tc->th_off);
3517d96f4efSBrian Somers }
3527d96f4efSBrian Somers
3537d96f4efSBrian Somers /* Update IP header packet length and checksum */
3547d96f4efSBrian Somers {
3557d96f4efSBrian Somers int accumulate;
3567d96f4efSBrian Somers
3577d96f4efSBrian Somers accumulate = pip->ip_len;
3587d96f4efSBrian Somers pip->ip_len = htons(ntohs(pip->ip_len) + slen);
3597d96f4efSBrian Somers accumulate -= pip->ip_len;
3607d96f4efSBrian Somers
3617d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
3627d96f4efSBrian Somers }
3637d96f4efSBrian Somers
3647d96f4efSBrian Somers /* Update TCP checksum, Use TcpChecksum since so many things have
3657d96f4efSBrian Somers already changed. */
3667d96f4efSBrian Somers
3677d96f4efSBrian Somers tc->th_sum = 0;
36859dde15eSGleb Smirnoff #ifdef _KERNEL
369*0fc7bdc9SRichard Scheffenegger tcp_set_flags(tc, tcp_get_flags(tc) | TH_RES1);
37059dde15eSGleb Smirnoff #else
3717d96f4efSBrian Somers tc->th_sum = TcpChecksum(pip);
37259dde15eSGleb Smirnoff #endif
3737d96f4efSBrian Somers }
3747d96f4efSBrian Somers
3757d96f4efSBrian Somers static void
ProxyEncodeIpHeader(struct ip * pip,int maxpacketsize)376effc8e57SLutz Donnerhacke ProxyEncodeIpHeader(struct ip *pip, int maxpacketsize)
3777d96f4efSBrian Somers {
3787d96f4efSBrian Somers #define OPTION_LEN_BYTES 8
3797d96f4efSBrian Somers #define OPTION_LEN_INT16 4
3807d96f4efSBrian Somers #define OPTION_LEN_INT32 2
381bc596e56SAlex Richardson _Alignas(_Alignof(u_short)) u_char option[OPTION_LEN_BYTES];
3827d96f4efSBrian Somers
3836293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
3847d96f4efSBrian Somers fprintf(stdout, " ip cksum 1 = %x\n", (u_int)IpChecksum(pip));
3857d96f4efSBrian Somers fprintf(stdout, "tcp cksum 1 = %x\n", (u_int)TcpChecksum(pip));
3864c32f5d2SBrian Somers #endif
3877d96f4efSBrian Somers
388ed01a582SDag-Erling Smørgrav (void)maxpacketsize;
389ed01a582SDag-Erling Smørgrav
3907d96f4efSBrian Somers /* Check to see that there is room to add an IP option */
3917d96f4efSBrian Somers if (pip->ip_hl > (0x0f - OPTION_LEN_INT32))
3927d96f4efSBrian Somers return;
3937d96f4efSBrian Somers
3947d96f4efSBrian Somers /* Build option and copy into packet */
3957d96f4efSBrian Somers {
3967d96f4efSBrian Somers u_char *ptr;
3977d96f4efSBrian Somers struct tcphdr *tc;
3987d96f4efSBrian Somers
3997d96f4efSBrian Somers ptr = (u_char *) pip;
4007d96f4efSBrian Somers ptr += 20;
4017d96f4efSBrian Somers memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20);
4027d96f4efSBrian Somers
4037d96f4efSBrian Somers option[0] = 0x64; /* class: 3 (reserved), option 4 */
4047d96f4efSBrian Somers option[1] = OPTION_LEN_BYTES;
4057d96f4efSBrian Somers
4067d96f4efSBrian Somers memcpy(&option[2], (u_char *)&pip->ip_dst, 4);
4077d96f4efSBrian Somers
4089fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip);
4097d96f4efSBrian Somers memcpy(&option[6], (u_char *)&tc->th_sport, 2);
4107d96f4efSBrian Somers
4117d96f4efSBrian Somers memcpy(ptr, option, 8);
4127d96f4efSBrian Somers }
4137d96f4efSBrian Somers
4147d96f4efSBrian Somers /* Update checksum, header length and packet length */
4157d96f4efSBrian Somers {
4167d96f4efSBrian Somers int i;
4177d96f4efSBrian Somers int accumulate;
4187d96f4efSBrian Somers u_short *sptr;
4197d96f4efSBrian Somers
4207d96f4efSBrian Somers sptr = (u_short *) option;
4217d96f4efSBrian Somers accumulate = 0;
4227d96f4efSBrian Somers for (i = 0; i < OPTION_LEN_INT16; i++)
4237d96f4efSBrian Somers accumulate -= *(sptr++);
4247d96f4efSBrian Somers
4257d96f4efSBrian Somers sptr = (u_short *) pip;
4267d96f4efSBrian Somers accumulate += *sptr;
4277d96f4efSBrian Somers pip->ip_hl += OPTION_LEN_INT32;
4287d96f4efSBrian Somers accumulate -= *sptr;
4297d96f4efSBrian Somers
4307d96f4efSBrian Somers accumulate += pip->ip_len;
4317d96f4efSBrian Somers pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES);
4327d96f4efSBrian Somers accumulate -= pip->ip_len;
4337d96f4efSBrian Somers
4347d96f4efSBrian Somers ADJUST_CHECKSUM(accumulate, pip->ip_sum);
4357d96f4efSBrian Somers }
4367d96f4efSBrian Somers #undef OPTION_LEN_BYTES
4377d96f4efSBrian Somers #undef OPTION_LEN_INT16
4387d96f4efSBrian Somers #undef OPTION_LEN_INT32
4396293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
4407d96f4efSBrian Somers fprintf(stdout, " ip cksum 2 = %x\n", (u_int)IpChecksum(pip));
4417d96f4efSBrian Somers fprintf(stdout, "tcp cksum 2 = %x\n", (u_int)TcpChecksum(pip));
4424c32f5d2SBrian Somers #endif
4437d96f4efSBrian Somers }
4447d96f4efSBrian Somers
4457d96f4efSBrian Somers /* Functions by other packet alias source files
4467d96f4efSBrian Somers
4477d96f4efSBrian Somers ProxyCheck() -- Checks whether an outgoing packet should
4487d96f4efSBrian Somers be proxied.
4497d96f4efSBrian Somers ProxyModify() -- Encodes the original destination address/port
4507d96f4efSBrian Somers for a packet which is to be redirected to
4517d96f4efSBrian Somers a proxy server.
4527d96f4efSBrian Somers */
4537d96f4efSBrian Somers
4547d96f4efSBrian Somers int
ProxyCheck(struct libalias * la,struct in_addr * proxy_server_addr,u_short * proxy_server_port,struct in_addr src_addr,struct in_addr dst_addr,u_short dst_port,u_char ip_p)4554741f3a1SPaolo Pisati ProxyCheck(struct libalias *la, struct in_addr *proxy_server_addr,
4564741f3a1SPaolo Pisati u_short * proxy_server_port, struct in_addr src_addr,
4574741f3a1SPaolo Pisati struct in_addr dst_addr, u_short dst_port, u_char ip_p)
4587d96f4efSBrian Somers {
4597d96f4efSBrian Somers struct proxy_entry *ptr;
4607d96f4efSBrian Somers
461ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
4627d96f4efSBrian Somers
4635e289f9eSPoul-Henning Kamp ptr = la->proxyList;
464f0f93429SDag-Erling Smørgrav while (ptr != NULL) {
4657d96f4efSBrian Somers u_short proxy_port;
4667d96f4efSBrian Somers
4677d96f4efSBrian Somers proxy_port = ptr->proxy_port;
4687d96f4efSBrian Somers if ((dst_port == proxy_port || proxy_port == 0)
4694741f3a1SPaolo Pisati && ip_p == ptr->proto
470f0f93429SDag-Erling Smørgrav && src_addr.s_addr != ptr->server_addr.s_addr) {
4717d96f4efSBrian Somers struct in_addr src_addr_masked;
4727d96f4efSBrian Somers struct in_addr dst_addr_masked;
4737d96f4efSBrian Somers
4747d96f4efSBrian Somers src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr;
4757d96f4efSBrian Somers dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr;
4767d96f4efSBrian Somers
4777d96f4efSBrian Somers if ((src_addr_masked.s_addr == ptr->src_addr.s_addr)
478f0f93429SDag-Erling Smørgrav && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr)) {
4797d96f4efSBrian Somers if ((*proxy_server_port = ptr->server_port) == 0)
4807d96f4efSBrian Somers *proxy_server_port = dst_port;
4817d96f4efSBrian Somers *proxy_server_addr = ptr->server_addr;
482ffcb611aSDag-Erling Smørgrav return (ptr->proxy_type);
4837d96f4efSBrian Somers }
4847d96f4efSBrian Somers }
4857d96f4efSBrian Somers ptr = ptr->next;
4867d96f4efSBrian Somers }
4877d96f4efSBrian Somers
488ffcb611aSDag-Erling Smørgrav return (0);
4897d96f4efSBrian Somers }
4907d96f4efSBrian Somers
4917d96f4efSBrian Somers void
ProxyModify(struct libalias * la,struct alias_link * lnk,struct ip * pip,int maxpacketsize,int proxy_type)492ed01a582SDag-Erling Smørgrav ProxyModify(struct libalias *la, struct alias_link *lnk,
4937d96f4efSBrian Somers struct ip *pip,
4947d96f4efSBrian Somers int maxpacketsize,
4957d96f4efSBrian Somers int proxy_type)
4967d96f4efSBrian Somers {
497ccd57eeaSPaolo Pisati LIBALIAS_LOCK_ASSERT(la);
498ed01a582SDag-Erling Smørgrav (void)la;
499ed01a582SDag-Erling Smørgrav
500f0f93429SDag-Erling Smørgrav switch (proxy_type) {
5017d96f4efSBrian Somers case PROXY_TYPE_ENCODE_IPHDR:
5027d96f4efSBrian Somers ProxyEncodeIpHeader(pip, maxpacketsize);
5037d96f4efSBrian Somers break;
5047d96f4efSBrian Somers
5057d96f4efSBrian Somers case PROXY_TYPE_ENCODE_TCPSTREAM:
506ed01a582SDag-Erling Smørgrav ProxyEncodeTcpStream(lnk, pip, maxpacketsize);
5077d96f4efSBrian Somers break;
5087d96f4efSBrian Somers }
5097d96f4efSBrian Somers }
5107d96f4efSBrian Somers
5117d96f4efSBrian Somers /*
5127d96f4efSBrian Somers Public API functions
5137d96f4efSBrian Somers */
5147d96f4efSBrian Somers
5157d96f4efSBrian Somers /*
5167d96f4efSBrian Somers * This function takes command strings of the form:
5177d96f4efSBrian Somers *
5187d96f4efSBrian Somers * server <addr>[:<port>]
5197d96f4efSBrian Somers * [port <port>]
5207d96f4efSBrian Somers * [rule n]
5217d96f4efSBrian Somers * [proto tcp|udp]
5227d96f4efSBrian Somers * [src <addr>[/n]]
5237d96f4efSBrian Somers * [dst <addr>[/n]]
5247d96f4efSBrian Somers * [type encode_tcp_stream|encode_ip_hdr|no_encode]
5257d96f4efSBrian Somers *
5267d96f4efSBrian Somers * delete <rule number>
5277d96f4efSBrian Somers *
5287d96f4efSBrian Somers * Subfields can be in arbitrary order. Port numbers and addresses
5297d96f4efSBrian Somers * must be in either numeric or symbolic form. An optional rule number
5307d96f4efSBrian Somers * is used to control the order in which rules are searched. If two
5317d96f4efSBrian Somers * rules have the same number, then search order cannot be guaranteed,
5327d96f4efSBrian Somers * and the rules should be disjoint. If no rule number is specified,
5337d96f4efSBrian Somers * then 0 is used, and group 0 rules are always checked before any
5347d96f4efSBrian Somers * others.
5357d96f4efSBrian Somers */
536effc8e57SLutz Donnerhacke int
LibAliasProxyRule(struct libalias * la,const char * cmd)537effc8e57SLutz Donnerhacke LibAliasProxyRule(struct libalias *la, const char *cmd)
538effc8e57SLutz Donnerhacke {
539ccd57eeaSPaolo Pisati int i, n, len, ret;
5407d96f4efSBrian Somers int cmd_len;
5417d96f4efSBrian Somers int token_count;
5427d96f4efSBrian Somers int state;
5437d96f4efSBrian Somers char *token;
5447d96f4efSBrian Somers char buffer[256];
5457d96f4efSBrian Somers char str_port[sizeof(buffer)];
5467d96f4efSBrian Somers char str_server_port[sizeof(buffer)];
547d9e630b5SAndrey A. Chernov char *res = buffer;
5487d96f4efSBrian Somers
5497d96f4efSBrian Somers int rule_index;
5507d96f4efSBrian Somers int proto;
5517d96f4efSBrian Somers int proxy_type;
5527d96f4efSBrian Somers int proxy_port;
5537d96f4efSBrian Somers int server_port;
5547d96f4efSBrian Somers struct in_addr server_addr;
5557d96f4efSBrian Somers struct in_addr src_addr, src_mask;
5567d96f4efSBrian Somers struct in_addr dst_addr, dst_mask;
5577d96f4efSBrian Somers struct proxy_entry *proxy_entry;
5587d96f4efSBrian Somers
559ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la);
560ccd57eeaSPaolo Pisati ret = 0;
561effc8e57SLutz Donnerhacke
5627d96f4efSBrian Somers /* Copy command line into a buffer */
5634834b77dSBrian Somers cmd += strspn(cmd, " \t");
5647d96f4efSBrian Somers cmd_len = strlen(cmd);
565ccd57eeaSPaolo Pisati if (cmd_len > (int)(sizeof(buffer) - 1)) {
566ccd57eeaSPaolo Pisati ret = -1;
567ccd57eeaSPaolo Pisati goto getout;
568ccd57eeaSPaolo Pisati }
5697d96f4efSBrian Somers strcpy(buffer, cmd);
5707d96f4efSBrian Somers
5717d96f4efSBrian Somers /* Convert to lower case */
5727d96f4efSBrian Somers len = strlen(buffer);
5737d96f4efSBrian Somers for (i = 0; i < len; i++)
574d9e630b5SAndrey A. Chernov buffer[i] = tolower((unsigned char)buffer[i]);
5757d96f4efSBrian Somers
5767d96f4efSBrian Somers /* Set default proxy type */
5777d96f4efSBrian Somers
5787d96f4efSBrian Somers /* Set up default values */
5797d96f4efSBrian Somers rule_index = 0;
5807d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_NONE;
5817d96f4efSBrian Somers proto = IPPROTO_TCP;
5827d96f4efSBrian Somers proxy_port = 0;
5837d96f4efSBrian Somers server_addr.s_addr = 0;
5847d96f4efSBrian Somers server_port = 0;
5857d96f4efSBrian Somers src_addr.s_addr = 0;
5867d96f4efSBrian Somers IpMask(0, &src_mask);
5877d96f4efSBrian Somers dst_addr.s_addr = 0;
5887d96f4efSBrian Somers IpMask(0, &dst_mask);
5897d96f4efSBrian Somers
5907d96f4efSBrian Somers str_port[0] = 0;
5917d96f4efSBrian Somers str_server_port[0] = 0;
5927d96f4efSBrian Somers
5937d96f4efSBrian Somers /* Parse command string with state machine */
5947d96f4efSBrian Somers #define STATE_READ_KEYWORD 0
5957d96f4efSBrian Somers #define STATE_READ_TYPE 1
5967d96f4efSBrian Somers #define STATE_READ_PORT 2
5977d96f4efSBrian Somers #define STATE_READ_SERVER 3
5987d96f4efSBrian Somers #define STATE_READ_RULE 4
5997d96f4efSBrian Somers #define STATE_READ_DELETE 5
6007d96f4efSBrian Somers #define STATE_READ_PROTO 6
6017d96f4efSBrian Somers #define STATE_READ_SRC 7
6027d96f4efSBrian Somers #define STATE_READ_DST 8
6037d96f4efSBrian Somers state = STATE_READ_KEYWORD;
604d9e630b5SAndrey A. Chernov token = strsep(&res, " \t");
6057d96f4efSBrian Somers token_count = 0;
606f0f93429SDag-Erling Smørgrav while (token != NULL) {
6077d96f4efSBrian Somers token_count++;
608f0f93429SDag-Erling Smørgrav switch (state) {
6097d96f4efSBrian Somers case STATE_READ_KEYWORD:
6107d96f4efSBrian Somers if (strcmp(token, "type") == 0)
6117d96f4efSBrian Somers state = STATE_READ_TYPE;
6127d96f4efSBrian Somers else if (strcmp(token, "port") == 0)
6137d96f4efSBrian Somers state = STATE_READ_PORT;
6147d96f4efSBrian Somers else if (strcmp(token, "server") == 0)
6157d96f4efSBrian Somers state = STATE_READ_SERVER;
6167d96f4efSBrian Somers else if (strcmp(token, "rule") == 0)
6177d96f4efSBrian Somers state = STATE_READ_RULE;
6187d96f4efSBrian Somers else if (strcmp(token, "delete") == 0)
6197d96f4efSBrian Somers state = STATE_READ_DELETE;
6207d96f4efSBrian Somers else if (strcmp(token, "proto") == 0)
6217d96f4efSBrian Somers state = STATE_READ_PROTO;
6227d96f4efSBrian Somers else if (strcmp(token, "src") == 0)
6237d96f4efSBrian Somers state = STATE_READ_SRC;
6247d96f4efSBrian Somers else if (strcmp(token, "dst") == 0)
6257d96f4efSBrian Somers state = STATE_READ_DST;
626ccd57eeaSPaolo Pisati else {
627ccd57eeaSPaolo Pisati ret = -1;
628ccd57eeaSPaolo Pisati goto getout;
629ccd57eeaSPaolo Pisati }
6307d96f4efSBrian Somers break;
6317d96f4efSBrian Somers
6327d96f4efSBrian Somers case STATE_READ_TYPE:
6337d96f4efSBrian Somers if (strcmp(token, "encode_ip_hdr") == 0)
6347d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_IPHDR;
6357d96f4efSBrian Somers else if (strcmp(token, "encode_tcp_stream") == 0)
6367d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_TCPSTREAM;
6377d96f4efSBrian Somers else if (strcmp(token, "no_encode") == 0)
6387d96f4efSBrian Somers proxy_type = PROXY_TYPE_ENCODE_NONE;
639ccd57eeaSPaolo Pisati else {
640ccd57eeaSPaolo Pisati ret = -1;
641ccd57eeaSPaolo Pisati goto getout;
642ccd57eeaSPaolo Pisati }
6437d96f4efSBrian Somers state = STATE_READ_KEYWORD;
6447d96f4efSBrian Somers break;
6457d96f4efSBrian Somers
6467d96f4efSBrian Somers case STATE_READ_PORT:
6477d96f4efSBrian Somers strcpy(str_port, token);
6487d96f4efSBrian Somers state = STATE_READ_KEYWORD;
6497d96f4efSBrian Somers break;
6507d96f4efSBrian Somers
651effc8e57SLutz Donnerhacke case STATE_READ_SERVER: {
6527d96f4efSBrian Somers int err;
6537d96f4efSBrian Somers char *p;
6547d96f4efSBrian Somers char s[sizeof(buffer)];
6557d96f4efSBrian Somers
6567d96f4efSBrian Somers p = token;
6577d96f4efSBrian Somers while (*p != ':' && *p != 0)
6587d96f4efSBrian Somers p++;
6597d96f4efSBrian Somers
660f0f93429SDag-Erling Smørgrav if (*p != ':') {
6617d96f4efSBrian Somers err = IpAddr(token, &server_addr);
662ccd57eeaSPaolo Pisati if (err) {
663ccd57eeaSPaolo Pisati ret = -1;
664ccd57eeaSPaolo Pisati goto getout;
665ccd57eeaSPaolo Pisati }
666f0f93429SDag-Erling Smørgrav } else {
6677d96f4efSBrian Somers *p = ' ';
6687d96f4efSBrian Somers
6697d96f4efSBrian Somers n = sscanf(token, "%s %s", s, str_server_port);
670ccd57eeaSPaolo Pisati if (n != 2) {
671ccd57eeaSPaolo Pisati ret = -1;
672ccd57eeaSPaolo Pisati goto getout;
673ccd57eeaSPaolo Pisati }
6747d96f4efSBrian Somers
6757d96f4efSBrian Somers err = IpAddr(s, &server_addr);
676ccd57eeaSPaolo Pisati if (err) {
677ccd57eeaSPaolo Pisati ret = -1;
678ccd57eeaSPaolo Pisati goto getout;
679ccd57eeaSPaolo Pisati }
6807d96f4efSBrian Somers }
681effc8e57SLutz Donnerhacke
6827d96f4efSBrian Somers state = STATE_READ_KEYWORD;
6837d96f4efSBrian Somers break;
684effc8e57SLutz Donnerhacke }
6857d96f4efSBrian Somers case STATE_READ_RULE:
6867d96f4efSBrian Somers n = sscanf(token, "%d", &rule_index);
687ccd57eeaSPaolo Pisati if (n != 1 || rule_index < 0) {
688ccd57eeaSPaolo Pisati ret = -1;
689ccd57eeaSPaolo Pisati goto getout;
690ccd57eeaSPaolo Pisati }
6917d96f4efSBrian Somers state = STATE_READ_KEYWORD;
6927d96f4efSBrian Somers break;
6937d96f4efSBrian Somers
694effc8e57SLutz Donnerhacke case STATE_READ_DELETE: {
6957d96f4efSBrian Somers int err;
6967d96f4efSBrian Somers int rule_to_delete;
6977d96f4efSBrian Somers
698ccd57eeaSPaolo Pisati if (token_count != 2) {
699ccd57eeaSPaolo Pisati ret = -1;
700ccd57eeaSPaolo Pisati goto getout;
701ccd57eeaSPaolo Pisati }
7027d96f4efSBrian Somers
7037d96f4efSBrian Somers n = sscanf(token, "%d", &rule_to_delete);
704ccd57eeaSPaolo Pisati if (n != 1) {
705ccd57eeaSPaolo Pisati ret = -1;
706ccd57eeaSPaolo Pisati goto getout;
707ccd57eeaSPaolo Pisati }
7085e289f9eSPoul-Henning Kamp err = RuleNumberDelete(la, rule_to_delete);
7097d96f4efSBrian Somers if (err)
710ccd57eeaSPaolo Pisati ret = -1;
711fdb727f4SConrad Meyer else
712ccd57eeaSPaolo Pisati ret = 0;
713ccd57eeaSPaolo Pisati goto getout;
7147d96f4efSBrian Somers }
7157d96f4efSBrian Somers
7167d96f4efSBrian Somers case STATE_READ_PROTO:
7177d96f4efSBrian Somers if (strcmp(token, "tcp") == 0)
7187d96f4efSBrian Somers proto = IPPROTO_TCP;
7197d96f4efSBrian Somers else if (strcmp(token, "udp") == 0)
7207d96f4efSBrian Somers proto = IPPROTO_UDP;
721ccd57eeaSPaolo Pisati else {
722ccd57eeaSPaolo Pisati ret = -1;
723ccd57eeaSPaolo Pisati goto getout;
724ccd57eeaSPaolo Pisati }
7257d96f4efSBrian Somers state = STATE_READ_KEYWORD;
7267d96f4efSBrian Somers break;
7277d96f4efSBrian Somers
7287d96f4efSBrian Somers case STATE_READ_SRC:
729effc8e57SLutz Donnerhacke case STATE_READ_DST: {
7307d96f4efSBrian Somers int err;
7317d96f4efSBrian Somers char *p;
7327d96f4efSBrian Somers struct in_addr mask;
7337d96f4efSBrian Somers struct in_addr addr;
7347d96f4efSBrian Somers
7357d96f4efSBrian Somers p = token;
7367d96f4efSBrian Somers while (*p != '/' && *p != 0)
7377d96f4efSBrian Somers p++;
7387d96f4efSBrian Somers
739f0f93429SDag-Erling Smørgrav if (*p != '/') {
7407d96f4efSBrian Somers IpMask(32, &mask);
7417d96f4efSBrian Somers err = IpAddr(token, &addr);
742ccd57eeaSPaolo Pisati if (err) {
743ccd57eeaSPaolo Pisati ret = -1;
744ccd57eeaSPaolo Pisati goto getout;
745ccd57eeaSPaolo Pisati }
746f0f93429SDag-Erling Smørgrav } else {
7477d96f4efSBrian Somers int nbits;
7487d96f4efSBrian Somers char s[sizeof(buffer)];
7497d96f4efSBrian Somers
7507d96f4efSBrian Somers *p = ' ';
7517d96f4efSBrian Somers n = sscanf(token, "%s %d", s, &nbits);
752ccd57eeaSPaolo Pisati if (n != 2) {
753ccd57eeaSPaolo Pisati ret = -1;
754ccd57eeaSPaolo Pisati goto getout;
755ccd57eeaSPaolo Pisati }
7567d96f4efSBrian Somers
7577d96f4efSBrian Somers err = IpAddr(s, &addr);
758ccd57eeaSPaolo Pisati if (err) {
759ccd57eeaSPaolo Pisati ret = -1;
760ccd57eeaSPaolo Pisati goto getout;
761ccd57eeaSPaolo Pisati }
7627d96f4efSBrian Somers
7637d96f4efSBrian Somers err = IpMask(nbits, &mask);
764ccd57eeaSPaolo Pisati if (err) {
765ccd57eeaSPaolo Pisati ret = -1;
766ccd57eeaSPaolo Pisati goto getout;
767ccd57eeaSPaolo Pisati }
7687d96f4efSBrian Somers }
7697d96f4efSBrian Somers
770f0f93429SDag-Erling Smørgrav if (state == STATE_READ_SRC) {
7717d96f4efSBrian Somers src_addr = addr;
7727d96f4efSBrian Somers src_mask = mask;
773f0f93429SDag-Erling Smørgrav } else {
7747d96f4efSBrian Somers dst_addr = addr;
7757d96f4efSBrian Somers dst_mask = mask;
7767d96f4efSBrian Somers }
777effc8e57SLutz Donnerhacke
7787d96f4efSBrian Somers state = STATE_READ_KEYWORD;
7797d96f4efSBrian Somers break;
780effc8e57SLutz Donnerhacke }
7817d96f4efSBrian Somers
7827d96f4efSBrian Somers default:
783ccd57eeaSPaolo Pisati ret = -1;
784ccd57eeaSPaolo Pisati goto getout;
7857d96f4efSBrian Somers break;
7867d96f4efSBrian Somers }
7877d96f4efSBrian Somers
788d9e630b5SAndrey A. Chernov do {
789d9e630b5SAndrey A. Chernov token = strsep(&res, " \t");
790d9e630b5SAndrey A. Chernov } while (token != NULL && !*token);
7917d96f4efSBrian Somers }
7927d96f4efSBrian Somers #undef STATE_READ_KEYWORD
7937d96f4efSBrian Somers #undef STATE_READ_TYPE
7947d96f4efSBrian Somers #undef STATE_READ_PORT
7957d96f4efSBrian Somers #undef STATE_READ_SERVER
7967d96f4efSBrian Somers #undef STATE_READ_RULE
7977d96f4efSBrian Somers #undef STATE_READ_DELETE
7987d96f4efSBrian Somers #undef STATE_READ_PROTO
7997d96f4efSBrian Somers #undef STATE_READ_SRC
8007d96f4efSBrian Somers #undef STATE_READ_DST
8017d96f4efSBrian Somers
802effc8e57SLutz Donnerhacke /* Convert port strings to numbers.
803effc8e57SLutz Donnerhacke This needs to be done after the string is parsed, because
804effc8e57SLutz Donnerhacke the prototype might not be designated before the ports
805effc8e57SLutz Donnerhacke (which might be symbolic entries in /etc/services) */
8067d96f4efSBrian Somers
807f0f93429SDag-Erling Smørgrav if (strlen(str_port) != 0) {
8087d96f4efSBrian Somers int err;
8097d96f4efSBrian Somers
8107d96f4efSBrian Somers err = IpPort(str_port, proto, &proxy_port);
811ccd57eeaSPaolo Pisati if (err) {
812ccd57eeaSPaolo Pisati ret = -1;
813ccd57eeaSPaolo Pisati goto getout;
814ccd57eeaSPaolo Pisati }
815f0f93429SDag-Erling Smørgrav } else {
8167d96f4efSBrian Somers proxy_port = 0;
8177d96f4efSBrian Somers }
8187d96f4efSBrian Somers
819f0f93429SDag-Erling Smørgrav if (strlen(str_server_port) != 0) {
8207d96f4efSBrian Somers int err;
8217d96f4efSBrian Somers
8227d96f4efSBrian Somers err = IpPort(str_server_port, proto, &server_port);
823ccd57eeaSPaolo Pisati if (err) {
824ccd57eeaSPaolo Pisati ret = -1;
825ccd57eeaSPaolo Pisati goto getout;
826ccd57eeaSPaolo Pisati }
827f0f93429SDag-Erling Smørgrav } else {
8287d96f4efSBrian Somers server_port = 0;
8297d96f4efSBrian Somers }
8307d96f4efSBrian Somers
8317d96f4efSBrian Somers /* Check that at least the server address has been defined */
832ccd57eeaSPaolo Pisati if (server_addr.s_addr == 0) {
833ccd57eeaSPaolo Pisati ret = -1;
834ccd57eeaSPaolo Pisati goto getout;
835ccd57eeaSPaolo Pisati }
8367d96f4efSBrian Somers
8377d96f4efSBrian Somers /* Add to linked list */
8387d96f4efSBrian Somers proxy_entry = malloc(sizeof(struct proxy_entry));
839ccd57eeaSPaolo Pisati if (proxy_entry == NULL) {
840ccd57eeaSPaolo Pisati ret = -1;
841ccd57eeaSPaolo Pisati goto getout;
842ccd57eeaSPaolo Pisati }
8437d96f4efSBrian Somers
8447d96f4efSBrian Somers proxy_entry->proxy_type = proxy_type;
8457d96f4efSBrian Somers proxy_entry->rule_index = rule_index;
8467d96f4efSBrian Somers proxy_entry->proto = proto;
8477d96f4efSBrian Somers proxy_entry->proxy_port = htons(proxy_port);
8487d96f4efSBrian Somers proxy_entry->server_port = htons(server_port);
8497d96f4efSBrian Somers proxy_entry->server_addr = server_addr;
8507d96f4efSBrian Somers proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr;
8517d96f4efSBrian Somers proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr;
8527d96f4efSBrian Somers proxy_entry->src_mask = src_mask;
8537d96f4efSBrian Somers proxy_entry->dst_mask = dst_mask;
8547d96f4efSBrian Somers
8555e289f9eSPoul-Henning Kamp RuleAdd(la, proxy_entry);
8567d96f4efSBrian Somers
857ccd57eeaSPaolo Pisati getout:
858ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la);
859ccd57eeaSPaolo Pisati return (ret);
8607d96f4efSBrian Somers }
861