On Mon, Jan 02, 2017 at 12:12:42PM +0100, Martin Pieuchot wrote:
> Diff below adds an helper for pflowioctl().  The goal is to reduce the
> number of error paths where the NET_LOCK() should be released.
> 
> ok?

I would not call it pflow_init(), as ..._init() functions are often
called during boot.

There are some "if (...) { return (ENOMEM); }".  The braces are not
necessary.

anyway OK bluhm@

> 
> Index: net/if_pflow.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_pflow.c,v
> retrieving revision 1.65
> diff -u -p -r1.65 if_pflow.c
> --- net/if_pflow.c    29 Dec 2016 12:12:43 -0000      1.65
> +++ net/if_pflow.c    2 Jan 2017 11:11:01 -0000
> @@ -69,6 +69,7 @@ int pflow_output(struct ifnet *ifp, stru
>       struct rtentry *rt);
>  int  pflow_clone_create(struct if_clone *, int);
>  int  pflow_clone_destroy(struct ifnet *);
> +int  pflow_init(struct pflow_softc *, struct pflowreq *);
>  void pflow_init_timeouts(struct pflow_softc *);
>  int  pflow_calc_mtu(struct pflow_softc *, int, int);
>  void pflow_setmtu(struct pflow_softc *, int);
> @@ -302,6 +303,157 @@ pflowvalidsockaddr(const struct sockaddr
>               return (0);
>       }
>  }
> +
> +int
> +pflow_init(struct pflow_softc *sc, struct pflowreq *pflowr)
> +{
> +     struct proc             *p = curproc;
> +     struct socket           *so;
> +     struct sockaddr         *sa;
> +     int                      error = 0;
> +
> +     if (pflowr->addrmask & PFLOW_MASK_VERSION) {
> +             switch(pflowr->version) {
> +             case PFLOW_PROTO_5:
> +             case PFLOW_PROTO_10:
> +                     break;
> +             default:
> +                     return(EINVAL);
> +             }
> +     }
> +
> +     pflow_flush(sc);
> +
> +     if (pflowr->addrmask & PFLOW_MASK_DSTIP) {
> +             if (sc->sc_flowdst != NULL &&
> +                 sc->sc_flowdst->sa_family != pflowr->flowdst.ss_family) {
> +                     free(sc->sc_flowdst, M_DEVBUF, sc->sc_flowdst->sa_len);
> +                     sc->sc_flowdst = NULL;
> +                     if (sc->so != NULL) {
> +                             soclose(sc->so);
> +                             sc->so = NULL;
> +                     }
> +             }
> +
> +             if (sc->sc_flowdst == NULL) {
> +                     switch (pflowr->flowdst.ss_family) {
> +                     case AF_INET:
> +                             if ((sc->sc_flowdst = malloc(
> +                                 sizeof(struct sockaddr_in),
> +                                 M_DEVBUF,  M_NOWAIT)) == NULL) {
> +                                     return (ENOMEM);
> +                             }
> +                             memcpy(sc->sc_flowdst, &pflowr->flowdst,
> +                                 sizeof(struct sockaddr_in));
> +                             sc->sc_flowdst->sa_len = sizeof(struct
> +                                 sockaddr_in);
> +                             break;
> +                     case AF_INET6:
> +                             if ((sc->sc_flowdst = malloc(
> +                                 sizeof(struct sockaddr_in6),
> +                                 M_DEVBUF, M_NOWAIT)) == NULL) {
> +                                     return (ENOMEM);
> +                             }
> +                             memcpy(sc->sc_flowdst, &pflowr->flowdst,
> +                                 sizeof(struct sockaddr_in6));
> +                             sc->sc_flowdst->sa_len = sizeof(struct
> +                                 sockaddr_in6);
> +                             break;
> +                     default:
> +                             break;
> +                     }
> +             }
> +             if (sc->sc_flowdst != NULL) {
> +                     sc->send_nam->m_len = sc->sc_flowdst->sa_len;
> +                     sa = mtod(sc->send_nam, struct sockaddr *);
> +                     memcpy(sa, sc->sc_flowdst, sc->sc_flowdst->sa_len);
> +             }
> +     }
> +
> +     if (pflowr->addrmask & PFLOW_MASK_SRCIP) {
> +             if (sc->sc_flowsrc != NULL &&
> +                 sc->sc_flowsrc->sa_family != pflowr->flowsrc.ss_family) {
> +                     free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len);
> +                     sc->sc_flowsrc = NULL;
> +                     if (sc->so != NULL) {
> +                             soclose(sc->so);
> +                             sc->so = NULL;
> +                     }
> +             }
> +
> +             if (sc->sc_flowsrc == NULL) {
> +                     switch(pflowr->flowsrc.ss_family) {
> +                     case AF_INET:
> +                             if ((sc->sc_flowsrc = malloc(
> +                                 sizeof(struct sockaddr_in),
> +                                 M_DEVBUF, M_NOWAIT)) == NULL) {
> +                                     return (ENOMEM);
> +                             }
> +                             memcpy(sc->sc_flowsrc, &pflowr->flowsrc,
> +                                 sizeof(struct sockaddr_in));
> +                             sc->sc_flowsrc->sa_len = sizeof(struct
> +                                 sockaddr_in);
> +                             break;
> +                     case AF_INET6:
> +                             if ((sc->sc_flowsrc = malloc(
> +                                 sizeof(struct sockaddr_in6),
> +                                 M_DEVBUF, M_NOWAIT)) == NULL) {
> +                                     return (ENOMEM);
> +                             }
> +                             memcpy(sc->sc_flowsrc, &pflowr->flowsrc,
> +                                 sizeof(struct sockaddr_in6));
> +                             sc->sc_flowsrc->sa_len = sizeof(struct
> +                                 sockaddr_in6);
> +                             break;
> +                     default:
> +                             break;
> +                     }
> +             }
> +             if (sc->so != NULL) {
> +                     soclose(sc->so);
> +                     sc->so = NULL;
> +             }
> +     }
> +
> +     if (sc->so == NULL) {
> +             if (pflowvalidsockaddr(sc->sc_flowdst, 0)) {
> +                     error = socreate(sc->sc_flowdst->sa_family,
> +                         &so, SOCK_DGRAM, 0);
> +                     if (error)
> +                             return (error);
> +                     if (pflowvalidsockaddr(sc->sc_flowsrc, 1)) {
> +                             struct mbuf *m;
> +
> +                             MGET(m, M_WAIT, MT_SONAME);
> +                             m->m_len = sc->sc_flowsrc->sa_len;
> +                             sa = mtod(m, struct sockaddr *);
> +                             memcpy(sa, sc->sc_flowsrc,
> +                                 sc->sc_flowsrc->sa_len);
> +
> +                             error = sobind(so, m, p);
> +                             m_freem(m);
> +                             if (error) {
> +                                     soclose(so);
> +                                     return (error);
> +                             }
> +                     }
> +                     sc->so = so;
> +             }
> +     } else if (!pflowvalidsockaddr(sc->sc_flowdst, 0)) {
> +             soclose(sc->so);
> +             sc->so = NULL;
> +     }
> +
> +     /* error check is above */
> +     if (pflowr->addrmask & PFLOW_MASK_VERSION)
> +             sc->sc_version = pflowr->version;
> +
> +     pflow_setmtu(sc, ETHERMTU);
> +     pflow_init_timeouts(sc);
> +
> +     return (0);
> +}
> +
>  int
>  pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
>  {
> @@ -309,9 +461,6 @@ pflowioctl(struct ifnet *ifp, u_long cmd
>       struct pflow_softc      *sc = ifp->if_softc;
>       struct ifreq            *ifr = (struct ifreq *)data;
>       struct pflowreq          pflowr;
> -     struct socket           *so;
> -     struct sockaddr         *sa;
> -     struct mbuf             *m;
>       int                      s, error;
>  
>       switch (cmd) {
> @@ -365,159 +514,12 @@ pflowioctl(struct ifnet *ifp, u_long cmd
>               if ((error = copyin(ifr->ifr_data, &pflowr,
>                   sizeof(pflowr))))
>                       return (error);
> -             if (pflowr.addrmask & PFLOW_MASK_VERSION) {
> -                     switch(pflowr.version) {
> -                     case PFLOW_PROTO_5:
> -                     case PFLOW_PROTO_10:
> -                             break;
> -                     default:
> -                             return(EINVAL);
> -                     }
> -             }
>  
>               s = splnet();
> -             pflow_flush(sc);
> -
> -             if (pflowr.addrmask & PFLOW_MASK_DSTIP) {
> -                     if (sc->sc_flowdst != NULL &&
> -                         sc->sc_flowdst->sa_family !=
> -                         pflowr.flowdst.ss_family) {
> -                             free(sc->sc_flowdst, M_DEVBUF,
> -                                 sc->sc_flowdst->sa_len);
> -                             sc->sc_flowdst = NULL;
> -                             if (sc->so != NULL) {
> -                                     soclose(sc->so);
> -                                     sc->so = NULL;
> -                             }
> -                     }
> -
> -                     if (sc->sc_flowdst == NULL) {
> -                             switch(pflowr.flowdst.ss_family) {
> -                             case AF_INET:
> -                                     if ((sc->sc_flowdst = malloc(
> -                                         sizeof(struct sockaddr_in),
> -                                         M_DEVBUF,  M_NOWAIT)) == NULL) {
> -                                             splx(s);
> -                                             return (ENOMEM);
> -                                     }
> -                                     memcpy(sc->sc_flowdst, &pflowr.flowdst,
> -                                         sizeof(struct sockaddr_in));
> -                                     sc->sc_flowdst->sa_len = sizeof(struct
> -                                         sockaddr_in);
> -                                     break;
> -                             case AF_INET6:
> -                                     if ((sc->sc_flowdst = malloc(
> -                                         sizeof(struct sockaddr_in6),
> -                                         M_DEVBUF, M_NOWAIT)) == NULL) {
> -                                             splx(s);
> -                                             return (ENOMEM);
> -                                     }
> -                                     memcpy(sc->sc_flowdst, &pflowr.flowdst,
> -                                         sizeof(struct sockaddr_in6));
> -                                     sc->sc_flowdst->sa_len = sizeof(struct
> -                                         sockaddr_in6);
> -                                     break;
> -                             default:
> -                                     break;
> -                             }
> -                     }
> -                     if (sc->sc_flowdst != NULL) {
> -                             sc->send_nam->m_len = sc->sc_flowdst->sa_len;
> -                             sa = mtod(sc->send_nam, struct sockaddr *);
> -                             memcpy(sa, sc->sc_flowdst,
> -                                 sc->sc_flowdst->sa_len);
> -                     }
> -             }
> -
> -             if (pflowr.addrmask & PFLOW_MASK_SRCIP) {
> -                     if (sc->sc_flowsrc != NULL &&
> -                         sc->sc_flowsrc->sa_family !=
> -                         pflowr.flowsrc.ss_family) {
> -                             free(sc->sc_flowsrc, M_DEVBUF,
> -                                 sc->sc_flowsrc->sa_len);
> -                             sc->sc_flowsrc = NULL;
> -                             if (sc->so != NULL) {
> -                                     soclose(sc->so);
> -                                     sc->so = NULL;
> -                             }
> -                     }
> -
> -                     if (sc->sc_flowsrc == NULL) {
> -                             switch(pflowr.flowsrc.ss_family) {
> -                             case AF_INET:
> -                                     if ((sc->sc_flowsrc = malloc(
> -                                         sizeof(struct sockaddr_in),
> -                                         M_DEVBUF, M_NOWAIT)) == NULL) {
> -                                             splx(s);
> -                                             return (ENOMEM);
> -                                     }
> -                                     memcpy(sc->sc_flowsrc, &pflowr.flowsrc,
> -                                         sizeof(struct sockaddr_in));
> -                                     sc->sc_flowsrc->sa_len = sizeof(struct
> -                                         sockaddr_in);
> -                                     break;
> -                             case AF_INET6:
> -                                     if ((sc->sc_flowsrc = malloc(
> -                                         sizeof(struct sockaddr_in6),
> -                                         M_DEVBUF, M_NOWAIT)) == NULL) {
> -                                             splx(s);
> -                                             return (ENOMEM);
> -                                     }
> -                                     memcpy(sc->sc_flowsrc, &pflowr.flowsrc,
> -                                         sizeof(struct sockaddr_in6));
> -                                     sc->sc_flowsrc->sa_len = sizeof(struct
> -                                         sockaddr_in6);
> -                                     break;
> -                             default:
> -                                     break;
> -                             }
> -                     }
> -                     if (sc->so != NULL) {
> -                             soclose(sc->so);
> -                             sc->so = NULL;
> -                     }
> -             }
> -
> -             if (sc->so == NULL) {
> -                     if (pflowvalidsockaddr(sc->sc_flowdst, 0)) {
> -                             error = socreate(sc->sc_flowdst->sa_family,
> -                                 &so, SOCK_DGRAM, 0);
> -                             if (error) {
> -                                     splx(s);
> -                                     return (error);
> -                             }
> -                             if (pflowvalidsockaddr(sc->sc_flowsrc, 1)) {
> -                                     MGET(m, M_WAIT, MT_SONAME);
> -                                     m->m_len = sc->sc_flowsrc->sa_len;
> -                                     sa = mtod(m, struct sockaddr *);
> -                                     memcpy(sa, sc->sc_flowsrc,
> -                                         sc->sc_flowsrc->sa_len);
> -
> -                                     error = sobind(so, m, p);
> -                                     m_freem(m);
> -                                     if (error) {
> -                                             soclose(so);
> -                                             splx(s);
> -                                             return (error);
> -                                     }
> -                             }
> -                             sc->so = so;
> -                     }
> -             } else {
> -                     if (!pflowvalidsockaddr(sc->sc_flowdst, 0)) {
> -                             soclose(sc->so);
> -                             sc->so = NULL;
> -                     }
> -             }
> -
> -             /* error check is above */
> -             if (pflowr.addrmask & PFLOW_MASK_VERSION)
> -                     sc->sc_version = pflowr.version;
> -
> -             pflow_setmtu(sc, ETHERMTU);
> -             pflow_init_timeouts(sc);
> -
> +             error = pflow_init(sc, &pflowr);
>               splx(s);
> +             if (error != 0)
> +                     return (error);
>  
>               if ((ifp->if_flags & IFF_UP) && sc->so != NULL) {
>                       ifp->if_flags |= IFF_RUNNING;

Reply via email to