/* * Send auth failed message from server to client. */ void send_auth_failed(struct context *c, const char *client_reason) { struct gc_arena gc = gc_new(); static const char auth_failed[] = "AUTH_FAILED"; size_t len; schedule_exit(c, c->options.scheduled_exit_interval, SIGTERM); len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed); if (len > PUSH_BUNDLE_SIZE) { len = PUSH_BUNDLE_SIZE; } { struct buffer buf = alloc_buf_gc(len, &gc); buf_printf(&buf, auth_failed); if (client_reason) { buf_printf(&buf, ",%s", client_reason); } send_control_channel_string(c, BSTR(&buf), D_PUSH); } gc_free(&gc); }
bool send_push_reply (struct context *c) { struct gc_arena gc = gc_new (); struct buffer buf = alloc_buf_gc (MAX_PUSH_LIST_LEN + 256, &gc); bool ret = false; buf_printf (&buf, "PUSH_REPLY"); if (c->options.push_list && strlen (c->options.push_list->options)) buf_printf (&buf, ",%s", c->options.push_list->options); if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask) buf_printf (&buf, ",ifconfig %s %s", print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc), print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc)); if (strlen (BSTR (&buf)) < MAX_PUSH_LIST_LEN) ret = send_control_channel_string (c, BSTR (&buf), D_PUSH); else msg (M_WARN, "Maximum length of --push buffer (%d) has been exceeded", MAX_PUSH_LIST_LEN); gc_free (&gc); return ret; }
bool send_push_request(struct context *c) { const int max_push_requests = c->options.handshake_window / PUSH_REQUEST_INTERVAL; if (++c->c2.n_sent_push_requests <= max_push_requests) { return send_control_channel_string(c, "PUSH_REQUEST", D_PUSH); } else { msg(D_STREAM_ERRORS, "No reply from server after sending %d push requests", max_push_requests); c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */ c->sig->signal_text = "no-push-reply"; return false; } }
static bool send_push_options(struct context *c, struct buffer *buf, struct push_list *push_list, int safe_cap, bool *push_sent, bool *multi_push) { struct push_entry *e = push_list->head; while (e) { if (e->enable) { const int l = strlen(e->option); if (BLEN(buf) + l >= safe_cap) { buf_printf(buf, ",push-continuation 2"); { const bool status = send_control_channel_string(c, BSTR(buf), D_PUSH); if (!status) { return false; } *push_sent = true; *multi_push = true; buf_reset_len(buf); buf_printf(buf, "%s", push_reply_cmd); } } if (BLEN(buf) + l >= safe_cap) { msg(M_WARN, "--push option is too long"); return false; } buf_printf(buf, ",%s", e->option); } e = e->next; } return true; }
static bool send_push_reply(struct context *c, struct push_list *per_client_push_list) { struct gc_arena gc = gc_new(); struct buffer buf = alloc_buf_gc(PUSH_BUNDLE_SIZE, &gc); bool multi_push = false; const int extra = 84; /* extra space for possible trailing ifconfig and push-continuation */ const int safe_cap = BCAP(&buf) - extra; bool push_sent = false; buf_printf(&buf, "%s", push_reply_cmd); /* send options which are common to all clients */ if (!send_push_options(c, &buf, &c->options.push_list, safe_cap, &push_sent, &multi_push)) { goto fail; } /* send client-specific options */ if (!send_push_options(c, &buf, per_client_push_list, safe_cap, &push_sent, &multi_push)) { goto fail; } if (multi_push) { buf_printf(&buf, ",push-continuation 1"); } if (BLEN(&buf) > sizeof(push_reply_cmd)-1) { const bool status = send_control_channel_string(c, BSTR(&buf), D_PUSH); if (!status) { goto fail; } push_sent = true; } /* If nothing have been pushed, send an empty push, * as the client is expecting a response */ if (!push_sent) { bool status = false; buf_reset_len(&buf); buf_printf(&buf, "%s", push_reply_cmd); status = send_control_channel_string(c, BSTR(&buf), D_PUSH); if (!status) { goto fail; } } gc_free(&gc); return true; fail: gc_free(&gc); return false; }
/* * Send restart message from server to client. */ void send_restart(struct context *c, const char *kill_msg) { schedule_exit(c, c->options.scheduled_exit_interval, SIGTERM); send_control_channel_string(c, kill_msg ? kill_msg : "RESTART", D_PUSH); }
bool send_push_reply (struct context *c) { struct gc_arena gc = gc_new (); struct buffer buf = alloc_buf_gc (PUSH_BUNDLE_SIZE, &gc); struct push_entry *e = c->options.push_list.head; bool multi_push = false; static char cmd[] = "PUSH_REPLY"; const int extra = 84; /* extra space for possible trailing ifconfig and push-continuation */ const int safe_cap = BCAP (&buf) - extra; bool push_sent = false; msg( M_INFO, "send_push_reply(): safe_cap=%d", safe_cap ); buf_printf (&buf, "%s", cmd); if ( c->c2.push_ifconfig_ipv6_defined ) { /* IPv6 is put into buffer first, could be lengthy */ buf_printf( &buf, ",ifconfig-ipv6 %s/%d %s", print_in6_addr( c->c2.push_ifconfig_ipv6_local, 0, &gc), c->c2.push_ifconfig_ipv6_netbits, print_in6_addr( c->c2.push_ifconfig_ipv6_remote, 0, &gc) ); if (BLEN (&buf) >= safe_cap) { msg (M_WARN, "--push ifconfig-ipv6 option is too long"); goto fail; } } while (e) { if (e->enable) { const int l = strlen (e->option); if (BLEN (&buf) + l >= safe_cap) { buf_printf (&buf, ",push-continuation 2"); { const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH); if (!status) goto fail; push_sent = true; multi_push = true; buf_reset_len (&buf); buf_printf (&buf, "%s", cmd); } } if (BLEN (&buf) + l >= safe_cap) { msg (M_WARN, "--push option is too long"); goto fail; } buf_printf (&buf, ",%s", e->option); } e = e->next; } if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask) { in_addr_t ifconfig_local = c->c2.push_ifconfig_local; #ifdef ENABLE_CLIENT_NAT if (c->c2.push_ifconfig_local_alias) ifconfig_local = c->c2.push_ifconfig_local_alias; #endif buf_printf (&buf, ",ifconfig %s %s", print_in_addr_t (ifconfig_local, 0, &gc), print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc)); } if (multi_push) buf_printf (&buf, ",push-continuation 1"); if (BLEN (&buf) > sizeof(cmd)-1) { const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH); if (!status) goto fail; push_sent = true; } /* If nothing have been pushed, send an empty push, * as the client is expecting a response */ if (!push_sent) { bool status = false; buf_reset_len (&buf); buf_printf (&buf, "%s", cmd); status = send_control_channel_string (c, BSTR(&buf), D_PUSH); if (!status) goto fail; } gc_free (&gc); return true; fail: gc_free (&gc); return false; }
bool send_push_request (struct context *c) { return send_control_channel_string (c, "PUSH_REQUEST", D_PUSH); }
/* * Send auth failed message from server to client. */ void send_auth_failed (struct context *c) { schedule_exit (c, c->options.scheduled_exit_interval); send_control_channel_string (c, "AUTH_FAILED", D_PUSH); }