diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2020-08-27 10:47:53 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2020-08-27 10:47:53 +0000 |
commit | 13adc2f816f74e7ed9d6a6c95db6354105f39ad1 (patch) | |
tree | 9a78f149be7dc6d2f58080258f61bb2dcee45744 /sys/net/if_pppx.c | |
parent | 23f545c2b3de218f838ddd0c6b8b9625f736b2de (diff) |
Make pipex(4) more common for pppac(4) and pppx(4). Replace
pipex_iface of struct pipex_session with owner_sc which refers the
owner device. This makes ioctl commands for pppac or pppx device
simpler. PIPEX{S,G}MODE became dummy since both pppac and pppx is
always used with pipex. Also move some pppac specific things to the
pppac part on if_pppx.c.
suggestions from mvs, ok mvs
Diffstat (limited to 'sys/net/if_pppx.c')
-rw-r--r-- | sys/net/if_pppx.c | 188 |
1 files changed, 99 insertions, 89 deletions
diff --git a/sys/net/if_pppx.c b/sys/net/if_pppx.c index e48291d6f77..8906fc73491 100644 --- a/sys/net/if_pppx.c +++ b/sys/net/if_pppx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pppx.c,v 1.101 2020/08/14 11:05:38 mvs Exp $ */ +/* $OpenBSD: if_pppx.c,v 1.102 2020/08/27 10:47:52 yasuoka Exp $ */ /* * Copyright (c) 2010 Claudio Jeker <claudio@openbsd.org> @@ -163,7 +163,6 @@ struct pppx_if { struct ifnet pxi_if; struct pppx_dev *pxi_dev; /* [I] */ struct pipex_session *pxi_session; /* [I] */ - struct pipex_iface_context pxi_ifcontext; /* [N] */ }; static inline int @@ -181,12 +180,6 @@ int pppx_add_session(struct pppx_dev *, struct pipex_session_req *); int pppx_del_session(struct pppx_dev *, struct pipex_session_close_req *); -int pppx_config_session(struct pppx_dev *, - struct pipex_session_config_req *); -int pppx_get_stat(struct pppx_dev *, - struct pipex_session_stat_req *); -int pppx_get_closed(struct pppx_dev *, - struct pipex_session_list_req *); int pppx_set_session_descr(struct pppx_dev *, struct pipex_session_descr_req *); @@ -424,17 +417,6 @@ pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) NET_LOCK(); switch (cmd) { - case PIPEXSMODE: - /* - * npppd always enables on open, and only disables before - * closing. we cheat and let open and close do that, so lie - * to npppd. - */ - break; - case PIPEXGMODE: - *(int *)addr = 1; - break; - case PIPEXASESSION: error = pppx_add_session(pxd, (struct pipex_session_req *)addr); @@ -445,21 +427,6 @@ pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) (struct pipex_session_close_req *)addr); break; - case PIPEXCSESSION: - error = pppx_config_session(pxd, - (struct pipex_session_config_req *)addr); - break; - - case PIPEXGSTAT: - error = pppx_get_stat(pxd, - (struct pipex_session_stat_req *)addr); - break; - - case PIPEXGCLOSED: - error = pppx_get_closed(pxd, - (struct pipex_session_list_req *)addr); - break; - case PIPEXSIFDESCR: error = pppx_set_session_descr(pxd, (struct pipex_session_descr_req *)addr); @@ -472,7 +439,7 @@ pppxioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; default: - error = ENOTTY; + error = pipex_ioctl(pxd, cmd, addr); break; } NET_UNLOCK(); @@ -741,11 +708,7 @@ pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req) if_addrhooks_run(ifp); } - /* fake a pipex interface context */ - pxi->pxi_ifcontext.ifindex = ifp->if_index; - pxi->pxi_ifcontext.pipexmode = PIPEX_ENABLED; - - error = pipex_link_session(session, &pxi->pxi_ifcontext); + error = pipex_link_session(session, ifp, pxd); if (error) goto detach; @@ -786,40 +749,6 @@ pppx_del_session(struct pppx_dev *pxd, struct pipex_session_close_req *req) } int -pppx_config_session(struct pppx_dev *pxd, - struct pipex_session_config_req *req) -{ - struct pppx_if *pxi; - - pxi = pppx_if_find(pxd, req->pcr_session_id, req->pcr_protocol); - if (pxi == NULL) - return (EINVAL); - - return pipex_config_session(req, &pxi->pxi_ifcontext); -} - -int -pppx_get_stat(struct pppx_dev *pxd, struct pipex_session_stat_req *req) -{ - struct pppx_if *pxi; - - pxi = pppx_if_find(pxd, req->psr_session_id, req->psr_protocol); - if (pxi == NULL) - return (EINVAL); - - return pipex_get_stat(req, &pxi->pxi_ifcontext); -} - -int -pppx_get_closed(struct pppx_dev *pxd, struct pipex_session_list_req *req) -{ - /* XXX: Only opened sessions exist for pppx(4) */ - memset(req, 0, sizeof(*req)); - - return 0; -} - -int pppx_set_session_descr(struct pppx_dev *pxd, struct pipex_session_descr_req *req) { @@ -1014,8 +943,8 @@ struct pppac_softc { struct mutex sc_wsel_mtx; struct selinfo sc_wsel; - struct pipex_iface_context - sc_pipex_iface; + struct pipex_session + *sc_multicast_session; struct mbuf_queue sc_mq; @@ -1047,6 +976,10 @@ static struct pppac_list pppac_devs = LIST_HEAD_INITIALIZER(pppac_devs); static int pppac_ioctl(struct ifnet *, u_long, caddr_t); +static int pppac_add_session(struct pppac_softc *, + struct pipex_session_req *); +static int pppac_del_session(struct pppac_softc *, + struct pipex_session_close_req *); static int pppac_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void pppac_qstart(struct ifqueue *); @@ -1075,6 +1008,7 @@ pppacopen(dev_t dev, int flags, int mode, struct proc *p) { struct pppac_softc *sc; struct ifnet *ifp; + struct pipex_session *session; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); if (pppac_lookup(dev) != NULL) { @@ -1082,6 +1016,12 @@ pppacopen(dev_t dev, int flags, int mode, struct proc *p) return (EBUSY); } + /* virtual pipex_session entry for multicast */ + session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO); + session->is_multicast = 1; + session->ownersc = sc; + sc->sc_multicast_session = session; + sc->sc_dev = dev; mtx_init(&sc->sc_rsel_mtx, IPL_SOFTNET); @@ -1112,8 +1052,6 @@ pppacopen(dev_t dev, int flags, int mode, struct proc *p) bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif - pipex_iface_init(&sc->sc_pipex_iface, ifp->if_index); - return (0); } @@ -1245,6 +1183,7 @@ pppacioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) struct pppac_softc *sc = pppac_lookup(dev); int error = 0; + NET_LOCK(); switch (cmd) { case TUNSIFMODE: /* make npppd happy */ break; @@ -1255,10 +1194,18 @@ pppacioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) *(int *)data = mq_hdatalen(&sc->sc_mq); break; + case PIPEXASESSION: + error = pppac_add_session(sc, (struct pipex_session_req *)data); + break; + case PIPEXDSESSION: + error = pppac_del_session(sc, + (struct pipex_session_close_req *)data); + break; default: - error = pipex_ioctl(&sc->sc_pipex_iface, cmd, data); + error = pipex_ioctl(sc, cmd, data); break; } + NET_UNLOCK(); return (error); } @@ -1373,7 +1320,10 @@ pppacclose(dev_t dev, int flags, int mode, struct proc *p) if_detach(ifp); - pipex_iface_fini(&sc->sc_pipex_iface); + pool_put(&pipex_session_pool, sc->sc_multicast_session); + NET_LOCK(); + pipex_destroy_all_sessions(sc); + NET_UNLOCK(); LIST_REMOVE(sc, sc_entry); free(sc, M_DEVBUF, sizeof(*sc)); @@ -1417,6 +1367,37 @@ pppac_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } static int +pppac_add_session(struct pppac_softc *sc, struct pipex_session_req *req) +{ + int error; + struct pipex_session *session; + + error = pipex_init_session(&session, req); + if (error != 0) + return (error); + error = pipex_link_session(session, &sc->sc_if, sc); + if (error != 0) + pipex_rele_session(session); + + return (error); +} + +static int +pppac_del_session(struct pppac_softc *sc, struct pipex_session_close_req *req) +{ + struct pipex_session *session; + + session = pipex_lookup_by_session_id(req->pcr_protocol, + req->pcr_session_id); + if (session == NULL || session->ownersc != sc) + return (EINVAL); + pipex_unlink_session(session); + pipex_rele_session(session); + + return (0); +} + +static int pppac_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { @@ -1452,7 +1433,10 @@ pppac_qstart(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; struct pppac_softc *sc = ifp->if_softc; - struct mbuf *m; + struct mbuf *m, *m0; + struct pipex_session *session; + struct ip ip; + int rv; NET_LOCK(); while ((m = ifq_dequeue(ifq)) != NULL) { @@ -1463,19 +1447,45 @@ pppac_qstart(struct ifqueue *ifq) } #endif - m = pipex_output(m, m->m_pkthdr.ph_family, 0, - &sc->sc_pipex_iface); - if (m == NULL) + switch (m->m_pkthdr.ph_family) { + case AF_INET: + if (m->m_pkthdr.len < sizeof(struct ip)) + goto bad; + m_copydata(m, 0, sizeof(struct ip), (caddr_t)&ip); + if (IN_MULTICAST(ip.ip_dst.s_addr)) { + /* pass a copy to pipex */ + m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT); + if (m0 != NULL) + pipex_ip_output(m0, + sc->sc_multicast_session); + else + goto bad; + } else { + session = pipex_lookup_by_ip_address(ip.ip_dst); + if (session != NULL) { + pipex_ip_output(m, session); + m = NULL; + } + } + break; + } + if (m == NULL) /* handled by pipex */ continue; m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT); - if (m == NULL) { - /* oh well */ - continue; - } + if (m == NULL) + goto bad; *mtod(m, uint32_t *) = htonl(m->m_pkthdr.ph_family); - mq_enqueue(&sc->sc_mq, m); /* qdrop */ + rv = mq_enqueue(&sc->sc_mq, m); + if (rv == 1) + counters_inc(ifp->if_counters, ifc_collisions); + continue; +bad: + counters_inc(ifp->if_counters, ifc_oerrors); + if (m != NULL) + m_freem(m); + continue; } NET_UNLOCK(); |