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;