You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
7.5 KiB

  1. --- a/doc/openfortivpn.1.in
  2. +++ b/doc/openfortivpn.1.in
  3. @@ -12,6 +12,7 @@ openfortivpn \- Client for PPP+SSL VPN t
  4. [\fB\-\-otp\-prompt=\fI<prompt>\fR]
  5. [\fB\-\-otp\-delay=\fI<delay>\fR]
  6. [\fB\-\-realm=\fI<realm>\fR]
  7. +[\fB\-\-ifname=\fI<interface>\fR]
  8. [\fB\-\-set\-routes=<bool>\fR]
  9. [\fB\-\-no\-routes\fR]
  10. [\fB\-\-set\-dns=<bool>\fR]
  11. @@ -83,6 +84,9 @@ no wait (this is the default).
  12. Connect to the specified authentication realm. Defaults to empty, which
  13. is usually what you want.
  14. .TP
  15. +\fB\-\-ifname=\fI<interface>\fR
  16. +Bind the connection to the specified network interface.
  17. +.TP
  18. \fB\-\-set\-routes=\fI<bool>\fR, \fB\-\-no-routes\fR
  19. Set if openfortivpn should try to configure IP routes through the VPN when
  20. tunnel is up. If used multiple times, the last one takes priority.
  21. --- a/src/config.c
  22. +++ b/src/config.c
  23. @@ -50,6 +50,7 @@ const struct vpn_config invalid_cfg = {
  24. .otp_delay = -1,
  25. .pinentry = NULL,
  26. .realm = {'\0'},
  27. + .iface_name = {'\0'},
  28. .set_routes = -1,
  29. .set_dns = -1,
  30. .pppd_use_peerdns = -1,
  31. @@ -490,6 +491,8 @@ void merge_config(struct vpn_config *dst
  32. }
  33. if (src->realm[0])
  34. strcpy(dst->realm, src->realm);
  35. + if (src->iface_name[0])
  36. + strcpy(dst->iface_name, src->iface_name);
  37. if (src->set_routes != invalid_cfg.set_routes)
  38. dst->set_routes = src->set_routes;
  39. if (src->set_dns != invalid_cfg.set_dns)
  40. --- a/src/config.h
  41. +++ b/src/config.h
  42. @@ -86,6 +86,7 @@ struct vpn_config {
  43. char *otp_prompt;
  44. unsigned int otp_delay;
  45. char *pinentry;
  46. + char iface_name[FIELD_SIZE + 1];
  47. char realm[FIELD_SIZE + 1];
  48. int set_routes;
  49. --- a/src/main.c
  50. +++ b/src/main.c
  51. @@ -51,16 +51,16 @@
  52. " resolver and routes directly.\n" \
  53. " --pppd-ifname=<string> Set the pppd interface name, if supported by pppd.\n" \
  54. " --pppd-ipparam=<string> Provides an extra parameter to the ip-up, ip-pre-up\n" \
  55. -" and ip-down scripts. See man (8) pppd\n" \
  56. +" and ip-down scripts. See man (8) pppd.\n" \
  57. " --pppd-call=<name> Move most pppd options from pppd cmdline to\n" \
  58. " /etc/ppp/peers/<name> and invoke pppd with\n" \
  59. -" 'call <name>'\n"
  60. +" 'call <name>'.\n"
  61. #elif HAVE_USR_SBIN_PPP
  62. #define PPPD_USAGE \
  63. " [--ppp-system=<system>]\n"
  64. #define PPPD_HELP \
  65. " --ppp-system=<system> Connect to the specified system as defined in\n" \
  66. -" /etc/ppp/ppp.conf\n"
  67. +" /etc/ppp/ppp.conf.\n"
  68. #else
  69. #error "Neither HAVE_USR_SBIN_PPPD nor HAVE_USR_SBIN_PPP have been defined."
  70. #endif
  71. @@ -69,7 +69,7 @@
  72. #define RESOLVCONF_USAGE \
  73. "[--use-resolvconf=<0|1>] "
  74. #define RESOLVCONF_HELP \
  75. -" --use-resolvconf=[01] If possible use resolvconf to update /etc/resolv.conf\n"
  76. +" --use-resolvconf=[01] If possible use resolvconf to update /etc/resolv.conf.\n"
  77. #else
  78. #define RESOLVCONF_USAGE ""
  79. #define RESOLVCONF_HELP ""
  80. @@ -77,14 +77,14 @@
  81. #define usage \
  82. "Usage: openfortivpn [<host>[:<port>]] [-u <user>] [-p <pass>]\n" \
  83. -" [--pinentry=<program>]\n" \
  84. -" [--realm=<realm>] [--otp=<otp>] [--otp-delay=<delay>]\n" \
  85. -" [--otp-prompt=<prompt>] [--set-routes=<0|1>]\n" \
  86. +" [--otp=<otp>] [--otp-delay=<delay>] [--otp-prompt=<prompt>]\n" \
  87. +" [--pinentry=<program>] [--realm=<realm>]\n" \
  88. +" [--ifname=<ifname>] [--set-routes=<0|1>]\n" \
  89. " [--half-internet-routes=<0|1>] [--set-dns=<0|1>]\n" \
  90. PPPD_USAGE \
  91. " " RESOLVCONF_USAGE "[--ca-file=<file>]\n" \
  92. " [--user-cert=<file>] [--user-key=<file>]\n" \
  93. -" [--trusted-cert=<digest>] [--use-syslog]\n" \
  94. +" [--use-syslog] [--trusted-cert=<digest>]\n" \
  95. " [--persistent=<interval>] [-c <file>] [-v|-q]\n" \
  96. " openfortivpn --help\n" \
  97. " openfortivpn --version\n" \
  98. @@ -115,10 +115,11 @@ PPPD_USAGE \
  99. " -u <user>, --username=<user> VPN account username.\n" \
  100. " -p <pass>, --password=<pass> VPN account password.\n" \
  101. " -o <otp>, --otp=<otp> One-Time-Password.\n" \
  102. -" --otp-prompt=<prompt> Search for the OTP prompt starting with this string\n" \
  103. +" --otp-prompt=<prompt> Search for the OTP prompt starting with this string.\n" \
  104. " --otp-delay=<delay> Wait <delay> seconds before sending the OTP.\n" \
  105. -" --pinentry=<program> Use the program to supply a secret instead of asking for it\n" \
  106. +" --pinentry=<program> Use the program to supply a secret instead of asking for it.\n" \
  107. " --realm=<realm> Use specified authentication realm.\n" \
  108. +" --ifname=<interface> Bind to interface.\n" \
  109. " --set-routes=[01] Set if openfortivpn should configure routes\n" \
  110. " when tunnel is up.\n" \
  111. " --no-routes Do not configure routes, same as --set-routes=0.\n" \
  112. @@ -127,7 +128,7 @@ PPPD_USAGE \
  113. " --set-dns=[01] Set if openfortivpn should add DNS name servers\n" \
  114. " and domain search list in /etc/resolv.conf.\n" \
  115. " If installed resolvconf is used for the update.\n" \
  116. -" --no-dns Do not reconfigure DNS, same as --set-dns=0\n" \
  117. +" --no-dns Do not reconfigure DNS, same as --set-dns=0.\n" \
  118. " --ca-file=<file> Use specified PEM-encoded certificate bundle\n" \
  119. " instead of system-wide store to verify the gateway\n" \
  120. " certificate.\n" \
  121. @@ -199,6 +200,7 @@ int main(int argc, char **argv)
  122. .otp_delay = 0,
  123. .pinentry = NULL,
  124. .realm = {'\0'},
  125. + .iface_name = {'\0'},
  126. .set_routes = 1,
  127. .set_dns = 1,
  128. .use_syslog = 0,
  129. @@ -245,6 +247,7 @@ int main(int argc, char **argv)
  130. {"otp", required_argument, NULL, 'o'},
  131. {"otp-prompt", required_argument, NULL, 0},
  132. {"otp-delay", required_argument, NULL, 0},
  133. + {"ifname", required_argument, NULL, 0},
  134. {"set-routes", required_argument, NULL, 0},
  135. {"no-routes", no_argument, &cli_cfg.set_routes, 0},
  136. {"half-internet-routes", required_argument, NULL, 0},
  137. @@ -427,6 +430,12 @@ int main(int argc, char **argv)
  138. break;
  139. }
  140. if (strcmp(long_options[option_index].name,
  141. + "ifname") == 0) {
  142. + strncpy(cli_cfg.iface_name, optarg, FIELD_SIZE);
  143. + cli_cfg.iface_name[FIELD_SIZE] = '\0';
  144. + break;
  145. + }
  146. + if (strcmp(long_options[option_index].name,
  147. "set-routes") == 0) {
  148. int set_routes = strtob(optarg);
  149. --- a/src/tunnel.c
  150. +++ b/src/tunnel.c
  151. @@ -523,12 +523,28 @@ static int tcp_connect(struct tunnel *tu
  152. int ret, handle;
  153. struct sockaddr_in server;
  154. char *env_proxy;
  155. + const int iface_len = strnlen(tunnel->config->iface_name, IFNAMSIZ);
  156. handle = socket(AF_INET, SOCK_STREAM, 0);
  157. +
  158. if (handle == -1) {
  159. log_error("socket: %s\n", strerror(errno));
  160. goto err_socket;
  161. }
  162. + if (iface_len == IFNAMSIZ) {
  163. + log_error("socket: Too long iface name");
  164. + goto err_socket;
  165. + }
  166. + if (iface_len > 0) {
  167. + ret = setsockopt(handle, SOL_SOCKET, SO_BINDTODEVICE,
  168. + tunnel->config->iface_name, iface_len);
  169. + if (ret) {
  170. + log_error("socket: setting interface name failed with error: %d",
  171. + errno);
  172. + goto err_socket;
  173. + }
  174. + }
  175. +
  176. env_proxy = getenv("https_proxy");
  177. if (env_proxy == NULL)
  178. env_proxy = getenv("HTTPS_PROXY");