/* $OpenBSD: queue_backend.c,v 1.20 2012/01/14 15:13:14 chl Exp $ */ /* * Copyright (c) 2011 Gilles Chehade * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "smtpd.h" #include "log.h" static const char* envelope_validate(struct envelope *, uint64_t); /* fsqueue backend */ extern struct queue_backend queue_backend_fs; struct queue_backend * queue_backend_lookup(enum queue_type type) { switch (type) { case QT_FS: return &queue_backend_fs; default: fatalx("invalid queue type"); } return (NULL); } int queue_message_create(enum queue_kind qkind, u_int32_t *msgid) { return env->sc_queue->message(qkind, QOP_CREATE, msgid); } int queue_message_delete(enum queue_kind qkind, u_int32_t msgid) { return env->sc_queue->message(qkind, QOP_DELETE, &msgid); } int queue_message_commit(enum queue_kind qkind, u_int32_t msgid) { return env->sc_queue->message(qkind, QOP_COMMIT, &msgid); } int queue_message_corrupt(enum queue_kind qkind, u_int32_t msgid) { return env->sc_queue->message(qkind, QOP_CORRUPT, &msgid); } int queue_message_fd_r(enum queue_kind qkind, u_int32_t msgid) { return env->sc_queue->message(qkind, QOP_FD_R, &msgid); } int queue_message_fd_rw(enum queue_kind qkind, u_int32_t msgid) { return env->sc_queue->message(qkind, QOP_FD_RW, &msgid); } int queue_envelope_create(enum queue_kind qkind, struct envelope *ep) { return env->sc_queue->envelope(qkind, QOP_CREATE, ep); } int queue_envelope_delete(enum queue_kind qkind, struct envelope *ep) { return env->sc_queue->envelope(qkind, QOP_DELETE, ep); } int queue_envelope_load(enum queue_kind qkind, u_int64_t evpid, struct envelope *ep) { const char *e; ep->id = evpid; if (env->sc_queue->envelope(qkind, QOP_LOAD, ep)) { if ((e = envelope_validate(ep, evpid)) == NULL) return 1; log_debug("invalid envelope %016" PRIx64 ": %s", ep->id, e); } return 0; } int queue_envelope_update(enum queue_kind qkind, struct envelope *ep) { return env->sc_queue->envelope(qkind, QOP_UPDATE, ep); } void * qwalk_new(enum queue_kind kind, u_int32_t msgid) { return env->sc_queue->qwalk_new(kind, msgid); } int qwalk(void *hdl, u_int64_t *evpid) { return env->sc_queue->qwalk(hdl, evpid); } void qwalk_close(void *hdl) { return env->sc_queue->qwalk_close(hdl); } u_int32_t queue_generate_msgid(void) { u_int32_t msgid; while((msgid = arc4random_uniform(0xffffffff)) == 0) ; return msgid; } u_int64_t queue_generate_evpid(u_int32_t msgid) { u_int32_t rnd; u_int64_t evpid; while((rnd = arc4random_uniform(0xffffffff)) == 0) ; evpid = msgid; evpid <<= 32; evpid |= rnd; return evpid; } /**/ static const char* envelope_validate(struct envelope *ep, uint64_t id) { if (ep->version != SMTPD_ENVELOPE_VERSION) return "version mismatch"; if ((ep->id & 0xffffffff) == 0 || ((ep->id >> 32) & 0xffffffff) == 0) return "invalid id"; if (ep->id != id) return "id mismatch"; if (memchr(ep->helo, '\0', sizeof(ep->helo)) == NULL) return "invalid helo"; if (ep->helo[0] == '\0') return "empty helo"; if (memchr(ep->hostname, '\0', sizeof(ep->hostname)) == NULL) return "invalid hostname"; if (ep->hostname[0] == '\0') return "empty hostname"; if (memchr(ep->errorline, '\0', sizeof(ep->errorline)) == NULL) return "invalid error line"; return NULL; }