VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/libalias/alias_proxy.c@ 30528

最後變更 在這個檔案從30528是 24223,由 vboxsync 提交於 15 年 前

alias_proxy.c: warnings caused by the iprt/ctype.h change

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette