The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/libalias/alias_proxy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 4d8e24014c1938601638a9782a7f9a2e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.