+static void process_msg(char *line)
+{
+ DBG("Parse: <%s>", line);
+
+ char *p = line;
+ int c;
+ // 2016-11-04T17:18:54.825821+01:00 sshd[6733]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=1.2.3.4
+ // 2016-11-05T12:49:52.418880+01:00 sshd[16271]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.26 user=root
+
+ // We shall start with 32 non-spaces
+ for (int i=0; i<32; i++)
+ {
+ c = *p++;
+ if (!c || c == ' ')
+ return;
+ }
+ DBG("Parse 1: <%s>", p);
+
+ // Space, something, colon, space
+ if (*p++ != ' ')
+ return;
+ while (*p && *p != ' ' && *p != ':')
+ p++;
+ if (!check_next(&p, ": "))
+ return;
+ DBG("Parse 2: <%s>", p);
+
+ // pam_unix(something), colon, space
+ if (check_next(&p, "pam_unix("))
+ {
+ do
+ {
+ c = *p++;
+ if (!c || c == ' ')
+ return;
+ }
+ while (c != ')');
+ if (!check_next(&p, ": "))
+ return;
+ DBG("Parse 3: <%s>", p);
+
+ if (!check_next(&p, "authentication failure; "))
+ return;
+
+ parse_failure(p, 1);
+ }
+
+ // "PAM <n> more authentication failures;"
+ if (check_next(&p, "PAM "))
+ {
+ if (!(*p >= '0' && *p <= '9'))
+ return;
+ int cnt = atoi(p);
+ while (*p >= '0' && *p <= '9')
+ p++;
+
+ if (!check_next(&p, " more authentication failures; "))
+ return;
+
+ parse_failure(p, cnt);
+ }
+}
+