Hello community,

here is the log from the commit of package openfortivpn for openSUSE:Factory 
checked in at 2020-09-14 12:32:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openfortivpn (Old)
 and      /work/SRC/openSUSE:Factory/.openfortivpn.new.4249 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openfortivpn"

Mon Sep 14 12:32:07 2020 rev:13 rq:834122 version:1.15.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/openfortivpn/openfortivpn.changes        
2020-06-30 21:56:14.114716170 +0200
+++ /work/SRC/openSUSE:Factory/.openfortivpn.new.4249/openfortivpn.changes      
2020-09-14 12:33:44.597305836 +0200
@@ -1,0 +2,13 @@
+Wed Sep  9 18:34:03 UTC 2020 - Martin Hauke <[email protected]>
+
+- Update to version 1.15.0
+  * fix issue sending pin codes
+  * add command line option to bind to specific interface
+  * use different hints for OTP and 2FA
+  * remove password from /proc/#/cmd
+  * extend OTP to allow FTM push
+  * add preliminary support for host checks
+  * don't accept route to the vpn gateway
+  * fix byte counter in pppd_write
+
+-------------------------------------------------------------------

Old:
----
  openfortivpn-1.14.1.tar.gz

New:
----
  openfortivpn-1.15.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ openfortivpn.spec ++++++
--- /var/tmp/diff_new_pack.wzpT0R/_old  2020-09-14 12:33:45.977306717 +0200
+++ /var/tmp/diff_new_pack.wzpT0R/_new  2020-09-14 12:33:45.981306719 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           openfortivpn
-Version:        1.14.1
+Version:        1.15.0
 Release:        0
 Summary:        Client for PPP+SSL VPN tunnel services
 License:        GPL-3.0-or-later

++++++ openfortivpn-1.14.1.tar.gz -> openfortivpn-1.15.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/CHANGELOG.md 
new/openfortivpn-1.15.0/CHANGELOG.md
--- old/openfortivpn-1.14.1/CHANGELOG.md        2020-05-21 07:52:53.000000000 
+0200
+++ new/openfortivpn-1.15.0/CHANGELOG.md        2020-09-09 09:50:49.000000000 
+0200
@@ -14,6 +14,17 @@
 This high level changelog is usually updated when a release is tagged.
 On the master branch there may be changes that are not (yet) described here.
 
+### 1.15.0
+
+* [-] fix issue sending pin codes
+* [+] add command line option to bind to specific interface
+* [+] use different hints for OTP and 2FA
+* [+] remove password from /proc/#/cmd
+* [+] extend OTP to allow FTM push
+* [+] add preliminary support for host checks
+* [-] don't accept route to the vpn gateway
+* [-] fix byte counter in pppd_write
+
 ### 1.14.1
 
 * [-] fix out of bounds array access
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/README.md 
new/openfortivpn-1.15.0/README.md
--- old/openfortivpn-1.14.1/README.md   2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/README.md   2020-09-09 09:50:49.000000000 +0200
@@ -71,7 +71,7 @@
 Multiple readers are currently not supported.
 
 Smartcard support has been tested with Yubikey under Linux, but other PIV 
enabled
-smartcards may work too. On Mac OS X Mojave it is known that the pkcs 
eingine-by-id is not found.
+smartcards may work too. On Mac OS X Mojave it is known that the pkcs 
engine-by-id is not found.
 
 
 
@@ -81,7 +81,7 @@
 
 ### Installing existing packages
 
-Some Linux distibutions provide `openfortivpn` packages:
+Some Linux distributions provide `openfortivpn` packages:
 * [Fedora / CentOS](https://apps.fedoraproject.org/packages/openfortivpn)
 * [openSUSE / SLE](https://software.opensuse.org/package/openfortivpn)
 * [Gentoo](https://packages.gentoo.org/packages/net-vpn/openfortivpn)
@@ -168,9 +168,9 @@
 * when setting IP routes through VPN (when the tunnel is up);
 * when adding nameservers to `/etc/resolv.conf` (when the tunnel is up).
 
-For these reasons, you may need to use `sudo openfortivpn`.
+For these reasons, you need to use `sudo openfortivpn`.
 If you need it to be usable by non-sudoer users, you might consider adding an
-entry in `/etc/sudoers`.
+entry in `/etc/sudoers` or a file under `/etc/sudoers.d`.
 
 For example:
 `visudo -f /etc/sudoers.d/openfortivpn`
@@ -179,6 +179,8 @@
 
 %adm       ALL = (ALL) OPENFORTIVPN
 ```
+Adapt the above example by changing the `openfortivpn` path or choosing
+a group different from `adm` - such as a dedicated `openfortivpn` group.
 
 **Warning**: Make sure only trusted users can run openfortivpn as root!
 As described in [#54](https://github.com/adrienverge/openfortivpn/issues/54),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/configure.ac 
new/openfortivpn-1.15.0/configure.ac
--- old/openfortivpn-1.14.1/configure.ac        2020-05-21 07:52:53.000000000 
+0200
+++ new/openfortivpn-1.15.0/configure.ac        2020-09-09 09:50:49.000000000 
+0200
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.63])
-AC_INIT([openfortivpn], [1.14.1])
+AC_INIT([openfortivpn], [1.15.0])
 AC_CONFIG_SRCDIR([src/main.c])
 AM_INIT_AUTOMAKE([foreign subdir-objects])
 
@@ -206,7 +206,6 @@
 strncpy \
 strsignal \
 strstr \
-strtok \
 strtok_r \
 strtol \
 strtoul \
@@ -245,6 +244,7 @@
 )
 AS_IF([test "x$with_rt_dst" = "x"], [
 AC_MSG_CHECKING(whether rtentry is available and has rt_dst)
+AC_LANG(C)
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -472,6 +472,23 @@
       [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
 AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
 
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <sys/types.h>
+#include <sys/socket.h>
+int main(int argc, char **argv){
+        int ret, handle;
+        handle = socket(AF_INET, SOCK_STREAM, 0);
+        ret = setsockopt(handle, SOL_SOCKET, SO_BINDTODEVICE,"lo",3);
+}
+])], [
+       AC_DEFINE(HAVE_SO_BINDTODEVICE, 1)
+       AC_MSG_NOTICE([HAVE_SO_BINDTODEVICE... 1])
+],[
+       AC_DEFINE(HAVE_SO_BINDTODEVICE, 0)
+       AC_MSG_NOTICE([HAVE_SO_BINDTODEVICE... 0])
+])
+
+
 # prepare to get rid of obsolete code (FortiOS 4)
 AC_ARG_ENABLE([obsolete],
        [AS_HELP_STRING([--disable-obsolete], [disable support for FortiOS 
4])],,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/doc/openfortivpn.1.in 
new/openfortivpn-1.15.0/doc/openfortivpn.1.in
--- old/openfortivpn-1.14.1/doc/openfortivpn.1.in       2020-05-21 
07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/doc/openfortivpn.1.in       2020-09-09 
09:50:49.000000000 +0200
@@ -11,7 +11,9 @@
 [\fB\-\-otp=\fI<otp>\fR]
 [\fB\-\-otp\-prompt=\fI<prompt>\fR]
 [\fB\-\-otp\-delay=\fI<delay>\fR]
+[\fB\-\-no\-ftm\-push\fR]
 [\fB\-\-realm=\fI<realm>\fR]
+[\fB\-\-ifname=\fI<interface>\fR]
 [\fB\-\-set\-routes=<bool>\fR]
 [\fB\-\-no\-routes\fR]
 [\fB\-\-set\-dns=<bool>\fR]
@@ -79,10 +81,19 @@
 The delay time must be specified in seconds, where 0 means
 no wait (this is the default).
 .TP
+\fB\-\-no\-ftm\-push\fR
+Do not use FTM push if the server provides the option.
+The server may be configured to allow two factor authentication through a
+push notification to the mobile application. If this option is provided,
+authentication based on OTP will be used instead.
+.TP
 \fB\-\-realm=\fI<realm>\fR
 Connect to the specified authentication realm. Defaults to empty, which
 is usually what you want.
 .TP
+\fB\-\-ifname=\fI<interface>\fR
+Bind the connection to the specified network interface.
+.TP
 \fB\-\-set\-routes=\fI<bool>\fR, \fB\-\-no-routes\fR
 Set if openfortivpn should try to configure IP routes through the VPN when
 tunnel is up. If used multiple times, the last one takes priority.
@@ -286,6 +297,10 @@
 .br
 # otp\-prompt = Please
 .br
+# This would disable FTM push notification support, and use OTP instead
+.br
+# no\-ftm\-push = 1
+.br
 # pinentry = pinentry program
 .br
 user\-cert = @SYSCONFDIR@/openfortivpn/user\-cert.pem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/config.c 
new/openfortivpn-1.15.0/src/config.c
--- old/openfortivpn-1.14.1/src/config.c        2020-05-21 07:52:53.000000000 
+0200
+++ new/openfortivpn-1.15.0/src/config.c        2020-09-09 09:50:49.000000000 
+0200
@@ -48,8 +48,10 @@
        .otp = {'\0'},
        .otp_prompt = NULL,
        .otp_delay = -1,
+       .no_ftm_push = -1,
        .pinentry = NULL,
        .realm = {'\0'},
+       .iface_name = {'\0'},
        .set_routes = -1,
        .set_dns = -1,
        .pppd_use_peerdns = -1,
@@ -77,7 +79,10 @@
        .min_tls = -1,
        .seclevel_1 = -1,
        .cert_whitelist = NULL,
-       .use_engine = -1
+       .use_engine = -1,
+       .user_agent = NULL,
+       .hostcheck = NULL,
+       .check_virtual_desktop = NULL,
 };
 
 /*
@@ -274,6 +279,15 @@
                                continue;
                        }
                        cfg->otp_delay = otp_delay;
+               } else if (strcmp(key, "no-ftm-push") == 0) {
+                       int no_ftm_push = strtob(val);
+
+                       if (no_ftm_push < 0) {
+                               log_warn("Bad no-ftm-push in config file: 
\"%s\".\n",
+                                        val);
+                               continue;
+                       }
+                       cfg->no_ftm_push = no_ftm_push;
                } else if (strcmp(key, "pinentry") == 0) {
                        free(cfg->pinentry);
                        cfg->pinentry = strdup(val);
@@ -426,6 +440,15 @@
                                continue;
                        }
                        cfg->seclevel_1 = seclevel_1;
+               } else if (strcmp(key, "user-agent") == 0) {
+                       free(cfg->user_agent);
+                       cfg->user_agent = strdup(val);
+               } else if (strcmp(key, "hostcheck") == 0) {
+                       free(cfg->hostcheck);
+                       cfg->hostcheck = strdup(val);
+               } else if (strcmp(key, "check-virtual-desktop") == 0) {
+                       free(cfg->check_virtual_desktop);
+                       cfg->check_virtual_desktop = strdup(val);
                } else {
                        log_warn("Bad key in config file: \"%s\".\n", key);
                        goto err_free;
@@ -484,12 +507,16 @@
                strcpy(dst->otp, src->otp);
        if (src->otp_delay != invalid_cfg.otp_delay)
                dst->otp_delay = src->otp_delay;
+       if (src->no_ftm_push != invalid_cfg.no_ftm_push)
+               dst->no_ftm_push = src->no_ftm_push;
        if (src->pinentry) {
                free(dst->pinentry);
                dst->pinentry = src->pinentry;
        }
        if (src->realm[0])
                strcpy(dst->realm, src->realm);
+       if (src->iface_name[0])
+               strcpy(dst->iface_name, src->iface_name);
        if (src->set_routes != invalid_cfg.set_routes)
                dst->set_routes = src->set_routes;
        if (src->set_dns != invalid_cfg.set_dns)
@@ -567,4 +594,10 @@
                }
                dst->cert_whitelist = src->cert_whitelist;
        }
+       if (src->user_agent != invalid_cfg.user_agent)
+               dst->user_agent = src->user_agent;
+       if (src->hostcheck != invalid_cfg.hostcheck)
+               dst->hostcheck = src->hostcheck;
+       if (src->check_virtual_desktop != invalid_cfg.check_virtual_desktop)
+               dst->check_virtual_desktop = src->check_virtual_desktop;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/config.h 
new/openfortivpn-1.15.0/src/config.h
--- old/openfortivpn-1.14.1/src/config.h        2020-05-21 07:52:53.000000000 
+0200
+++ new/openfortivpn-1.15.0/src/config.h        2020-09-09 09:50:49.000000000 
+0200
@@ -85,7 +85,9 @@
        char            otp[FIELD_SIZE + 1];
        char            *otp_prompt;
        unsigned int  otp_delay;
+       int         no_ftm_push;
        char            *pinentry;
+       char            iface_name[FIELD_SIZE + 1];
        char            realm[FIELD_SIZE + 1];
 
        int     set_routes;
@@ -118,6 +120,9 @@
        char                    *cipher_list;
        struct x509_digest      *cert_whitelist;
        int                     use_engine;
+       char                    *user_agent;
+       char                    *hostcheck;
+       char                    *check_virtual_desktop;
 };
 
 int add_trusted_cert(struct vpn_config *cfg, const char *digest);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/hdlc.c 
new/openfortivpn-1.15.0/src/hdlc.c
--- old/openfortivpn-1.14.1/src/hdlc.c  2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/src/hdlc.c  2020-09-09 09:50:49.000000000 +0200
@@ -132,7 +132,7 @@
        if (frmsize < 7)
                return ERR_HDLC_BUFFER_TOO_SMALL;
 
-       // In theory each frame begins with a Flag Sequence, but it is ommitted
+       // In theory each frame begins with a Flag Sequence, but it is omitted
        // if the previous frame ends with a Flag Sequence.
        if (need_flag_sequence)
                frame[written++] = 0x7e;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/http.c 
new/openfortivpn-1.15.0/src/http.c
--- old/openfortivpn-1.14.1/src/http.c  2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/src/http.c  2020-09-09 09:50:49.000000000 +0200
@@ -50,10 +50,10 @@
 static void url_encode(char *dest, const char *str)
 {
        while (*str != '\0') {
-               if (isalnum(*str) || *str == '-' || *str == '_'
-                   || *str == '.' || *str == '~')
+               if (isalnum(*str) || *str == '-' || *str == '_' ||
+                   *str == '.' || *str == '~') {
                        *dest++ = *str;
-               else {
+               } else {
                        static const char hex[] = "0123456789ABCDEF";
 
                        *dest++ = '%';
@@ -122,11 +122,8 @@
 }
 
 
-static const char *find_header(
-        const char *res,
-        const char *header,
-        uint32_t response_size
-)
+static const char *find_header(const char *res, const char *header,
+                               uint32_t response_size)
 {
        const char *line = res;
 
@@ -154,11 +151,8 @@
  * @return     1         in case of success
  *             < 0       in case of error
  */
-int http_receive(
-        struct tunnel *tunnel,
-        char **response,
-        uint32_t *response_size
-)
+int http_receive(struct tunnel *tunnel,
+                 char **response, uint32_t *response_size)
 {
        uint32_t capacity = HTTP_BUFFER_SIZE;
        char *buffer;
@@ -280,17 +274,20 @@
        int ret;
        const char *template = ("%s %s HTTP/1.1\r\n"
                                "Host: %s:%d\r\n"
-                               "User-Agent: Mozilla/5.0 SV1\r\n"
-                               "Accept: text/plain\r\n"
-                               "Accept-Encoding: identity\r\n"
+                               "User-Agent: %s\r\n"
+                               "Accept: */*\r\n"
+                               "Accept-Encoding: gzip, deflate, br\r\n"
+                               "Pragma: no-cache\r\n"
+                               "Cache-Control: no-store, no-cache, 
must-revalidate\r\n"
+                               "If-Modified-Since: Sat, 1 Jan 2000 00:00:00 
GMT\r\n"
                                "Content-Type: 
application/x-www-form-urlencoded\r\n"
                                "Cookie: %s\r\n"
                                "Content-Length: %d\r\n"
                                "\r\n%s");
 
        ret = http_send(tunnel, template, method, uri,
-                       tunnel->config->gateway_host,
-                       tunnel->config->gateway_port, tunnel->cookie,
+                       tunnel->config->gateway_host, 
tunnel->config->gateway_port,
+                       tunnel->config->user_agent, tunnel->cookie,
                        strlen(data), data);
        if (ret != 1)
                return ret;
@@ -375,12 +372,43 @@
        return ret;
 }
 
+static int get_action_url(const char *buf, const char *key,
+                          char *retbuf, size_t retbuflen)
+{
+
+       int ret = -1;
+       char *tokens;
+       size_t keylen = strlen(key);
+       char *saveptr = NULL;
+
+       tokens = strdup(buf);
+       if (tokens == NULL) {
+               ret = -3;
+               goto end;
+       }
+
+       for (const char *kv_pair = strtok_r(tokens, " \"\r\n", &saveptr);
+            kv_pair != NULL;
+            kv_pair = strtok_r(NULL, " \"\r\n", &saveptr)) {
+               if (strncmp(key, kv_pair, keylen) == 0) {
+                       const char *val = strtok_r(NULL, "\"\r\n", &saveptr);
+
+                       if (strlen(val) > retbuflen - 1) {  // value too long
+                               ret = -2;
+                       } else {
+                               strcpy(retbuf, val);
+                               ret = 1;
+                       }
+                       break;
+               }
+       }
+
+       free(tokens);
+end:
+       return ret;
+}
 
-static int get_auth_cookie(
-        struct tunnel *tunnel,
-        char *buf,
-        uint32_t buffer_size
-)
+static int get_auth_cookie(struct tunnel *tunnel, char *buf, uint32_t 
buffer_size)
 {
        int ret = 0;
        const char *line;
@@ -393,13 +421,21 @@
                        if (line[11] == ';' || line[11] == '\0') {
                                log_debug("Empty cookie.\n");
                        } else {
-                               char *end;
-
-                               end = strstr(line, "\r");
-                               end[0] = '\0';
-                               end = strstr(line, ";");
-                               if (end != NULL)
-                                       end[0] = '\0';
+                               char *end1;
+                               char *end2;
+                               char end1_save = '\0';
+                               char end2_save = '\0';
+
+                               end1 = strstr(line, "\r");
+                               if (end1 != NULL) {
+                                       end1_save = *end1;
+                                       end1[0] = '\0';
+                               }
+                               end2 = strstr(line, ";");
+                               if (end2 != NULL) {
+                                       end2_save = *end2;
+                                       end2[0] = '\0';
+                               }
                                log_debug("Cookie: %s\n", line);
                                strncpy(tunnel->cookie, line, COOKIE_SIZE);
                                tunnel->cookie[COOKIE_SIZE] = '\0';
@@ -409,6 +445,10 @@
                                } else {
                                        ret = 1; // success
                                }
+                               if (end1 != NULL)
+                                       end1[0] = end1_save;
+                               if (end2 != NULL)
+                                       end2[0] = end2_save;
                        }
                }
        }
@@ -425,12 +465,8 @@
 }
 
 
-static int try_otp_auth(
-        struct tunnel *tunnel,
-        const char *buffer,
-        char **res,
-        uint32_t *response_size
-)
+static int try_otp_auth(struct tunnel *tunnel, const char *buffer,
+                        char **res, uint32_t *response_size)
 {
        char data[256];
        char path[40];
@@ -597,7 +633,11 @@
        char reqid[32] = { '\0' };
        char polid[32] = { '\0' };
        char group[128] = { '\0' };
-       char data[1024], token[128], tokenresponse[256];
+       char portal[64] = { '\0' };
+       char magic[32] = {'\0' };
+       char peer[32]  = { '\0' };
+       char data[1152], token[128], tokenresponse[256], tokenparams[320];
+       char action_url[1024] = { '\0' };
        char *res = NULL;
        uint32_t response_size;
 
@@ -618,7 +658,7 @@
                } else {
                        url_encode(password, tunnel->config->password);
                        snprintf(data, sizeof(data),
-                                
"username=%s&credential=%s&realm=%s&ajax=1&redir=%%2Fremote%%2Findex&just_logged_in=1",
+                                "username=%s&credential=%s&realm=%s&ajax=1",
                                 username, password, realm);
                }
                ret = http_request(tunnel, "POST", "/remote/logincheck",
@@ -671,26 +711,46 @@
                get_value_from_response(res, "grp=", group, 128);
                get_value_from_response(res, "reqid=", reqid, 32);
                get_value_from_response(res, "polid=", polid, 32);
-
-               if (cfg->otp[0] == '\0') {
-                       read_password(cfg->pinentry, "otp",
-                                     "Two-factor authentication token: ",
-                                     cfg->otp, FIELD_SIZE);
+               get_value_from_response(res, "portal=", portal, 64);
+               get_value_from_response(res, "magic=", magic, 32);
+               get_value_from_response(res, "peer=", peer, 32);
+
+               if (cfg->otp[0] == '\0' &&
+                   strncmp(token, "ftm_push", 8) == 0 &&
+                   cfg->no_ftm_push == 0) {
+                       /*
+                        * The server supports FTM push if `tokeninfo` is 
`ftm_push`,
+                        * but only try this if the OTP is not provided by the 
config
+                        * file or command line.
+                        */
+                       snprintf(tokenparams, sizeof(tokenparams), "ftmpush=1");
+               } else {
                        if (cfg->otp[0] == '\0') {
-                               log_error("No token specified\n");
-                               return 0;
+                               // Prompt for 2FA token
+                               read_password(cfg->pinentry, "2fa",
+                                             "Two-factor authentication token: 
",
+                                             cfg->otp, FIELD_SIZE);
+
+                               if (cfg->otp[0] == '\0') {
+                                       log_error("No token specified\n");
+                                       return 0;
+                               }
                        }
+
+                       url_encode(tokenresponse, cfg->otp);
+                       snprintf(tokenparams, sizeof(tokenparams),
+                                "code=%s&code2=&magic=%s",
+                                tokenresponse, magic);
                }
 
-               url_encode(tokenresponse, cfg->otp);
                snprintf(data, sizeof(data),
-                        
"username=%s&realm=%s&reqid=%s&polid=%s&grp=%s&code=%s&code2=&redir=%%2Fremote%%2Findex&just_logged_in=1",
-                        username, realm, reqid, polid, group, tokenresponse);
+                        
"username=%s&realm=%s&reqid=%s&polid=%s&grp=%s&portal=%s&peer=%s&%s",
+                        username, realm, reqid, polid, group, portal, peer,
+                        tokenparams);
 
                delay_otp(tunnel);
-               ret = http_request(
-                             tunnel, "POST", "/remote/logincheck",
-                             data, &res, &response_size);
+               ret = http_request(tunnel, "POST", "/remote/logincheck",
+                                  data, &res, &response_size);
                if (ret != 1)
                        goto end;
 
@@ -705,6 +765,18 @@
                ret = get_auth_cookie(tunnel, res, response_size);
        }
 
+       /*
+        * If hostchecking enabled, get action url
+        */
+       get_action_url(res, "action=", action_url, 1024);
+       if (strlen(action_url) != 0) {
+               snprintf(data, sizeof(data), 
"hostcheck=%s&check_virtual_desktop=%s",
+                        tunnel->config->hostcheck,
+                        tunnel->config->check_virtual_desktop);
+               ret = http_request(tunnel, "POST", action_url,
+                                  data, &res, &response_size);
+       }
+
 end:
        free(res);
        return ret;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/io.c 
new/openfortivpn-1.15.0/src/io.c
--- old/openfortivpn-1.14.1/src/io.c    2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/src/io.c    2020-09-09 09:50:49.000000000 +0200
@@ -49,9 +49,9 @@
 
 #define SEM_INIT(sem, x, value)        semaphore_create(mach_task_self(), sem, 
\
                                                                
SYNC_POLICY_FIFO, value)
-#define SEM_WAIT(sem)                  semaphore_wait(*sem)
-#define SEM_POST(sem)                  semaphore_signal(*sem)
-#define SEM_DESTROY(sem)               semaphore_destroy(mach_task_self(), 
*sem)
+#define SEM_WAIT(sem)                  semaphore_wait(*(sem))
+#define SEM_POST(sem)                  semaphore_signal(*(sem))
+#define SEM_DESTROY(sem)               semaphore_destroy(mach_task_self(), 
*(sem))
 
 #else
 
@@ -74,14 +74,16 @@
 static void lock_callback(int mode, int type, const char *file, int line)
 {
        if (mode & CRYPTO_LOCK)
-               pthread_mutex_lock(&(lockarray[type]));
+               pthread_mutex_lock(&lockarray[type]);
        else
-               pthread_mutex_unlock(&(lockarray[type]));
+               pthread_mutex_unlock(&lockarray[type]);
 }
+
 static unsigned long thread_id(void)
 {
        return (unsigned long) pthread_self();
 }
+
 static void init_ssl_locks(void)
 {
        int i;
@@ -89,17 +91,18 @@
        lockarray = (pthread_mutex_t *) OPENSSL_malloc(CRYPTO_num_locks() *
                        sizeof(pthread_mutex_t));
        for (i = 0; i < CRYPTO_num_locks(); i++)
-               pthread_mutex_init(&(lockarray[i]), NULL);
+               pthread_mutex_init(&lockarray[i], NULL);
        CRYPTO_set_id_callback((unsigned long (*)()) thread_id);
        CRYPTO_set_locking_callback((void (*)()) lock_callback);
 }
+
 static void destroy_ssl_locks(void)
 {
        int i;
 
        CRYPTO_set_locking_callback(NULL);
        for (i = 0; i < CRYPTO_num_locks(); i++)
-               pthread_mutex_destroy(&(lockarray[i]));
+               pthread_mutex_destroy(&lockarray[i]);
        OPENSSL_free(lockarray);
 }
 #else
@@ -334,9 +337,13 @@
                        n = write(tunnel->pppd_pty, &hdlc_buffer[written],
                                  len - written);
                        // retry on repeatable failure
-                       if ((n == -1) && (errno != EAGAIN)) {
-                               log_error("write: %s\n", strerror(errno));
-                               goto err_free_buf;
+                       if (n == -1) {
+                               if (errno == EAGAIN) {
+                                       continue;
+                               } else {
+                                       log_error("write: %s\n", 
strerror(errno));
+                                       goto err_free_buf;
+                               }
                        }
                        written += n;
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/ipv4.c 
new/openfortivpn-1.15.0/src/ipv4.c
--- old/openfortivpn-1.14.1/src/ipv4.c  2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/src/ipv4.c  2020-09-09 09:50:49.000000000 +0200
@@ -220,7 +220,7 @@
        log_debug("netstat_path: %s\n", netstat_path);
 
        // Open the command for reading
-       fp = popen(NETSTAT_PATH" -f inet -rn", "r");
+       fp = popen(NETSTAT_PATH " -f inet -rn", "r");
        if (fp == NULL) {
                err = ERR_IPV4_SEE_ERRNO;
                goto end;
@@ -475,7 +475,6 @@
                               | ((mask & 0xff0000) >> 8)
                               | ((mask & 0xff00) << 8)
                               | ((mask & 0xff) << 24);
-
                }
                log_debug_details("- Destination IP Hex: %x\n", dest);
                log_debug_details("- Destination Mask Hex: %x\n", mask);
@@ -846,11 +845,9 @@
        if ((tunnel->ipv4.split_rt == NULL)
            || ((tunnel->ipv4.split_routes % STEP_SPLIT_ROUTES) == 0)) {
                void *new_ptr
-                       = realloc(
-                                 tunnel->ipv4.split_rt,
+                       = realloc(tunnel->ipv4.split_rt,
                                  (size_t) (tunnel->ipv4.split_routes + 
STEP_SPLIT_ROUTES)
-                                 * sizeof(*(tunnel->ipv4.split_rt))
-                         );
+                                 * sizeof(*(tunnel->ipv4.split_rt)));
                if (new_ptr == NULL)
                        return ERR_IPV4_NO_MEM;
                tunnel->ipv4.split_rt = new_ptr;
@@ -893,6 +890,13 @@
                int ret;
 
                route = &tunnel->ipv4.split_rt[i];
+               // check if the route to be added is not the one to the gateway 
itself
+               if (route_dest(route).s_addr == 
route_dest(&tunnel->ipv4.gtw_rt).s_addr) {
+                       log_debug("Skipping route to tunnel gateway (%s).\n",
+                                 ipv4_show_route(route));
+                       continue;
+               }
+
                free(route_iface(route));
                route_iface(route) = strdup(tunnel->ppp_iface);
                if (!route_iface(route))
@@ -1001,11 +1005,10 @@
        if (tunnel->ipv4.split_routes)
                // try even if ipv4_protect_tunnel_route has failed
                return ipv4_set_split_routes(tunnel);
-       else if (ret == 0) {
+       else if (ret == 0)
                return ipv4_set_default_routes(tunnel);
-       } else {
+       else
                return ret;
-       }
 }
 
 int ipv4_restore_routes(struct tunnel *tunnel)
@@ -1036,7 +1039,6 @@
                                log_warn("Could not restore default route (%s). 
Already restored?\n",
                                         err_ipv4_str(ret));
                        }
-
                }
        } else {
                log_debug("Route to vpn server was not added\n");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/log.c 
new/openfortivpn-1.15.0/src/log.c
--- old/openfortivpn-1.14.1/src/log.c   2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/src/log.c   2020-09-09 09:50:49.000000000 +0200
@@ -87,6 +87,7 @@
        if (loglevel < OFV_LOG_DEBUG_ALL)
                loglevel++;
 }
+
 void decrease_verbosity(void)
 {
        if (loglevel > OFV_LOG_MUTE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/main.c 
new/openfortivpn-1.15.0/src/main.c
--- old/openfortivpn-1.14.1/src/main.c  2020-05-21 07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/src/main.c  2020-09-09 09:50:49.000000000 +0200
@@ -51,16 +51,16 @@
 "                                resolver and routes directly.\n" \
 "  --pppd-ifname=<string>        Set the pppd interface name, if supported by 
pppd.\n" \
 "  --pppd-ipparam=<string>       Provides an extra parameter to the ip-up, 
ip-pre-up\n" \
-"                                and ip-down scripts. See man (8) pppd\n" \
+"                                and ip-down scripts. See man (8) pppd.\n" \
 "  --pppd-call=<name>            Move most pppd options from pppd cmdline 
to\n" \
 "                                /etc/ppp/peers/<name> and invoke pppd with\n" 
\
-"                                'call <name>'\n"
+"                                'call <name>'.\n"
 #elif HAVE_USR_SBIN_PPP
 #define PPPD_USAGE \
 "                    [--ppp-system=<system>]\n"
 #define PPPD_HELP \
 "  --ppp-system=<system>         Connect to the specified system as defined 
in\n" \
-"                                /etc/ppp/ppp.conf\n"
+"                                /etc/ppp/ppp.conf.\n"
 #else
 #error "Neither HAVE_USR_SBIN_PPPD nor HAVE_USR_SBIN_PPP have been defined."
 #endif
@@ -69,7 +69,7 @@
 #define RESOLVCONF_USAGE \
 "[--use-resolvconf=<0|1>] "
 #define RESOLVCONF_HELP \
-"  --use-resolvconf=[01]         If possible use resolvconf to update 
/etc/resolv.conf\n"
+"  --use-resolvconf=[01]         If possible use resolvconf to update 
/etc/resolv.conf.\n"
 #else
 #define RESOLVCONF_USAGE ""
 #define RESOLVCONF_HELP ""
@@ -77,14 +77,14 @@
 
 #define usage \
 "Usage: openfortivpn [<host>[:<port>]] [-u <user>] [-p <pass>]\n" \
-"                    [--pinentry=<program>]\n" \
-"                    [--realm=<realm>] [--otp=<otp>] [--otp-delay=<delay>]\n" \
-"                    [--otp-prompt=<prompt>] [--set-routes=<0|1>]\n" \
+"                    [--otp=<otp>] [--otp-delay=<delay>] 
[--otp-prompt=<prompt>]\n" \
+"                    [--pinentry=<program>] [--realm=<realm>]\n" \
+"                    [--ifname=<ifname>] [--set-routes=<0|1>]\n" \
 "                    [--half-internet-routes=<0|1>] [--set-dns=<0|1>]\n" \
 PPPD_USAGE \
 "                    " RESOLVCONF_USAGE "[--ca-file=<file>]\n" \
 "                    [--user-cert=<file>] [--user-key=<file>]\n" \
-"                    [--trusted-cert=<digest>] [--use-syslog]\n" \
+"                    [--use-syslog] [--trusted-cert=<digest>]\n" \
 "                    [--persistent=<interval>] [-c <file>] [-v|-q]\n" \
 "       openfortivpn --help\n" \
 "       openfortivpn --version\n" \
@@ -111,14 +111,16 @@
 "  -h --help                     Show this help message and exit.\n" \
 "  --version                     Show version and exit.\n" \
 "  -c <file>, --config=<file>    Specify a custom config file (default:\n" \
-"                                "SYSCONFDIR"/openfortivpn/config).\n" \
+"                                " SYSCONFDIR "/openfortivpn/config).\n" \
 "  -u <user>, --username=<user>  VPN account username.\n" \
 "  -p <pass>, --password=<pass>  VPN account password.\n" \
 "  -o <otp>, --otp=<otp>         One-Time-Password.\n" \
-"  --otp-prompt=<prompt>         Search for the OTP prompt starting with this 
string\n" \
+"  --otp-prompt=<prompt>         Search for the OTP prompt starting with this 
string.\n" \
 "  --otp-delay=<delay>           Wait <delay> seconds before sending the 
OTP.\n" \
-"  --pinentry=<program>          Use the program to supply a secret instead of 
asking for it\n" \
+"  --no-ftm-push                 Do not use FTM push if the server provides 
the option.\n" \
+"  --pinentry=<program>          Use the program to supply a secret instead of 
asking for it.\n" \
 "  --realm=<realm>               Use specified authentication realm.\n" \
+"  --ifname=<interface>          Bind to interface.\n" \
 "  --set-routes=[01]             Set if openfortivpn should configure 
routes\n" \
 "                                when tunnel is up.\n" \
 "  --no-routes                   Do not configure routes, same as 
--set-routes=0.\n" \
@@ -127,7 +129,7 @@
 "  --set-dns=[01]                Set if openfortivpn should add DNS name 
servers\n" \
 "                                and domain search list in 
/etc/resolv.conf.\n" \
 "                                If installed resolvconf is used for the 
update.\n" \
-"  --no-dns                      Do not reconfigure DNS, same as 
--set-dns=0\n" \
+"  --no-dns                      Do not reconfigure DNS, same as 
--set-dns=0.\n" \
 "  --ca-file=<file>              Use specified PEM-encoded certificate 
bundle\n" \
 "                                instead of system-wide store to verify the 
gateway\n" \
 "                                certificate.\n" \
@@ -170,7 +172,7 @@
 "Config file:\n" \
 "  Options can be taken from a configuration file. Options passed in the\n" \
 "  command line will override those from the config file, though. The 
default\n" \
-"  config file is "SYSCONFDIR"/openfortivpn/config,\n" \
+"  config file is " SYSCONFDIR "/openfortivpn/config,\n" \
 "  but this can be set using the -c option.\n" \
 "  A simple config file example looks like:\n" \
 "      # this is a comment\n" \
@@ -185,7 +187,7 @@
 int main(int argc, char **argv)
 {
        int ret = EXIT_FAILURE;
-       const char *config_file = SYSCONFDIR"/openfortivpn/config";
+       const char *config_file = SYSCONFDIR "/openfortivpn/config";
        const char *host;
        char *port_str;
 
@@ -197,8 +199,10 @@
                .otp = {'\0'},
                .otp_prompt = NULL,
                .otp_delay = 0,
+               .no_ftm_push = 0,
                .pinentry = NULL,
                .realm = {'\0'},
+               .iface_name = {'\0'},
                .set_routes = 1,
                .set_dns = 1,
                .use_syslog = 0,
@@ -230,7 +234,8 @@
                .seclevel_1 = 0,
                .cipher_list = NULL,
                .cert_whitelist = NULL,
-               .use_engine = 0
+               .use_engine = 0,
+               .user_agent = "Mozilla/5.0 SV1",
        };
        struct vpn_config cli_cfg = invalid_cfg;
 
@@ -245,6 +250,8 @@
                {"otp",             required_argument, NULL, 'o'},
                {"otp-prompt",      required_argument, NULL, 0},
                {"otp-delay",       required_argument, NULL, 0},
+               {"no-ftm-push",     no_argument, &cli_cfg.no_ftm_push, 1},
+               {"ifname",          required_argument, NULL, 0},
                {"set-routes",      required_argument, NULL, 0},
                {"no-routes",       no_argument, &cli_cfg.set_routes, 0},
                {"half-internet-routes", required_argument, NULL, 0},
@@ -427,6 +434,12 @@
                                break;
                        }
                        if (strcmp(long_options[option_index].name,
+                                  "ifname") == 0) {
+                               strncpy(cli_cfg.iface_name, optarg, FIELD_SIZE);
+                               cli_cfg.iface_name[FIELD_SIZE] = '\0';
+                               break;
+                       }
+                       if (strcmp(long_options[option_index].name,
                                   "set-routes") == 0) {
                                int set_routes = strtob(optarg);
 
@@ -507,6 +520,8 @@
                        break;
                case 'p':
                        cli_cfg.password = strdup(optarg);
+                       while (*optarg)
+                               *optarg++ = '*';  // nuke it
                        break;
                case 'o':
                        strncpy(cli_cfg.otp, optarg, FIELD_SIZE);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/tunnel.c 
new/openfortivpn-1.15.0/src/tunnel.c
--- old/openfortivpn-1.14.1/src/tunnel.c        2020-05-21 07:52:53.000000000 
+0200
+++ new/openfortivpn-1.15.0/src/tunnel.c        2020-09-09 09:50:49.000000000 
+0200
@@ -523,12 +523,46 @@
        int ret, handle;
        struct sockaddr_in server;
        char *env_proxy;
+       const int iface_len = strnlen(tunnel->config->iface_name, IFNAMSIZ);
 
        handle = socket(AF_INET, SOCK_STREAM, 0);
+
        if (handle == -1) {
                log_error("socket: %s\n", strerror(errno));
                goto err_socket;
        }
+       if (iface_len == IFNAMSIZ) {
+               log_error("socket: Too long iface name\n");
+               goto err_post_socket;
+       }
+       if (iface_len > 0) {
+#if HAVE_SO_BINDTODEVICE
+               ret = setsockopt(handle, SOL_SOCKET, SO_BINDTODEVICE,
+                                tunnel->config->iface_name, iface_len);
+#else
+               struct ifreq ifr;
+
+               memset(&ifr, 0, sizeof(ifr));
+               if (strlcpy(ifr.ifr_name, tunnel->config->iface_name, IFNAMSIZ)
+                   >= IFNAMSIZ) {
+                       log_error("interface name too long\n");
+                       goto err_post_socket;
+               }
+               ifr.ifr_addr.sa_family = AF_INET;
+               if (ioctl(handle, SIOCGIFADDR, &ifr) == -1) {
+                       log_error("ioctl(%d,SIOCGIFADDR,\"%s\") failed\n", 
handle,
+                                 ifr.ifr_name);
+                       goto err_post_socket;
+               }
+               ret = bind(handle, &ifr.ifr_addr, ifr.ifr_addr.sa_len);
+#endif
+               if (ret) {
+                       log_error("socket: setting interface name failed with 
error: %d\n",
+                                 errno);
+                       goto err_post_socket;
+               }
+       }
+
        env_proxy = getenv("https_proxy");
        if (env_proxy == NULL)
                env_proxy = getenv("HTTPS_PROXY");
@@ -678,7 +712,6 @@
                                        eol = strstr(response, HTTP_EOL[i]);
                                response = eol;
                        }
-
                }
 
                free(env_proxy); // release memory allocated by strdup()
@@ -690,6 +723,7 @@
 err_connect:
        free(env_proxy); // release memory allocated by strdup()
 err_strdup:
+err_post_socket:
        if (close(handle))
                log_warn("Could not close socket (%s).\n", strerror(errno));
 err_socket:
@@ -842,9 +876,8 @@
                log_error("Could not load OS OpenSSL files.\n");
 
        if (tunnel->config->ca_file) {
-               if (!SSL_CTX_load_verify_locations(
-                           tunnel->ssl_context,
-                           tunnel->config->ca_file, NULL)) {
+               if (!SSL_CTX_load_verify_locations(tunnel->ssl_context,
+                                                  tunnel->config->ca_file, 
NULL)) {
                        log_error("SSL_CTX_load_verify_locations: %s\n",
                                  ERR_error_string(ERR_peek_last_error(), 
NULL));
                        return 1;
@@ -919,7 +952,6 @@
 
        /* Use engine for PIV if user-cert config starts with pkcs11 URI: */
        if (tunnel->config->use_engine > 0) {
-
                ENGINE *e;
 
                ENGINE_load_builtin_engines();
@@ -991,9 +1023,9 @@
                }
 
                if (tunnel->config->user_key) {
-                       if (!SSL_CTX_use_PrivateKey_file(
-                                   tunnel->ssl_context, 
tunnel->config->user_key,
-                                   SSL_FILETYPE_PEM)) {
+                       if (!SSL_CTX_use_PrivateKey_file(tunnel->ssl_context,
+                                                        
tunnel->config->user_key,
+                                                        SSL_FILETYPE_PEM)) {
                                log_error("SSL_CTX_use_PrivateKey_file: %s\n",
                                          
ERR_error_string(ERR_peek_last_error(), NULL));
                                return 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/src/userinput.c 
new/openfortivpn-1.15.0/src/userinput.c
--- old/openfortivpn-1.14.1/src/userinput.c     2020-05-21 07:52:53.000000000 
+0200
+++ new/openfortivpn-1.15.0/src/userinput.c     2020-09-09 09:50:49.000000000 
+0200
@@ -97,7 +97,7 @@
 static int pinentry_read(int from, char **retstr)
 {
        int bufsiz = 0;
-       char *buf = NULL;
+       char *buf = NULL, *saveptr = NULL;
        int len = 0;
        int ret;
 
@@ -135,6 +135,7 @@
            || strncmp(buf, "D ", 2) == 0) {
                if (retstr) {
                        *retstr = strchr(buf, ' ');
+                       *retstr = *retstr ? strtok_r(*retstr, "\n", &saveptr) : 
NULL;
                        *retstr = *retstr ? uri_unescape(*retstr + 1) : NULL;
                }
                free(buf);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openfortivpn-1.14.1/tests/ci/checkpatch/checkpatch.pl 
new/openfortivpn-1.15.0/tests/ci/checkpatch/checkpatch.pl
--- old/openfortivpn-1.14.1/tests/ci/checkpatch/checkpatch.pl   2020-05-21 
07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/tests/ci/checkpatch/checkpatch.pl   2020-09-09 
09:50:49.000000000 +0200
@@ -51,7 +51,7 @@
 my @ignore = ();
 my $help = 0;
 my $configuration_file = ".checkpatch.conf";
-my $max_line_length = 80;
+my $max_line_length = 100;
 my $ignore_perl_version = 0;
 my $minimum_perl_version = 5.10.0;
 my $min_conf_desc_length = 4;
@@ -97,9 +97,11 @@
   --types TYPE(,TYPE2...)    show only these comma separated message types
   --ignore TYPE(,TYPE2...)   ignore various comma separated message types
   --show-types               show the specific message type in the output
-  --max-line-length=n        set the maximum line length, if exceeded, warn
+  --max-line-length=n        set the maximum line length, (default 
$max_line_length)
+                             if exceeded, warn on patches
+                             requires --strict for use with --file
   --min-conf-desc-length=n   set the min description length, if shorter, warn
-  --tab-size=n               set the number of spaces for tab (default 8)
+  --tab-size=n               set the number of spaces for tab (default 
$tabsize)
   --root=PATH                PATH to the kernel tree root
   --no-summary               suppress the per-file summary
   --mailback                 only produce a report in case of warnings/errors
@@ -244,6 +246,8 @@
 $fix = 1 if ($fix_inplace);
 $check_orig = $check;
 
+die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || 
$fix));
+
 my $exit = 0;
 
 my $perl_version_ok = 1;
@@ -267,11 +271,11 @@
 } elsif ($color =~ /^auto$/i) {
        $color = (-t STDOUT);
 } else {
-       die "Invalid color mode: $color\n";
+       die "$P: Invalid color mode: $color\n";
 }
 
 # skip TAB size 1 to avoid additional checks on $tabsize - 1
-die "Invalid TAB size: $tabsize\n" if ($tabsize < 2);
+die "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2);
 
 sub hash_save_array_words {
        my ($hashRef, $arrayRef) = @_;
@@ -1058,6 +1062,7 @@
        while (<$FILE>) {
                chomp;
                push(@rawlines, $_);
+               $vname = qq("$1") if ($filename eq '-' && $_ =~ 
m/^Subject:\s+(.+)/i);
        }
        close($FILE);
 
@@ -1674,8 +1679,16 @@
 sub ctx_locate_comment {
        my ($first_line, $end_line) = @_;
 
+       # If c99 comment on the current line, or the line before or after
+       my ($current_comment) = ($rawlines[$end_line - 1] =~ m@^\+.*(//.*$)@);
+       return $current_comment if (defined $current_comment);
+       ($current_comment) = ($rawlines[$end_line - 2] =~ m@^[\+ ].*(//.*$)@);
+       return $current_comment if (defined $current_comment);
+       ($current_comment) = ($rawlines[$end_line] =~ m@^[\+ ].*(//.*$)@);
+       return $current_comment if (defined $current_comment);
+
        # Catch a comment on the end of the line itself.
-       my ($current_comment) = ($rawlines[$end_line - 1] =~ 
m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
+       ($current_comment) = ($rawlines[$end_line - 1] =~ 
m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
        return $current_comment if (defined $current_comment);
 
        # Look through the context and try and figure out if there is a
@@ -2394,7 +2407,7 @@
 
                if ($rawline=~/^\+\+\+\s+(\S+)/) {
                        $setup_docs = 0;
-                       if ($1 =~ 
m@Documentation/admin-guide/kernel-parameters.rst$@) {
+                       if ($1 =~ 
m@Documentation/admin-guide/kernel-parameters.txt$@) {
                                $setup_docs = 1;
                        }
                        #next;
@@ -2594,7 +2607,7 @@
                                if (($last_binding_patch != -1) &&
                                    ($last_binding_patch ^ $is_binding_patch)) {
                                        WARN("DT_SPLIT_BINDING_PATCH",
-                                            "DT binding docs and includes 
should be a separate patch. See: 
Documentation/devicetree/bindings/submitting-patches.txt\n");
+                                            "DT binding docs and includes 
should be a separate patch. See: 
Documentation/devicetree/bindings/submitting-patches.rst\n");
                                }
                        }
 
@@ -3060,14 +3073,43 @@
                        #print "is_start<$is_start> is_end<$is_end> 
length<$length>\n";
                }
 
-# check for MAINTAINERS entries that don't have the right form
-               if ($realfile =~ /^MAINTAINERS$/ &&
-                   $rawline =~ /^\+[A-Z]:/ &&
-                   $rawline !~ /^\+[A-Z]:\t\S/) {
-                       if (WARN("MAINTAINERS_STYLE",
-                                "MAINTAINERS entries use one tab after 
TYPE:\n" . $herecurr) &&
-                           $fix) {
-                               $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
+# check MAINTAINERS entries
+               if ($realfile =~ /^MAINTAINERS$/) {
+# check MAINTAINERS entries for the right form
+                       if ($rawline =~ /^\+[A-Z]:/ &&
+                           $rawline !~ /^\+[A-Z]:\t\S/) {
+                               if (WARN("MAINTAINERS_STYLE",
+                                        "MAINTAINERS entries use one tab after 
TYPE:\n" . $herecurr) &&
+                                   $fix) {
+                                       $fixed[$fixlinenr] =~ 
s/^(\+[A-Z]):\s*/$1:\t/;
+                               }
+                       }
+# check MAINTAINERS entries for the right ordering too
+                       my $preferred_order = 'MRLSWQBCPTFXNK';
+                       if ($rawline =~ /^\+[A-Z]:/ &&
+                           $prevrawline =~ /^[\+ ][A-Z]:/) {
+                               $rawline =~ /^\+([A-Z]):\s*(.*)/;
+                               my $cur = $1;
+                               my $curval = $2;
+                               $prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/;
+                               my $prev = $1;
+                               my $prevval = $2;
+                               my $curindex = index($preferred_order, $cur);
+                               my $previndex = index($preferred_order, $prev);
+                               if ($curindex < 0) {
+                                       WARN("MAINTAINERS_STYLE",
+                                            "Unknown MAINTAINERS entry type: 
'$cur'\n" . $herecurr);
+                               } else {
+                                       if ($previndex >= 0 && $curindex < 
$previndex) {
+                                               WARN("MAINTAINERS_STYLE",
+                                                    "Misordered MAINTAINERS 
entry - list '$cur:' before '$prev:'\n" . $hereprev);
+                                       } elsif ((($prev eq 'F' && $cur eq 'F') 
||
+                                                 ($prev eq 'X' && $cur eq 
'X')) &&
+                                                ($prevval cmp $curval) > 0) {
+                                               WARN("MAINTAINERS_STYLE",
+                                                    "Misordered MAINTAINERS 
entry - list file patterns in alphabetic order\n" . $hereprev);
+                                       }
+                               }
                        }
                }
 
@@ -3240,8 +3282,10 @@
 
                        if ($msg_type ne "" &&
                            (show_type("LONG_LINE") || show_type($msg_type))) {
-                               WARN($msg_type,
-                                    "line over $max_line_length characters\n" 
. $herecurr);
+                               my $msg_level = \&WARN;
+                               $msg_level = \&CHK if ($file);
+                               &{$msg_level}($msg_type,
+                                             "line length of $length exceeds 
$max_line_length columns\n" . $herecurr);
                        }
                }
 
@@ -4199,6 +4243,17 @@
                             "ENOSYS means 'invalid syscall nr' and nothing 
else\n" . $herecurr);
                }
 
+# ENOTSUPP is not a standard error code and should be avoided in new patches.
+# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP.
+# Similarly to ENOSYS warning a small number of false positives is expected.
+               if (!$file && $line =~ /\bENOTSUPP\b/) {
+                       if (WARN("ENOTSUPP",
+                                "ENOTSUPP is not a SUSV4 error code, prefer 
EOPNOTSUPP\n" . $herecurr) &&
+                           $fix) {
+                               $fixed[$fixlinenr] =~ 
s/\bENOTSUPP\b/EOPNOTSUPP/;
+                       }
+               }
+
 # function brace can't be on same line, except for #defines of do while,
 # or if closed on same line
                if ($perl_version_ok &&
@@ -5890,6 +5945,14 @@
                        }
                }
 
+# check for data_race without a comment.
+               if ($line =~ /\bdata_race\s*\(/) {
+                       if (!ctx_has_comment($first_line, $linenr)) {
+                               WARN("DATA_RACE",
+                                    "data_race without comment\n" . $herecurr);
+                       }
+               }
+
 # check for smp_read_barrier_depends and read_barrier_depends
                if (!$file && $line =~ /\b(smp_|)read_barrier_depends\s*\(/) {
                        WARN("READ_BARRIER_DEPENDS",
@@ -6333,7 +6396,7 @@
 
                        if (!grep(/$name/, @setup_docs)) {
                                CHK("UNDOCUMENTED_SETUP",
-                                   "__setup appears un-documented -- check 
Documentation/admin-guide/kernel-parameters.rst\n" . $herecurr);
+                                   "__setup appears un-documented -- check 
Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);
                        }
                }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/tests/ci/checkpatch/spelling.txt 
new/openfortivpn-1.15.0/tests/ci/checkpatch/spelling.txt
--- old/openfortivpn-1.14.1/tests/ci/checkpatch/spelling.txt    2020-05-21 
07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/tests/ci/checkpatch/spelling.txt    2020-09-09 
09:50:49.000000000 +0200
@@ -59,6 +59,7 @@
 acumulating||accumulating
 acumulative||accumulative
 acumulator||accumulator
+acutally||actually
 adapater||adapter
 addional||additional
 additionaly||additionally
@@ -177,7 +178,9 @@
 atomicly||atomically
 atempt||attempt
 attachement||attachment
+attatch||attach
 attched||attached
+attemp||attempt
 attemps||attempts
 attemping||attempting
 attepmpt||attempt
@@ -235,16 +238,19 @@
 brigde||bridge
 broadcase||broadcast
 broadcat||broadcast
+bufer||buffer
 bufufer||buffer
 cacluated||calculated
 caculate||calculate
 caculation||calculation
 cadidate||candidate
+cahces||caches
 calender||calendar
 calescing||coalescing
 calle||called
 callibration||calibration
 callled||called
+callser||caller
 calucate||calculate
 calulate||calculate
 cancelation||cancellation
@@ -338,7 +344,6 @@
 condtion||condition
 conected||connected
 conector||connector
-connecetd||connected
 configration||configuration
 configuartion||configuration
 configuation||configuration
@@ -349,7 +354,9 @@
 configutation||configuration
 conider||consider
 conjuction||conjunction
+connecetd||connected
 connectinos||connections
+connetor||connector
 connnection||connection
 connnections||connections
 consistancy||consistency
@@ -469,6 +476,7 @@
 digial||digital
 dimention||dimension
 dimesions||dimensions
+disgest||digest
 dispalying||displaying
 diplay||display
 directon||direction
@@ -553,6 +561,7 @@
 etsbalishment||establishment
 excecutable||executable
 exceded||exceeded
+exceeed||exceed
 excellant||excellent
 execeeded||exceeded
 execeeds||exceeds
@@ -664,6 +673,7 @@
 hanled||handled
 happend||happened
 harware||hardware
+havind||having
 heirarchically||hierarchically
 helpfull||helpful
 hexdecimal||hexadecimal
@@ -742,6 +752,7 @@
 initilization||initialization
 initilize||initialize
 initliaze||initialize
+initilized||initialized
 inofficial||unofficial
 inrerface||interface
 insititute||institute
@@ -802,6 +813,7 @@
 isnt||isn't
 isssue||issue
 issus||issues
+iteraions||iterations
 iternations||iterations
 itertation||iteration
 itslef||itself
@@ -828,6 +840,7 @@
 librairies||libraries
 libraris||libraries
 licenceing||licencing
+limted||limited
 logaritmic||logarithmic
 loggging||logging
 loggin||login
@@ -835,6 +848,7 @@
 loobpack||loopback
 loosing||losing
 losted||lost
+maangement||management
 machinary||machinery
 maibox||mailbox
 maintainance||maintenance
@@ -895,6 +909,7 @@
 modulues||modules
 momery||memory
 memomry||memory
+monitring||monitoring
 monochorome||monochrome
 monochromo||monochrome
 monocrome||monochrome
@@ -924,6 +939,7 @@
 nescessary||necessary
 nessessary||necessary
 noticable||noticeable
+notication||notification
 notications||notifications
 notifcations||notifications
 notifed||notified
@@ -999,6 +1015,7 @@
 pased||passed
 passin||passing
 pathes||paths
+pattrns||patterns
 pecularities||peculiarities
 peformance||performance
 peforming||performing
@@ -1007,6 +1024,7 @@
 peprocessor||preprocessor
 perfoming||performing
 perfomring||performing
+periperal||peripheral
 peripherial||peripheral
 permissons||permissions
 peroid||period
@@ -1043,6 +1061,7 @@
 premption||preemption
 prepaired||prepared
 preperation||preparation
+preprare||prepare
 pressre||pressure
 primative||primitive
 princliple||principle
@@ -1064,6 +1083,7 @@
 processsing||processing
 procteted||protected
 prodecure||procedure
+progamming||programming
 progams||programs
 progess||progress
 programers||programmers
@@ -1151,12 +1171,14 @@
 reponse||response
 representaion||representation
 reqeust||request
+reqister||register
 requestied||requested
 requiere||require
 requirment||requirement
 requred||required
 requried||required
 requst||request
+requsted||requested
 reregisteration||reregistration
 reseting||resetting
 reseved||reserved
@@ -1227,10 +1249,12 @@
 seqeuencer||sequencer
 sequece||sequence
 sequencial||sequential
+serivce||service
 serveral||several
 servive||service
 setts||sets
 settting||setting
+shapshot||snapshot
 shotdown||shutdown
 shoud||should
 shouldnt||shouldn't
@@ -1238,6 +1262,7 @@
 shrinked||shrunk
 siginificantly||significantly
 signabl||signal
+significanly||significantly
 similary||similarly
 similiar||similar
 simlar||similar
@@ -1328,6 +1353,7 @@
 swithed||switched
 swithing||switching
 swtich||switch
+syfs||sysfs
 symetric||symmetric
 synax||syntax
 synchonized||synchronized
@@ -1352,6 +1378,7 @@
 therfore||therefore
 thier||their
 threds||threads
+threee||three
 threshhold||threshold
 thresold||threshold
 throught||through
@@ -1391,6 +1418,7 @@
 udpate||update
 uesd||used
 uknown||unknown
+usccess||success
 usupported||unsupported
 uncommited||uncommitted
 unconditionaly||unconditionally
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openfortivpn-1.14.1/tests/lint/checkpatch.sh 
new/openfortivpn-1.15.0/tests/lint/checkpatch.sh
--- old/openfortivpn-1.14.1/tests/lint/checkpatch.sh    2020-05-21 
07:52:53.000000000 +0200
+++ new/openfortivpn-1.15.0/tests/lint/checkpatch.sh    2020-09-09 
09:50:49.000000000 +0200
@@ -11,7 +11,6 @@
   tmp=$(mktemp)
 
   "$checkpatch_path" --no-tree --terse \
-    --max-line-length=90 \
     --ignore 
LEADING_SPACE,SPDX_LICENSE_TAG,CODE_INDENT,NAKED_SSCANF,VOLATILE,NEW_TYPEDEFS,LONG_LINE,LONG_LINE_STRING,QUOTED_WHITESPACE_BEFORE_NEWLINE
 \
     -f "$file" | tee "$tmp"
   


Reply via email to