| 
					
				 | 
			
			
				@@ -67,6 +67,8 @@ static int policies_parse_exit_policy_internal(config_line_t *cfg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                int ipv6_exit, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                int rejectprivate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                uint32_t local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                               tor_addr_t *ipv6_local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                               int reject_interface_addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                int add_default_policy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Replace all "private" entries in *<b>policy</b> with their expanded 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -152,7 +154,7 @@ policy_expand_unspec(smartlist_t **policy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Given a linked list of config lines containing "allow" and "deny" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Given a linked list of config lines containing "accept[6]" and "reject[6]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * tokens, parse them and append the result to <b>dest</b>. Return -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * if any tokens are malformed (and don't append any), else return 0. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -167,6 +169,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_t *result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_t *entries; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   addr_policy_t *item; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int malformed_list; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int r = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!cfg) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -179,12 +182,22 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     SMARTLIST_FOREACH_BEGIN(entries, const char *, ent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       log_debug(LD_CONFIG,"Adding new entry '%s'",ent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      item = router_parse_addr_policy_item_from_string(ent, assume_action); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      malformed_list = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      item = router_parse_addr_policy_item_from_string(ent, assume_action, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                       &malformed_list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (item) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         smartlist_add(result, item); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log_warn(LD_CONFIG,"Malformed policy '%s'.", ent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else if (malformed_list) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* the error is so severe the entire list should be discarded */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log_warn(LD_CONFIG, "Malformed policy '%s'. Discarding entire policy " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 "list.", ent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         r = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* the error is minor: don't add the item, but keep processing the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * rest of the policies in the list */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log_debug(LD_CONFIG, "Ignored policy '%s' due to non-fatal error. " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "The remainder of the policy list will be used.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  ent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } SMARTLIST_FOREACH_END(ent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     SMARTLIST_FOREACH(entries, char *, ent, tor_free(ent)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -430,7 +443,7 @@ validate_addr_policies(const or_options_t *options, char **msg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_t *addr_policy=NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   *msg = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (policies_parse_exit_policy_from_options(options,0,&addr_policy)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (policies_parse_exit_policy_from_options(options,0,NULL,0,&addr_policy)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     REJECT("Error in ExitPolicy entry."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -568,6 +581,8 @@ cmp_single_addr_policy(addr_policy_t *a, addr_policy_t *b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return r; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ((r=((int)a->is_private - (int)b->is_private))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return r; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* refcnt and is_canonical are irrelevant to equality, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * they are hash table implementation details */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ((r=tor_addr_compare(&a->addr, &b->addr, CMP_EXACT))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return r; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ((r=((int)a->maskbits - (int)b->maskbits))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -969,12 +984,24 @@ exit_policy_remove_redundancies(smartlist_t *dest) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "reject *:563,reject *:1214,reject *:4661-4666,"                  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "reject *:6346-6429,reject *:6699,reject *:6881-6999,accept *:*" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>. If 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * cfg doesn't end in an absolute accept or reject and if 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** Parse the exit policy <b>cfg</b> into the linked list *<b>dest</b>. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>ipv6_exit</b> is true, prepend "reject *6:*" to the policy. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>rejectprivate</b> is true: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - prepend "reject private:*" to the policy. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - if local_address is non-zero, treat it as a host-order IPv4 address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     and prepend an entry that rejects it as a destination. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - if ipv6_local_address is non-NULL, prepend an entry that rejects it as 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     a destination. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - if reject_interface_addresses is true, prepend entries that reject each 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     public IPv4 and IPv6 address of each interface on this machine. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If cfg doesn't end in an absolute accept or reject and if 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * <b>add_default_policy</b> is true, add the default exit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * policy afterwards. If <b>rejectprivate</b> is true, prepend 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * "reject private:*" to the policy. Return -1 if we can't parse cfg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * else return 0. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * policy afterwards. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Return -1 if we can't parse cfg, else return 0. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * This function is used to parse the exit policy from our torrc. For 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * the functions used to parse the exit policy from a router descriptor, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -985,21 +1012,142 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     int ipv6_exit, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     int rejectprivate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     uint32_t local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    tor_addr_t *ipv6_local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    int reject_interface_addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     int add_default_policy) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!ipv6_exit) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     append_exit_policy_string(dest, "reject *6:*"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (rejectprivate) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Reject IPv4 and IPv6 reserved private netblocks */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     append_exit_policy_string(dest, "reject private:*"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Reject our local IPv4 address */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (local_address) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       char buf[POLICY_BUF_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       tor_snprintf(buf, sizeof(buf), "reject %s:*", fmt_addr32(local_address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       append_exit_policy_string(dest, buf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for our published " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               "IPv4 address", buf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Reject our local IPv6 address */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (ipv6_exit && ipv6_local_address != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (tor_addr_is_v4(ipv6_local_address)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log_warn(LD_CONFIG, "IPv4 address '%s' provided as our IPv6 local " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 "address", fmt_addr(ipv6_local_address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        char buf6[POLICY_BUF_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tor_snprintf(buf6, sizeof(buf6), "reject %s:*", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     fmt_addr(ipv6_local_address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        append_exit_policy_string(dest, buf6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for our " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 "published IPv6 address", buf6); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Reject local addresses from public netblocks on any interface, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * but don't reject our published addresses twice */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (reject_interface_addresses) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      smartlist_t *public_addresses = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      char bufif[POLICY_BUF_LEN]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* Reject public IPv4 addresses on any interface, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * but don't reject our published IPv4 address twice */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      public_addresses = get_interface_address6_list(LOG_INFO, AF_INET, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      SMARTLIST_FOREACH_BEGIN(public_addresses, tor_addr_t *, a) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!tor_addr_eq_ipv4h(a, local_address)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          tor_snprintf(bufif, sizeof(bufif), "reject %s:*", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                       fmt_addr(a)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          append_exit_policy_string(dest, bufif); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for a local " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   "interface's public IPv4 address", bufif); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } SMARTLIST_FOREACH_END(a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      free_interface_address6_list(public_addresses); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (ipv6_exit) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* Reject public IPv6 addresses on any interface, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * but don't reject our published IPv6 address (if any) twice */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        public_addresses = get_interface_address6_list(LOG_INFO, AF_INET6, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        SMARTLIST_FOREACH_BEGIN(public_addresses, tor_addr_t *, a) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          /* if we don't have an IPv6 local address, we won't have rejected 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           * it above. This could happen if a future release does IPv6 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           * autodiscovery, and we are waiting to discover our external IPv6 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           * address */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (ipv6_local_address == NULL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              || !tor_addr_eq(ipv6_local_address, a)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tor_snprintf(bufif, sizeof(bufif), "reject6 %s:*", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                         fmt_addr(a)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            append_exit_policy_string(dest, bufif); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log_info(LD_CONFIG, "Adding a reject ExitPolicy '%s' for a local " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     "interface's public IPv6 address", bufif); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } SMARTLIST_FOREACH_END(a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        free_interface_address6_list(public_addresses); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (parse_addr_policy(cfg, dest, -1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Before we add the default policy and final rejects, check to see if 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * there are any lines after accept *:* or reject *:*. These lines have no 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * effect, and are most likely an error. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int found_final_effective_entry = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int first_redundant_entry = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (int i = 0; i < smartlist_len(*dest); ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sa_family_t family; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    addr_policy_t *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int found_ipv4_wildcard = 0, found_ipv6_wildcard = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p = smartlist_get(*dest, i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Look for accept/reject *[4|6|]:* entires */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (p->prt_min <= 1 && p->prt_max == 65535 && p->maskbits == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      family = tor_addr_family(&p->addr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* accept/reject *:* may have already been expanded into 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * accept/reject *4:*,accept/reject *6:* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * But handle both forms. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (family == AF_INET || family == AF_UNSPEC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        found_ipv4_wildcard = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (family == AF_INET6 || family == AF_UNSPEC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        found_ipv6_wildcard = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* We also find accept *4:*,reject *6:* ; and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * accept *4:*,<other policies>,accept *6:* ; and similar. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * That's ok, because they make any subsequent entries redundant. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (found_ipv4_wildcard && found_ipv6_wildcard) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      found_final_effective_entry = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* if we're not on the final entry in the list */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (i < smartlist_len(*dest) - 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        first_redundant_entry = i + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Work out if there are redundant trailing entries in the policy list */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (found_final_effective_entry && first_redundant_entry > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    addr_policy_t *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Longest possible policy is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * "accept6 ffff:ffff:..255/128:10000-65535", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * which contains a max-length IPv6 address, plus 24 characters. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    char line[TOR_ADDR_BUF_LEN + 32]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tor_assert(first_redundant_entry < smartlist_len(*dest)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p = smartlist_get(*dest, first_redundant_entry); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* since we've already parsed the policy into an addr_policy_t struct, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * we might not log exactly what the user typed in */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    policy_write_item(line, TOR_ADDR_BUF_LEN + 32, p, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    log_warn(LD_DIR, "Exit policy '%s' and all following policies are " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "redundant, as it follows accept/reject *:* rules for both " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "IPv4 and IPv6. They will be removed from the exit policy. (Use " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             "accept/reject *:* as the last entry in any exit policy.)", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (add_default_policy) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     append_exit_policy_string(dest, DEFAULT_EXIT_POLICY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1013,20 +1161,28 @@ policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Parse exit policy in <b>cfg</b> into <b>dest</b> smartlist. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Add entry that rejects all IPv6 destinations unless 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Prepend an entry that rejects all IPv6 destinations unless 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * <b>EXIT_POLICY_IPV6_ENABLED</b> bit is set in <b>options</b> bitmask. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * do add entry that rejects all destinations in private subnetwork 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Tor is running in. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - prepend an entry that rejects all destinations in all netblocks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     reserved for private use. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - if local_address is non-zero, treat it as a host-order IPv4 address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     and prepend an entry that rejects it as a destination. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - if ipv6_local_address is non-NULL, prepend an entry that rejects it as 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     a destination. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   - if reject_interface_addresses is true, prepend entries that reject each 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     public IPv4 and IPv6 address of each interface on this machine. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Respectively, if <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set, add 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set in <b>options</b>, append 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * default exit policy entries to <b>result</b> smartlist. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                            exit_policy_parser_cfg_t options, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           uint32_t local_address) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           uint32_t local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           tor_addr_t *ipv6_local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           int reject_interface_addresses) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1035,19 +1191,27 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                              reject_private, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                              local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                             ipv6_local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                             reject_interface_addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                              add_default); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Parse <b>ExitPolicy</b> member of <b>or_options</b> into <b>result</b> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * smartlist. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * If <b>or_options->IPv6Exit</b> is false, add an entry that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>or_options->IPv6Exit</b> is false, prepend an entry that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * rejects all IPv6 destinations. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * If <b>or_options->ExitPolicyRejectPrivate</b> is true, add entry that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * rejects all destinations in the private subnetwork of machine Tor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * instance is running in. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>or_options->ExitPolicyRejectPrivate</b> is true: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  - prepend an entry that rejects all destinations in all netblocks reserved 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *    for private use. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  - if local_address is non-zero, treat it as a host-order IPv4 address, and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *    prepend an entry that rejects it as a destination. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  - if ipv6_local_address is non-NULL, prepend an entry that rejects it as a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *    destination. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  - if reject_interface_addresses is true, prepend entries that reject each 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *    public IPv4 and IPv6 address of each interface on this machine. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * If <b>or_options->BridgeRelay</b> is false, add entries of default 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * If <b>or_options->BridgeRelay</b> is false, append entries of default 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * Tor exit policy into <b>result</b> smartlist. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * If or_options->ExitRelay is false, then make our exit policy into 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1056,6 +1220,8 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 policies_parse_exit_policy_from_options(const or_options_t *or_options, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                         uint32_t local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        tor_addr_t *ipv6_local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        int reject_interface_addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                         smartlist_t **result) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   exit_policy_parser_cfg_t parser_cfg = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1079,7 +1245,9 @@ policies_parse_exit_policy_from_options(const or_options_t *or_options, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return policies_parse_exit_policy(or_options->ExitPolicy,result, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    parser_cfg,local_address); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    parser_cfg,local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    ipv6_local_address, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    reject_interface_addresses); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating 
			 |