VirtualBox

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

Last change on this file since 65455 was 63015, checked in by vboxsync, 8 years ago

slirp: warnings

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