With this option, the server can remove individual options from the
set pushed to a client (call from --client-config-dir file, or from
--client-connect script or plugin). Options are removed at parse
time, so it is possible to do stuff like:
push-remove route-ipv6
push "route-ipv6 fd00::/8"
to first remove all IPv6 route options set so far, then add something
specific (what "push-reset" does to all the options).
Arguments to push-remove are strncmp()'ed to option string, so partial
matches like
push-remove "route-ipv6 2001:"
are possible ("remove all IPv6 routes starting with 2001:").
Implementation of remove_iroutes_from_push_route_list() had to be changed
slightly to stop it from re-enabling all disabled options again.
v2: documentation (Changes.rst, doc/openvpn.8)
remove surplus gc_arena
implement filtering of "ifconfig-ipv6"
v3: correct quoting in commit message
only handle a single argument per push-remove statement - if multiple
options are to be removed, just use multiple push-remove statements
Trac #29, #614
Signed-off-by: Gert Doering <gert@greenie.muc.de>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <
1463393584-8318-1-git-send-email-gert@greenie.muc.de>
URL: http://article.gmane.org/gmane.network.openvpn.devel/11665
Signed-off-by: Gert Doering <gert@greenie.muc.de>
New features
------------
+push-remove
+ new option to remove options on a per-client basis from the "push" list
+ (more fine-grained than "push-reset")
+
keying-material-exporter
Keying Material Exporter [RFC-5705] allow additional keying material to be
derived from existing TLS channel.
configuration file. This option will ignore
.B \-\-push
options at the global config file level.
+.\"*********************************************************
+.TP
+.B \-\-push\-remove opt
+selectively remove all
+.B \-\-push
+options matching "opt" from the option list for a client. "opt" is matched
+as a substring against the whole option string to-be-pushed to the client, so
+.B \-\-push\-remove route
+would remove all
+.B \-\-push route ...
+and
+.B \-\-push route-ipv6 ...
+statements, while
+.B \-\-push\-remove 'route-ipv6 2001:'
+would only remove IPv6 routes for 2001:... networks.
+
+.B \-\-push\-remove
+can only be used in a client-specific context, like in a
+.B \-\-client\-config\-dir
+file, or
+.B \-\-client\-connect
+script or plugin -- similar to
+.B \-\-push\-reset,
+just more selective.
+
+NOTE: to
+.I change
+an option,
+.B \-\-push\-remove
+can be used to first remove the old value, and then add a new
+.B \-\-push
+option with the new value.
+.\"*********************************************************
.TP
.B \-\-push\-peer\-info
Push additional information about the client to server. The additional information
The following
options are legal in a client-specific context:
-.B \-\-push, \-\-push\-reset, \-\-iroute, \-\-ifconfig\-push,
+.B \-\-push, \-\-push\-reset, \-\-push\-remove, \-\-iroute, \-\-ifconfig\-push,
and
.B \-\-config.
.\"*********************************************************
VERIFY_PERMISSION (OPT_P_INSTANCE);
push_reset (options);
}
+ else if (streq (p[0], "push-remove") && p[1] && !p[2])
+ {
+ VERIFY_PERMISSION (OPT_P_INSTANCE);
+ push_remove_option (options,p[1]);
+ }
else if (streq (p[0], "ifconfig-pool") && p[1] && p[2] && !p[4])
{
const int lev = M_WARN;
options->push_ifconfig_ipv6_local = local;
options->push_ifconfig_ipv6_netbits = netbits;
options->push_ifconfig_ipv6_remote = remote;
+ options->push_ifconfig_ipv6_blocked = false;
}
else if (streq (p[0], "disable") && !p[1])
{
struct in6_addr push_ifconfig_ipv6_local; /* IPv6 */
int push_ifconfig_ipv6_netbits; /* IPv6 */
struct in6_addr push_ifconfig_ipv6_remote; /* IPv6 */
+ bool push_ifconfig_ipv6_blocked; /* IPv6 */
bool enable_c2c;
bool duplicate_cn;
int cf_max;
buf_printf (&buf, "%s", cmd);
- if ( c->c2.push_ifconfig_ipv6_defined )
+ if ( c->c2.push_ifconfig_ipv6_defined &&
+ !c->options.push_ifconfig_ipv6_blocked )
{
/* IPv6 is put into buffer first, could be lengthy */
buf_printf( &buf, ",ifconfig-ipv6 %s/%d %s",
{
CLEAR (o->push_list);
}
+
+void
+push_remove_option (struct options *o, const char *p)
+{
+ msg( D_PUSH, "PUSH_REMOVE '%s'", p );
+
+ /* ifconfig-ipv6 is special, as not part of the push list */
+ if ( streq( p, "ifconfig-ipv6" ))
+ {
+ o->push_ifconfig_ipv6_blocked = true;
+ return;
+ }
+
+ if (o && o->push_list.head )
+ {
+ struct push_entry *e = o->push_list.head;
+
+ /* cycle through the push list */
+ while (e)
+ {
+ if ( e->enable &&
+ strncmp( e->option, p, strlen(p) ) == 0 )
+ {
+ msg (D_PUSH, "PUSH_REMOVE removing: '%s'", e->option);
+ e->enable = false;
+ }
+
+ e = e->next;
+ }
+ }
+}
#endif
#if P2MP_SERVER
/* parse the push item */
CLEAR (p);
- if (parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
+ if ( e->enable &&
+ parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
{
/* is the push item a route directive? */
if (p[0] && !strcmp (p[0], "route") && !p[3])
}
}
}
- }
- /* should we copy the push item? */
- e->enable = enable;
- if (!enable)
- msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option);
+ /* should we copy the push item? */
+ e->enable = enable;
+ if (!enable)
+ msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option);
+ }
e = e->next;
}
void push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc);
void push_reset (struct options *o);
+void push_remove_option (struct options *o, const char *p);
void remove_iroutes_from_push_route_list (struct options *o);