On Thu, Feb 11, 2016 at 05:28:50PM -0500, Peter Bisroev wrote:
> Hi Gilles,
> 
> Please find my diff inline to enable "listen on socket" feature that we have
> discussed. I have tested the diff with currently two supported listen options
> for this listener, mask-sender and filter. Everything seems to be working OK.
> 
> These are the summary of the changes:
> * Parser was adjusted to support "listen on socket", should be easier to
>   extend to new listener types.
> * Reusing config_listener().
> * struct smtpd has a new member sc_sock_listener to be used by smtp_enqueu()
> * If "listen on socket" was not specified in the config file, a default
>   socket listener will be created in parse_config()
> * I also removed "struct listener l" from parse.y as it was not being used
>   anywhere.
> * I have tried to stick to the coding style in the source, and tried to keep
>   the diff as small as possible. Please let me know if something is off and
>   I will fix it.
> 
> If these changes look OK to you, I will create a diff for the man page and
> send it through.
> 

I only skimmed through your diff, I need to apply it and read in
context but I like it a lot.

I'll test today and come back with comments once I've spent more
time reading it ;-)

Thanks


> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
> retrieving revision 1.181
> diff -u -p -r1.181 parse.y
> --- parse.y   18 Jan 2016 09:19:41 -0000      1.181
> +++ parse.y   11 Feb 2016 20:59:11 -0000
> @@ -97,7 +97,6 @@ static int           errors = 0;
>  struct filter_conf   *filter = NULL;
>  struct table         *table = NULL;
>  struct rule          *rule = NULL;
> -struct listener               l;
>  struct mta_limits    *limits;
>  static struct pki    *pki;
>  static struct ca     *sca;
> @@ -139,8 +138,9 @@ static struct listen_opts {
>       uint32_t        options;
>  } listen_opts;
>  
> -static void  create_listener(struct listenerlist *,  struct listen_opts *);
> -static void  config_listener(struct listener *,  struct listen_opts *);
> +static struct listener       *create_sock_listener(struct listen_opts *);
> +static void           create_if_listener(struct listenerlist *,  struct 
> listen_opts *);
> +static void           config_listener(struct listener *,  struct listen_opts 
> *);
>  
>  struct listener      *host_v4(const char *, in_port_t);
>  struct listener      *host_v6(const char *, in_port_t);
> @@ -156,6 +156,9 @@ static struct filter_conf *create_filter
>  static struct filter_conf *create_filter_chain(char *);
>  static int add_filter_arg(struct filter_conf *, char *);
>  
> +static int config_lo_filter(struct listen_opts *, char *);
> +static int config_lo_mask_source(struct listen_opts *);
> +
>  typedef struct {
>       union {
>               int64_t          number;
> @@ -175,7 +178,7 @@ typedef struct {
>  %token       ACCEPT REJECT INCLUDE ERROR MDA FROM FOR SOURCE MTA PKI 
> SCHEDULER
>  %token       ARROW AUTH TLS LOCAL VIRTUAL TAG TAGGED ALIAS FILTER KEY CA 
> DHPARAMS
>  %token       AUTH_OPTIONAL TLS_REQUIRE USERBASE SENDER SENDERS MASK_SOURCE 
> VERIFY FORWARDONLY RECIPIENT
> -%token       CIPHERS RECEIVEDAUTH MASQUERADE ENQUEUER
> +%token       CIPHERS RECEIVEDAUTH MASQUERADE SOCKET
>  %token       <v.string>      STRING
>  %token  <v.number>   NUMBER
>  %type        <v.table>       table
> @@ -403,7 +406,19 @@ pki              : opt_pki pki
>               | /* empty */
>               ;
>  
> -opt_listen           : INET4                 {
> +opt_sock_listen : FILTER STRING {
> +                     if (config_lo_filter(&listen_opts, $2)) {
> +                             YYERROR;
> +                     }
> +             }
> +             | MASK_SOURCE {
> +                     if (config_lo_mask_source(&listen_opts)) {
> +                             YYERROR;
> +                     }
> +             }
> +             ;
> +
> +opt_if_listen : INET4 {
>                       if (listen_opts.options & LO_FAMILY) {
>                               yyerror("address family already specified");
>                               YYERROR;
> @@ -451,13 +466,10 @@ opt_listen      : INET4                 {
>                       listen_opts.port = $2;
>               }
>               | FILTER STRING                 {
> -                     if (listen_opts.options & LO_FILTER) {
> -                             yyerror("filter already specified");
> +                     if (config_lo_filter(&listen_opts, $2)) {
>                               YYERROR;
>                       }
> -                     listen_opts.options |= LO_FILTER;
> -                     listen_opts.filtername = $2;
> -             }
> +}
>               | SMTPS                         {
>                       if (listen_opts.options & LO_SSL) {
>                               yyerror("TLS mode already specified");
> @@ -596,12 +608,9 @@ opt_listen       : INET4                 {
>                       listen_opts.hostnametable = t;
>               }
>               | MASK_SOURCE   {
> -                     if (listen_opts.options & LO_MASKSOURCE) {
> -                             yyerror("mask-source already specified");
> +                     if (config_lo_mask_source(&listen_opts)) {
>                               YYERROR;
>                       }
> -                     listen_opts.options |= LO_MASKSOURCE;
> -                     listen_opts.flags |= F_MASK_SOURCE;
>               }
>               | RECEIVEDAUTH  {
>                       if (listen_opts.options & LO_RECEIVEDAUTH) {
> @@ -653,7 +662,33 @@ opt_listen       : INET4                 {
>               }
>               ;
>  
> -listen               : opt_listen listen
> +listener_type        : socket_listener
> +             | interface_listener
> +             ;
> +
> +socket_listener      : SOCKET sock_listen {
> +                     if (conf->sc_sock_listener) {
> +                             yyerror("socket listener already configured");
> +                             YYERROR;
> +                     }
> +                     conf->sc_sock_listener = 
> create_sock_listener(&listen_opts);
> +             }
> +             ;
> +
> +interface_listener:
> +             STRING if_listen {
> +                     listen_opts.family = AF_UNSPEC;
> +                     listen_opts.flags |= F_EXT_DSN;
> +                     listen_opts.ifx = $1;
> +                     create_if_listener(conf->sc_listeners, &listen_opts);
> +             }
> +             ;
> +
> +sock_listen  : opt_sock_listen sock_listen
> +             | /* empty */
> +             ;
> +
> +if_listen    : opt_if_listen if_listen
>               | /* empty */
>               ;
>  
> @@ -846,28 +881,8 @@ main             : BOUNCEWARN {
>               } limits_mta
>               | LIMIT SCHEDULER limits_scheduler
>               | LISTEN {
> -                     memset(&l, 0, sizeof l);
>                       memset(&listen_opts, 0, sizeof listen_opts);
> -                     listen_opts.family = AF_UNSPEC;
> -                     listen_opts.flags |= F_EXT_DSN;
> -             } ON STRING listen {
> -                     listen_opts.ifx = $4;
> -                     create_listener(conf->sc_listeners, &listen_opts);
> -             }
> -             | ENQUEUER FILTER STRING {
> -                     if (dict_get(&conf->sc_filters, $3) == NULL) {
> -                             yyerror("undefined filter \"%s\"", $3);
> -                             free($3);
> -                             YYERROR;
> -                     }
> -                     if (strlcpy(conf->sc_enqueue_filter, $3,
> -                             sizeof conf->sc_enqueue_filter)
> -                         >= sizeof conf->sc_enqueue_filter) {
> -                             free($3);
> -                             YYERROR;
> -                     }
> -                     free($3);
> -             }
> +             } ON listener_type
>               | FILTER STRING STRING {
>                       if (!strcmp($3, "chain")) {
>                               free($3);
> @@ -1449,7 +1464,6 @@ lookup(char *s)
>               { "dhparams",           DHPARAMS },
>               { "domain",             DOMAIN },
>               { "encryption",         ENCRYPTION },
> -             { "enqueuer",           ENQUEUER },
>               { "expire",             EXPIRE },
>               { "filter",             FILTER },
>               { "for",                FOR },
> @@ -1489,6 +1503,7 @@ lookup(char *s)
>               { "senders",            SENDERS },
>               { "session",            SESSION },
>               { "smtps",              SMTPS },
> +             { "socket",             SOCKET },
>               { "source",             SOURCE },
>               { "table",              TABLE },
>               { "tag",                TAG },
> @@ -1945,6 +1960,12 @@ parse_config(struct smtpd *x_conf, const
>       popfile();
>       endservent();
>  
> +     /* If the socket listener was not configured, create a default one. */
> +     if (!conf->sc_sock_listener) {
> +             memset(&listen_opts, 0, sizeof listen_opts);
> +             conf->sc_sock_listener = create_sock_listener(&listen_opts);
> +     }
> +
>       /* Free macros and check which have not been used. */
>       for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
>               next = TAILQ_NEXT(sym, entry);
> @@ -2046,8 +2067,21 @@ symget(const char *nam)
>       return (NULL);
>  }
>  
> +static struct listener *
> +create_sock_listener(struct listen_opts *lo)
> +{
> +     struct listener *l = xcalloc(1, sizeof(*l), "create_sock_listener");
> +     lo->tag = "local";
> +     lo->hostname = conf->sc_hostname;
> +     l->ss.ss_family = AF_LOCAL;
> +     l->ss.ss_len = sizeof(struct sockaddr *);
> +     config_listener(l, lo);
> +
> +     return (l);
> +}
> +
>  static void
> -create_listener(struct listenerlist *ll,  struct listen_opts *lo)
> +create_if_listener(struct listenerlist *ll,  struct listen_opts *lo)
>  {
>       uint16_t        flags;
>  
> @@ -2560,3 +2594,28 @@ add_filter_arg(struct filter_conf *f, ch
>  
>       return (1);
>  }
> +
> +static int
> +config_lo_filter(struct listen_opts *lo, char *filter_name) {
> +     if (lo->options & LO_FILTER) {
> +             yyerror("filter already specified");
> +             return -1;
> +     }
> +     lo->options |= LO_FILTER;
> +     lo->filtername = filter_name;
> +
> +     return 0;
> +}
> +
> +static int
> +config_lo_mask_source(struct listen_opts *lo) {
> +     if (lo->options & LO_MASKSOURCE) {
> +             yyerror("mask-source already specified");
> +             return -1;
> +     }
> +     lo->options |= LO_MASKSOURCE;
> +     lo->flags |= F_MASK_SOURCE;
> +
> +     return 0;
> +}
> +
> Index: smtp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtp.c,v
> retrieving revision 1.152
> diff -u -p -r1.152 smtp.c
> --- smtp.c    8 Jan 2016 21:31:06 -0000       1.152
> +++ smtp.c    11 Feb 2016 20:59:11 -0000
> @@ -219,20 +219,9 @@ smtp_resume(void)
>  static int
>  smtp_enqueue(uid_t *euid)
>  {
> -     static struct listener   local, *listener = NULL;
> -     char                     buf[HOST_NAME_MAX+1], *hostname;
> -     int                      fd[2];
> -
> -     if (listener == NULL) {
> -             listener = &local;
> -             (void)strlcpy(listener->tag, "local", sizeof(listener->tag));
> -             listener->ss.ss_family = AF_LOCAL;
> -             listener->ss.ss_len = sizeof(struct sockaddr *);
> -             (void)strlcpy(listener->hostname, env->sc_hostname,
> -                 sizeof(listener->hostname));
> -             (void)strlcpy(listener->filter, env->sc_enqueue_filter,
> -                 sizeof listener->filter);
> -     }
> +     struct listener  *listener = env->sc_sock_listener;
> +     char             buf[HOST_NAME_MAX+1], *hostname;
> +     int              fd[2];
>  
>       /*
>        * Some enqueue requests buffered in IMSG may still arrive even after
> Index: smtpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
> retrieving revision 1.511
> diff -u -p -r1.511 smtpd.h
> --- smtpd.h   5 Feb 2016 19:21:04 -0000       1.511
> +++ smtpd.h   11 Feb 2016 20:59:11 -0000
> @@ -613,6 +613,9 @@ struct smtpd {
>  
>       time_t                                   sc_uptime;
>  
> +     /* This is a listener for a local socket used by smtp_enqueue(). */
> +     struct listener                         *sc_sock_listener;
> +
>       TAILQ_HEAD(listenerlist, listener)      *sc_listeners;
>  
>       TAILQ_HEAD(rulelist, rule)              *sc_rules;
> 

-- 
Gilles Chehade

https://www.poolp.org                                          @poolpOrg

Reply via email to