Hi again, We had a report of a crash when running "smtpctl discover" on an envelope that has a invalid dispatcher (action name changed in the config).
The issue is that the dispatcher is not checked after the envelope is loaded as a result of the discover command. But adding the check afterwards is not enough, because the envelope is already in the envelope cache, so this makes the whole live update/discover process actually useless (we would have to invalidate the cache). So the right fix, which also simplifies the code (always a good sign), is to make that check along with the other envelope validation checks that happen at envelope load time. Eric. Index: queue.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/queue.c,v retrieving revision 1.189 diff -u -p -r1.189 queue.c --- queue.c 30 Dec 2018 23:09:58 -0000 1.189 +++ queue.c 20 Apr 2020 18:43:17 -0000 @@ -686,7 +686,6 @@ static void queue_timeout(int fd, short event, void *p) { static uint32_t msgid = 0; - struct dispatcher *dsp; struct envelope evp; struct event *ev = p; struct timeval tv; @@ -705,13 +704,6 @@ queue_timeout(int fd, short event, void } if (r) { - dsp = dict_get(env->sc_dispatchers, evp.dispatcher); - if (dsp == NULL) { - log_warnx("warn: queue: missing dispatcher \"%s\"" - " for envelope %016"PRIx64", ignoring", - evp.dispatcher, evp.id); - goto reset; - } if (msgid && evpid_to_msgid(evp.id) != msgid) { m_create(p_scheduler, IMSG_QUEUE_MESSAGE_COMMIT, 0, 0, -1); @@ -724,7 +716,6 @@ queue_timeout(int fd, short event, void m_close(p_scheduler); } -reset: tv.tv_sec = 0; tv.tv_usec = 10; evtimer_add(ev, &tv); Index: queue_backend.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/queue_backend.c,v retrieving revision 1.65 diff -u -p -r1.65 queue_backend.c --- queue_backend.c 30 Dec 2018 23:09:58 -0000 1.65 +++ queue_backend.c 20 Apr 2020 18:42:38 -0000 @@ -730,6 +730,9 @@ envelope_validate(struct envelope *ep) if (memchr(ep->errorline, '\0', sizeof(ep->errorline)) == NULL) return "invalid error line"; + if (dict_get(env->sc_dispatchers, ep->dispatcher) == NULL) + return "unknown dispatcher"; + return NULL; }