diff options
Diffstat (limited to 'usr/src/uts/common/io/ppp/sppptun/sppptun.c')
-rw-r--r-- | usr/src/uts/common/io/ppp/sppptun/sppptun.c | 87 |
1 files changed, 49 insertions, 38 deletions
diff --git a/usr/src/uts/common/io/ppp/sppptun/sppptun.c b/usr/src/uts/common/io/ppp/sppptun/sppptun.c index 18e124c07b..18a729a1db 100644 --- a/usr/src/uts/common/io/ppp/sppptun/sppptun.c +++ b/usr/src/uts/common/io/ppp/sppptun/sppptun.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -448,7 +448,7 @@ sppptun_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp) char *cp; /* ordinary users have no need to push this module */ - if (secpolicy_net_config(credp, B_FALSE) != 0) + if (secpolicy_ppp_config(credp) != 0) return (EPERM); tll = kmem_zalloc(sizeof (tunll_t), KM_SLEEP); @@ -456,6 +456,7 @@ sppptun_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp) tll->tll_index = tunll_index++; tll->tll_wq = WR(q); + tll->tll_zoneid = crgetzoneid(credp); /* Insert at end of list */ insque(&tll->tll_next, tunll_list.q_back); @@ -514,6 +515,7 @@ sppptun_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp) return (ENOSR); tcl->tcl_rq = q; /* save read queue pointer */ tcl->tcl_flags |= TCLF_ISCLIENT; /* sanity check */ + tcl->tcl_zoneid = crgetzoneid(credp); q->q_ptr = WR(q)->q_ptr = (caddr_t)tcl; *devp = makedevice(getmajor(*devp), tcl->tcl_lsessid); @@ -539,17 +541,18 @@ make_control(tuncl_t *tclabout, tunll_t *tllabout, int action, tuncl_t *tclto) if (mp != NULL) { MTYPE(mp) = M_PROTO; ptc = (struct ppptun_control *)mp->b_wptr; + bzero(ptc, sizeof (*ptc)); mp->b_wptr += sizeof (*ptc); if (tclabout != NULL) { ptc->ptc_rsessid = tclabout->tcl_rsessid; ptc->ptc_address = tclabout->tcl_address; - } else { - bzero(ptc, sizeof (*ptc)); } ptc->ptc_discrim = tclto->tcl_ctlval; ptc->ptc_action = action; - (void) strncpy(ptc->ptc_name, tllabout->tll_name, - sizeof (ptc->ptc_name)); + if (tllabout != NULL) { + (void) strncpy(ptc->ptc_name, tllabout->tll_name, + sizeof (ptc->ptc_name)); + } } return (mp); } @@ -797,7 +800,8 @@ sppptun_outpkt(queue_t *q, mblk_t **mpp) *mpp = NULL; if (!(tcl->tcl_flags & TCLF_ISCLIENT)) { - merror(q, mp, EINVAL); + /* This should never happen on a lower layer stream */ + freemsg(mp); return (NULL); } @@ -815,7 +819,8 @@ sppptun_outpkt(queue_t *q, mblk_t **mpp) KCINCR(cks_octrl_drop); DTRACE_PROBE2(sppptun__bad__control, tuncl_t *, tcl, mblk_t *, mp); - merror(q, mp, EINVAL); + send_control(tcl, tcl->tcl_ctrl_tll, PTCA_BADCTRL, tcl); + freemsg(mp); return (NULL); } ptc = (struct ppptun_control *)mp->b_rptr; @@ -846,18 +851,22 @@ sppptun_outpkt(queue_t *q, mblk_t **mpp) } /* Don't allow empty control packets. */ + tll = tcl->tcl_ctrl_tll; if (mp->b_cont == NULL) { KCINCR(cks_octrl_drop); - merror(q, mp, EINVAL); + DTRACE_PROBE2(sppptun__bad__control, tuncl_t *, tcl, + mblk_t *, mp); + send_control(tcl, tll, PTCA_BADCTRL, tcl); + freemsg(mp); return (NULL); } - tll = tcl->tcl_ctrl_tll; } if (tll == NULL || (lowerq = tll->tll_wq) == NULL) { DTRACE_PROBE3(sppptun__cannot__send, tuncl_t *, tcl, tunll_t *, tll, mblk_t *, mp); - merror(q, mp, ENXIO); + send_control(tcl, tll, PTCA_UNPLUMB, tcl); + freemsg(mp); if (isdata) { tcl->tcl_stats.ppp_oerrors++; } else { @@ -919,7 +928,7 @@ sppptun_outpkt(queue_t *q, mblk_t **mpp) ether_copy(tcl->tcl_address.pta_pppoe.ptma_mac, edestp->addr); /* DLPI SAPs are in host byte order! */ - edestp->type = ETHERTYPE_PPPOES; + edestp->type = tll->tll_sap; /* Make sure the protocol field isn't compressed. */ len = (*mp->b_rptr & 1); @@ -969,7 +978,7 @@ sppptun_outpkt(queue_t *q, mblk_t **mpp) edestp = (ether_dest_t *)(dur + 1); /* DLPI SAPs are in host byte order! */ - edestp->type = ETHERTYPE_PPPOED; + edestp->type = tll->tll_sap; /* * If destination isn't set yet, then we have to @@ -1070,13 +1079,14 @@ save_for_close(tunll_t *tll, mblk_t *mp) * perimeters. */ static tunll_t * -tll_lookup_on_name(char *dname) +tll_lookup_on_name(const char *dname, zoneid_t zoneid) { tunll_t *tll; tll = TO_TLL(tunll_list.q_forw); for (; tll != TO_TLL(&tunll_list); tll = TO_TLL(tll->tll_next)) - if (strcmp(dname, tll->tll_name) == 0) + if (tll->tll_zoneid == zoneid && + strcmp(dname, tll->tll_name) == 0) return (tll); return (NULL); } @@ -1106,6 +1116,7 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) mblk_t *mptmp; ppptun_atype *pap; struct ppp_stats64 *psp; + zoneid_t zoneid; iop = (struct iocblk *)mp->b_rptr; tcl = NULL; @@ -1163,7 +1174,8 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) ptn = (union ppptun_name *)mp->b_cont->b_rptr; ptn->ptn_name[sizeof (ptn->ptn_name) - 1] = '\0'; - if ((tll = tll_lookup_on_name(ptn->ptn_name)) != NULL) { + tll = tll_lookup_on_name(ptn->ptn_name, tll->tll_zoneid); + if (tll != NULL) { rc = EEXIST; break; } @@ -1171,23 +1183,6 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) (void) strcpy(tll->tll_name, ptn->ptn_name); break; - case PPPTUN_GNAME: - /* This is done on the *module* (lower level) side. */ - if (tll == NULL) { - rc = EINVAL; - break; - } - if (mp->b_cont != NULL) - freemsg(mp->b_cont); - if ((mp->b_cont = allocb(sizeof (*ptn), BPRI_HI)) == NULL) { - rc = ENOSR; - break; - } - ptn = (union ppptun_name *)mp->b_cont->b_rptr; - bcopy(tll->tll_name, ptn->ptn_name, sizeof (ptn->ptn_name)); - len = sizeof (*ptn); - break; - case PPPTUN_SINFO: case PPPTUN_GINFO: /* Either side */ @@ -1197,7 +1192,8 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) } pti = (struct ppptun_info *)mp->b_cont->b_rptr; if (pti->pti_name[0] != '\0') - tll = tll_lookup_on_name(pti->pti_name); + tll = tll_lookup_on_name(pti->pti_name, + tcl == NULL ? tll->tll_zoneid : tcl->tcl_zoneid); if (tll == NULL) { /* Driver (client) side must have name */ if (tcl != NULL && pti->pti_name[0] == '\0') @@ -1246,11 +1242,15 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) rc = EINVAL; break; } + zoneid = tcl == NULL ? tll->tll_zoneid : tcl->tcl_zoneid; ptn = (union ppptun_name *)mp->b_cont->b_rptr; i = ptn->ptn_index; tll = TO_TLL(tunll_list.q_forw); - while (--i >= 0 && tll != TO_TLL(&tunll_list)) + while (tll != TO_TLL(&tunll_list)) { + if (tll->tll_zoneid == zoneid && --i < 0) + break; tll = TO_TLL(tll->tll_next); + } if (tll != TO_TLL(&tunll_list)) { bcopy(tll->tll_name, ptn->ptn_name, sizeof (ptn->ptn_name)); @@ -1384,7 +1384,7 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) } ptn = (union ppptun_name *)mp->b_cont->b_rptr; ptn->ptn_name[sizeof (ptn->ptn_name) - 1] = '\0'; - tll = tll_lookup_on_name(ptn->ptn_name); + tll = tll_lookup_on_name(ptn->ptn_name, tcl->tcl_zoneid); if (tll == NULL) { rc = ESRCH; break; @@ -1462,7 +1462,7 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) } ptn = (union ppptun_name *)mp->b_cont->b_rptr; ptn->ptn_name[sizeof (ptn->ptn_name) - 1] = '\0'; - tll = tll_lookup_on_name(ptn->ptn_name); + tll = tll_lookup_on_name(ptn->ptn_name, tcl->tcl_zoneid); if (tll == NULL || tll->tll_defcl != tcl) { rc = ESRCH; break; @@ -1470,6 +1470,17 @@ sppptun_inner_ioctl(queue_t *q, mblk_t *mp) tll->tll_defcl = NULL; break; + case PPPTUN_SSAP: + /* This is done on the *module* (lower level) side. */ + if (tll == NULL || mp->b_cont == NULL || + iop->ioc_count != sizeof (uint_t)) { + rc = EINVAL; + break; + } + + tll->tll_sap = *(uint_t *)mp->b_cont->b_rptr; + break; + default: /* Caller should already have checked command value */ ASSERT(0); @@ -1508,7 +1519,6 @@ sppptun_ioctl(queue_t *q, mblk_t *mp) case PPPIO_GETSTAT: case PPPIO_GETSTAT64: case PPPTUN_SNAME: - case PPPTUN_GNAME: case PPPTUN_SINFO: case PPPTUN_GINFO: case PPPTUN_GNNAME: @@ -1520,6 +1530,7 @@ sppptun_ioctl(queue_t *q, mblk_t *mp) case PPPTUN_SCTL: case PPPTUN_GCTL: case PPPTUN_DCTL: + case PPPTUN_SSAP: qwriter(q, mp, sppptun_inner_ioctl, PERIM_INNER); return; |