Browse code

Implemented multi-address DNS expansion on the network field of route commands.

When only a single IP address is desired from a multi-address DNS
expansion, use the first address rather than a random selection.

Version 2.1.1l


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6291 e7ae566f-a301-0410-adde-c780ea21d3b5

James Yonan authored on 2010/07/12 10:55:54
Showing 4 changed files
... ...
@@ -219,6 +219,7 @@ is_special_addr (const char *addr_str)
219 219
 
220 220
 static bool
221 221
 init_route (struct route *r,
222
+	    struct resolve_list *network_list,
222 223
 	    const struct route_option *ro,
223 224
 	    const struct route_special_addr *spec)
224 225
 {
... ...
@@ -237,14 +238,15 @@ init_route (struct route *r,
237 237
   
238 238
   if (!get_special_addr (spec, ro->network, &r->network, &status))
239 239
     {
240
-      r->network = getaddr (
241
-			    GETADDR_RESOLVE
242
-			    | GETADDR_HOST_ORDER
243
-			    | GETADDR_WARN_ON_SIGNAL,
244
-			    ro->network,
245
-			    0,
246
-			    &status,
247
-			    NULL);
240
+      r->network = getaddr_multi (
241
+				  GETADDR_RESOLVE
242
+				  | GETADDR_HOST_ORDER
243
+				  | GETADDR_WARN_ON_SIGNAL,
244
+				  ro->network,
245
+				  0,
246
+				  &status,
247
+				  NULL,
248
+				  network_list);
248 249
     }
249 250
 
250 251
   if (!status)
... ...
@@ -438,20 +440,45 @@ init_route_list (struct route_list *rl,
438 438
   else
439 439
     rl->spec.remote_endpoint_defined = false;
440 440
 
441
-  if (!(opt->n >= 0 && opt->n <= rl->capacity))
442
-    msg (M_FATAL, PACKAGE_NAME " ROUTE: (init) number of route options (%d) is greater than route list capacity (%d)", opt->n, rl->capacity);
443
-
444 441
   /* parse the routes from opt to rl */
445 442
   {
446 443
     int i, j = 0;
444
+    bool warned = false;
447 445
     for (i = 0; i < opt->n; ++i)
448 446
       {
449
-	if (!init_route (&rl->routes[j],
447
+	struct resolve_list netlist;
448
+	struct route r;
449
+	int k;
450
+
451
+	if (!init_route (&r,
452
+			 &netlist,
450 453
 			 &opt->routes[i],
451 454
 			 &rl->spec))
452 455
 	  ret = false;
453 456
 	else
454
-	  ++j;
457
+	  {
458
+	    if (!netlist.len)
459
+	      {
460
+		netlist.data[0] = r.network;
461
+		netlist.len = 1;
462
+	      }
463
+	    for (k = 0; k < netlist.len; ++k)
464
+	      {
465
+		if (j < rl->capacity)
466
+		  {
467
+		    r.network = netlist.data[k];
468
+		    rl->routes[j++] = r;
469
+		  }
470
+		else
471
+		  {
472
+		    if (!warned)
473
+		      {
474
+			msg (M_WARN, PACKAGE_NAME " ROUTE: routes dropped because number of expanded routes is greater than route list capacity (%d)", rl->capacity);
475
+			warned = true;
476
+		      }
477
+		  }
478
+	      }
479
+	  }
455 480
       }
456 481
     rl->n = j;
457 482
   }
... ...
@@ -89,12 +89,26 @@ getaddr (unsigned int flags,
89 89
 	 bool *succeeded,
90 90
 	 volatile int *signal_received)
91 91
 {
92
+  return getaddr_multi (flags, hostname, resolve_retry_seconds, succeeded, signal_received, NULL);
93
+}
94
+
95
+in_addr_t
96
+getaddr_multi (unsigned int flags,
97
+	 const char *hostname,
98
+	 int resolve_retry_seconds,
99
+	 bool *succeeded,
100
+	 volatile int *signal_received,
101
+	 struct resolve_list *reslist)
102
+{
92 103
   struct in_addr ia;
93 104
   int status;
94 105
   int sigrec = 0;
95 106
   int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
96 107
   struct gc_arena gc = gc_new ();
97 108
 
109
+  if (reslist)
110
+    reslist->len = 0;
111
+
98 112
   if (flags & GETADDR_RANDOMIZE)
99 113
     hostname = hostname_randomize(hostname, &gc);
100 114
 
... ...
@@ -212,12 +226,28 @@ getaddr (unsigned int flags,
212 212
 		++n;
213 213
 	      ASSERT (n >= 2);
214 214
 
215
-	      msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d addresses, choosing one by random",
215
+	      msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d addresses",
216 216
 		   hostname,
217 217
 		   n);
218 218
 
219 219
 	      /* choose address randomly, for basic load-balancing capability */
220
-	      ia.s_addr = *(in_addr_t *) (h->h_addr_list[get_random () % n]);
220
+	      /*ia.s_addr = *(in_addr_t *) (h->h_addr_list[get_random () % n]);*
221
+
222
+	      /* choose first address */
223
+	      ia.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
224
+
225
+	      if (reslist)
226
+		{
227
+		  int i;
228
+		  for (i = 0; i < n && i < SIZE(reslist->data); ++i)
229
+		    {
230
+		      in_addr_t a = *(in_addr_t *) (h->h_addr_list[i]);
231
+		      if (flags & GETADDR_HOST_ORDER)
232
+			a = ntohl(a);
233
+		      reslist->data[i] = a;
234
+		    }
235
+		  reslist->len = i;
236
+		}
221 237
 	    }
222 238
 	}
223 239
 
... ...
@@ -439,6 +439,11 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
439 439
  * DNS resolution
440 440
  */
441 441
 
442
+struct resolve_list {
443
+  int len;
444
+  in_addr_t data[16];
445
+};
446
+
442 447
 #define GETADDR_RESOLVE               (1<<0)
443 448
 #define GETADDR_FATAL                 (1<<1)
444 449
 #define GETADDR_HOST_ORDER            (1<<2)
... ...
@@ -456,6 +461,13 @@ in_addr_t getaddr (unsigned int flags,
456 456
 		   bool *succeeded,
457 457
 		   volatile int *signal_received);
458 458
 
459
+in_addr_t getaddr_multi (unsigned int flags,
460
+			 const char *hostname,
461
+			 int resolve_retry_seconds,
462
+			 bool *succeeded,
463
+			 volatile int *signal_received,
464
+			 struct resolve_list *reslist);
465
+
459 466
 /*
460 467
  * Transport protocol naming and other details.
461 468
  */
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1.1k])
2
+define(PRODUCT_VERSION,[2.1.1l])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])