VirtualBox

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

Last change on this file since 21664 was 20958, checked in by vboxsync, 16 years ago

NAT: export of libalias

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

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