source: rtems-libbsd/freebsd/sys/netinet/libalias/alias_proxy.c @ 0a57e1d

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 0a57e1d was 0a57e1d, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 08:35:05

Reduce divergence from FreeBSD sources

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