about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-11-06 12:31:27 +0000
committerLaurent Bercot <ska@appnovation.com>2023-11-06 12:31:27 +0000
commit7a126c7e024f935e3f6a7f3aa5ee49af6014514a (patch)
tree1870f94987eaea4088afc081e88b6f55300cee33
parent4d5a82771aa57829e269d69b1801cb7390cc1219 (diff)
downloadsmtpd-starttls-proxy-7a126c7e024f935e3f6a7f3aa5ee49af6014514a.tar.gz
smtpd-starttls-proxy-7a126c7e024f935e3f6a7f3aa5ee49af6014514a.tar.xz
smtpd-starttls-proxy-7a126c7e024f935e3f6a7f3aa5ee49af6014514a.zip
Switch command lookup table to bsearch
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--src/smtpd-starttls-proxy/smtpd-starttls-proxy-io.c81
1 files changed, 41 insertions, 40 deletions
diff --git a/src/smtpd-starttls-proxy/smtpd-starttls-proxy-io.c b/src/smtpd-starttls-proxy/smtpd-starttls-proxy-io.c
index 6464694..506d24c 100644
--- a/src/smtpd-starttls-proxy/smtpd-starttls-proxy-io.c
+++ b/src/smtpd-starttls-proxy/smtpd-starttls-proxy-io.c
@@ -30,9 +30,7 @@
 
 #define reset_timeout() tain_addsec_g(&deadline, 300)
 
-static int fdctl ;
-static int sslfds[2] ;
-static int wantexec = 0 ;
+#define MAXCBQ 16
 
 typedef struct io_s io_t, *io_t_ref ;
 struct io_s {
@@ -44,16 +42,27 @@ struct io_s {
   char outbuf[OUTSIZE] ;
 } ;
 
-static io_t io[2] =
+typedef int cmdfunc (char const *) ;
+typedef cmdfunc *cmdfunc_ref ;
+
+struct cmdmap_s
 {
-  { .in = BUFFER_INIT(&buffer_read, 0, io[0].inbuf, INSIZE), .out = BUFFER_INIT(&buffer_write, 1, io[0].outbuf, OUTSIZE), .w = 0 },
-  { .w = 0 }
+  char const *name ;
+  cmdfunc_ref f ;
 } ;
 
 typedef int cbfunc (char const *) ;
 typedef cbfunc *cbfunc_ref ;
 
-#define MAXCBQ 16
+static io_t io[2] =
+{
+  { .in = BUFFER_INIT(&buffer_read, 0, io[0].inbuf, INSIZE), .out = BUFFER_INIT(&buffer_write, 1, io[0].outbuf, OUTSIZE), .w = 0 },
+  { .w = 0 }
+} ;
+
+static int fdctl ;
+static int sslfds[2] ;
+static int wantexec = 0 ;
 
 static cbfunc_ref cbq[MAXCBQ] ;
 static size_t cbq_head = 0, cbq_tail = 0 ;
@@ -114,15 +123,16 @@ static void process_server_line (char const *s)
   if ((*cbq[cbq_tail])(s)) cbq_tail = (cbq_tail + 1) % MAXCBQ ;
 }
 
-typedef int cmdfunc (char const *) ;
-typedef cmdfunc *cmdfunc_ref ;
-
-typedef struct cmdmap_s cmdmap, *cmdmap_ref ;
-struct cmdmap_s
+static int namecmp (void const *a, void const *b)
 {
-  char const *name ;
-  cmdfunc_ref f ;
-} ;
+  char const *key = a ;
+  char const *name = ((struct cmdmap_s const *)b)->name ;
+  size_t len = strlen(name) ;
+  int r = strncasecmp(key, name, len) ;
+  if (r) return r ;
+  return !(key[len] == ' ' || key[len] == '\r' || key[len] == '\n') ;
+}
+#define BSEARCH(key, array) bsearch(key, (array), sizeof(array)/sizeof(struct cmdmap_s), sizeof(struct cmdmap_s), &namecmp)
 
 static int command_enqueue (char const *s, cbfunc_ref f)
 {
@@ -193,34 +203,25 @@ static int do_starttls (char const *s)
   return 0 ;
 }
 
-static cmdmap const commands[] =
-{
-  { .name = "ehlo", .f = &do_ehlo },
-  { .name = "starttls", .f = &do_starttls },
-  { .name = "helo", .f = &do_notls },
-  { .name = "mail", .f = &do_notls },
-  { .name = "rcpt", .f = &do_badorder },
-  { .name = "data", .f = &do_badorder },
-  { .name = "rset", .f = &do_forward },
-  { .name = "vrfy", .f = &do_forward },
-  { .name = "expn", .f = &do_forward },
-  { .name = "help", .f = &do_forward },
-  { .name = "noop", .f = &do_noop },
-  { .name = "quit", .f = &do_forward },
-  { .name = 0, .f = 0 }
-} ;
-
 static int process_client_line (char const *s)
 {
-  cmdmap const *cmd = commands ;
-  for (; cmd->name ; cmd++)
+  static struct cmdmap_s const commands[] =
   {
-    size_t len = strlen(cmd->name) ;
-    if (!strncasecmp(s, cmd->name, strlen(cmd->name))
-     && (s[len] == ' ' || s[len] == '\r' || s[len] == '\n'))
-      break ;
-  }
-  if (cmd->name) return (*cmd->f)(s) ;
+    { .name = "data", .f = &do_badorder },
+    { .name = "ehlo", .f = &do_ehlo },
+    { .name = "expn", .f = &do_forward },
+    { .name = "helo", .f = &do_notls },
+    { .name = "help", .f = &do_forward },
+    { .name = "mail", .f = &do_notls },
+    { .name = "noop", .f = &do_noop },
+    { .name = "quit", .f = &do_forward },
+    { .name = "rcpt", .f = &do_badorder },
+    { .name = "rset", .f = &do_forward },
+    { .name = "starttls", .f = &do_starttls },
+    { .name = "vrfy", .f = &do_forward }
+  } ;
+  struct cmdmap_s const *cmd = BSEARCH(s, commands) ;
+  if (cmd) return (*cmd->f)(s) ;
   answer_enqueue("500 SMTP motherfucker, do you speak it?\r\n") ;
   return 0 ;
 }