> On 09 Sep 2016, at 13:35, Eric Faurot <e...@faurot.net> wrote:
> 
> Because of the small ad hoc changes that were made here and there over
> the years, the listener config code has become a bit convoluted I think.

Yes.

> Here is a little cleanup to:
> 
> - have all listener creation functions take listen_opts as param,
>  and call config_listener() when done, which adds the listener(s)
>  to the current config list of listeners.
> 
> - make the fallback chain between interface(), host_v4() host_v6()
>  and host_dns() obvious when creating an if_listener.
> 
> - fix a bug where the specified family was ignored if the listener
>  is given as a hostname.
> 
> 
> Comments?

I like that. ok jung@

> Eric.
> 
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
> retrieving revision 1.189
> diff -u -p -r1.189 parse.y
> --- parse.y   31 Aug 2016 15:24:04 -0000      1.189
> +++ parse.y   9 Sep 2016 11:11:54 -0000
> @@ -138,15 +138,14 @@ static struct listen_opts {
>       uint32_t        options;
> } 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);
> -int           host_dns(struct listenerlist *, struct listen_opts *);
> -int           host(struct listenerlist *, struct listen_opts *);
> -int           interface(struct listenerlist *, struct listen_opts *);
> +static void  create_sock_listener(struct listen_opts *);
> +static void  create_if_listener(struct listen_opts *);
> +static void  config_listener(struct listener *, struct listen_opts *);
> +static int   host_v4(struct listen_opts *);
> +static int   host_v6(struct listen_opts *);
> +static int   host_dns(struct listen_opts *);
> +static int   interface(struct listen_opts *);
> +
> void           set_local(const char *);
> void           set_localaddrs(struct table *);
> int            delaytonum(char *);
> @@ -695,13 +694,13 @@ socket_listener : SOCKET sock_listen {
>                               yyerror("socket listener already configured");
>                               YYERROR;
>                       }
> -                     conf->sc_sock_listener = 
> create_sock_listener(&listen_opts);
> +                     create_sock_listener(&listen_opts);
>               }
>               ;
> 
> if_listener   : STRING if_listen {
>                       listen_opts.ifx = $1;
> -                     create_if_listener(conf->sc_listeners, &listen_opts);
> +                     create_if_listener(&listen_opts);
>               }
>               ;
> 
> @@ -2005,7 +2004,7 @@ parse_config(struct smtpd *x_conf, const
>       /* 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);
> +             create_sock_listener(&listen_opts);
>       }
> 
>       /* Free macros and check which have not been used. */
> @@ -2109,7 +2108,7 @@ symget(const char *nam)
>       return (NULL);
> }
> 
> -static struct listener *
> +static void
> create_sock_listener(struct listen_opts *lo)
> {
>       struct listener *l = xcalloc(1, sizeof(*l), "create_sock_listener");
> @@ -2118,13 +2117,12 @@ create_sock_listener(struct listen_opts 
>       l->ss.ss_family = AF_LOCAL;
>       l->ss.ss_len = sizeof(struct sockaddr *);
>       l->local = 1;
> +     conf->sc_sock_listener = l;
>       config_listener(l, lo);
> -
> -     return (l);
> }
> 
> static void
> -create_if_listener(struct listenerlist *ll,  struct listen_opts *lo)
> +create_if_listener(struct listen_opts *lo)
> {
>       uint16_t        flags;
> 
> @@ -2142,17 +2140,11 @@ create_if_listener(struct listenerlist *
>       if (lo->port) {
>               lo->flags = lo->ssl|lo->auth|flags;
>               lo->port = htons(lo->port);
> -             if (!interface(ll, lo))
> -                     if (host(ll, lo) <= 0)
> -                             errx(1, "invalid virtual ip or interface: %s", 
> lo->ifx);
>       }
>       else {
>               if (lo->ssl & F_SMTPS) {
>                       lo->port = htons(465);
>                       lo->flags = F_SMTPS|lo->auth|flags;
> -                     if (!interface(ll, lo))
> -                             if (host(ll, lo) <= 0)
> -                                     errx(1, "invalid virtual ip or 
> interface: %s", lo->ifx);
>               }
> 
>               if (!lo->ssl || (lo->ssl & F_STARTTLS)) {
> @@ -2160,11 +2152,19 @@ create_if_listener(struct listenerlist *
>                       lo->flags = lo->auth|flags;
>                       if (lo->ssl & F_STARTTLS)
>                               lo->flags |= F_STARTTLS;
> -                     if (!interface(ll, lo))
> -                             if (host(ll, lo) <= 0)
> -                                     errx(1, "invalid virtual ip or 
> interface: %s", lo->ifx);
>               }
>       }
> +
> +     if (interface(lo))
> +             return;
> +     if (host_v4(lo))
> +             return;
> +     if (host_v6(lo))
> +             return;
> +     if (host_dns(lo))
> +             return;
> +
> +     errx(1, "invalid virtual ip or interface: %s", lo->ifx);
> }
> 
> static void
> @@ -2224,58 +2224,69 @@ config_listener(struct listener *h,  str
> 
>       if (lo->ssl & F_TLS_VERIFY)
>               h->flags |= F_TLS_VERIFY;
> +
> +     if (h != conf->sc_sock_listener)
> +             TAILQ_INSERT_TAIL(conf->sc_listeners, h, entry);
> }
> 
> -struct listener *
> -host_v4(const char *s, in_port_t port)
> +static int
> +host_v4(struct listen_opts *lo)
> {
>       struct in_addr           ina;
>       struct sockaddr_in      *sain;
>       struct listener         *h;
> 
> +     if (lo->family != AF_UNSPEC && lo->family != AF_INET)
> +             return (0);
> +
>       memset(&ina, 0, sizeof(ina));
> -     if (inet_pton(AF_INET, s, &ina) != 1)
> -             return (NULL);
> +     if (inet_pton(AF_INET, lo->ifx, &ina) != 1)
> +             return (0);
> 
>       h = xcalloc(1, sizeof(*h), "host_v4");
>       sain = (struct sockaddr_in *)&h->ss;
>       sain->sin_len = sizeof(struct sockaddr_in);
>       sain->sin_family = AF_INET;
>       sain->sin_addr.s_addr = ina.s_addr;
> -     sain->sin_port = port;
> +     sain->sin_port = lo->port;
> 
>       if (sain->sin_addr.s_addr == htonl(INADDR_LOOPBACK))
>               h->local = 1;
> +     config_listener(h,  lo);
> 
> -     return (h);
> +     return (1);
> }
> 
> -struct listener *
> -host_v6(const char *s, in_port_t port)
> +static int
> +host_v6(struct listen_opts *lo)
> {
>       struct in6_addr          ina6;
>       struct sockaddr_in6     *sin6;
>       struct listener         *h;
> 
> +     if (lo->family != AF_UNSPEC && lo->family != AF_INET6)
> +             return (0);
> +
>       memset(&ina6, 0, sizeof(ina6));
> -     if (inet_pton(AF_INET6, s, &ina6) != 1)
> -             return (NULL);
> +     if (inet_pton(AF_INET6, lo->ifx, &ina6) != 1)
> +             return (0);
> 
>       h = xcalloc(1, sizeof(*h), "host_v6");
>       sin6 = (struct sockaddr_in6 *)&h->ss;
>       sin6->sin6_len = sizeof(struct sockaddr_in6);
>       sin6->sin6_family = AF_INET6;
> -     sin6->sin6_port = port;
> +     sin6->sin6_port = lo->port;
>       memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
> 
>       if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
>               h->local = 1;
> +     config_listener(h,  lo);
> 
> -     return (h);
> +     return (1);
> }
> 
> -int
> -host_dns(struct listenerlist *al, struct listen_opts *lo)
> +static int
> +host_dns(struct listen_opts *lo)
> {
>       struct addrinfo          hints, *res0, *res;
>       int                      error, cnt = 0;
> @@ -2284,7 +2295,7 @@ host_dns(struct listenerlist *al, struct
>       struct listener         *h;
> 
>       memset(&hints, 0, sizeof(hints));
> -     hints.ai_family = PF_UNSPEC;
> +     hints.ai_family = lo->family;
>       hints.ai_socktype = SOCK_STREAM;
>       hints.ai_flags = AI_ADDRCONFIG;
>       error = getaddrinfo(lo->ifx, NULL, &hints, &res0);
> @@ -2323,7 +2334,6 @@ host_dns(struct listenerlist *al, struct
> 
>               config_listener(h, lo);
> 
> -             TAILQ_INSERT_HEAD(al, h, entry);
>               cnt++;
>       }
> 
> @@ -2331,28 +2341,8 @@ host_dns(struct listenerlist *al, struct
>       return (cnt);
> }
> 
> -int
> -host(struct listenerlist *al, struct listen_opts *lo)
> -{
> -     struct listener *h;
> -
> -     h = host_v4(lo->ifx, lo->port);
> -
> -     /* IPv6 address? */
> -     if (h == NULL)
> -             h = host_v6(lo->ifx, lo->port);
> -
> -     if (h != NULL) {
> -             config_listener(h, lo);
> -             TAILQ_INSERT_HEAD(al, h, entry);
> -             return (1);
> -     }
> -
> -     return (host_dns(al, lo));
> -}
> -
> -int
> -interface(struct listenerlist *al, struct listen_opts *lo)
> +static int
> +interface(struct listen_opts *lo)
> {
>       struct ifaddrs *ifap, *p;
>       struct sockaddr_in      *sain;
> @@ -2400,7 +2390,6 @@ interface(struct listenerlist *al, struc
> 
>               config_listener(h, lo);
>               ret = 1;
> -             TAILQ_INSERT_HEAD(al, h, entry);
>       }
> 
>       freeifaddrs(ifap);
> 

Reply via email to