mblk_t * dls_header(dls_channel_t dc, const uint8_t *addr, uint16_t sap, uint_t pri, mblk_t *payload) { dls_impl_t *dip = (dls_impl_t *)dc; uint16_t vid; size_t extra_len; uint16_t mac_sap; mblk_t *mp; struct ether_vlan_header *evhp; vid = dip->di_dvp->dv_id; if (vid != VLAN_ID_NONE) { /* * We know ahead of time that we'll need to fill in * additional VLAN information in the link-layer header. * We will tell the MAC layer to pre-allocate some space at * the end of the Ethernet header for us. */ ASSERT(dip->di_mip->mi_media == DL_ETHER); extra_len = sizeof (struct ether_vlan_header) - sizeof (struct ether_header); mac_sap = VLAN_TPID; } else { extra_len = 0; mac_sap = sap; } mp = mac_header(dip->di_mh, addr, mac_sap, payload, extra_len); if (vid == VLAN_ID_NONE || mp == NULL) return (mp); /* This is an Ethernet VLAN link. Fill in the VLAN information */ ASSERT(MBLKL(mp) == sizeof (struct ether_header)); mp->b_wptr += extra_len; evhp = (struct ether_vlan_header *)mp->b_rptr; evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid)); evhp->ether_type = htons(sap); return (mp); }
/* ARGSUSED */ static int sdpfp_senduio(sock_lower_handle_t handle, struct uio *uiop, struct nmsghdr *msg, struct cred *cred) { struct sockaddr_ll *sol; mac_client_handle_t mch; struct pfpsock *ps; boolean_t new_open; mac_handle_t mh; size_t mpsize; uint_t maxsdu; mblk_t *mp0; mblk_t *mp; int error; mp = NULL; mp0 = NULL; new_open = B_FALSE; ps = (struct pfpsock *)handle; mh = ps->ps_mh; mch = ps->ps_mch; maxsdu = ps->ps_max_sdu; sol = (struct sockaddr_ll *)msg->msg_name; if (sol == NULL) { /* * If no sockaddr_ll has been provided with the send call, * use the one constructed when the socket was bound to an * interface and fail if it hasn't been bound. */ if (!ps->ps_bound) { ks_stats.kp_send_unbound.value.ui64++; return (EPROTO); } sol = (struct sockaddr_ll *)&ps->ps_sock; } else { /* * Verify the sockaddr_ll message passed down before using * it to send a packet out with. If it refers to an interface * that has not been bound, it is necessary to open it. */ struct sockaddr_ll *sll; if (msg->msg_namelen < sizeof (struct sockaddr_ll)) { ks_stats.kp_send_short_msg.value.ui64++; return (EINVAL); } if (sol->sll_family != AF_PACKET) { ks_stats.kp_send_wrong_family.value.ui64++; return (EAFNOSUPPORT); } sll = (struct sockaddr_ll *)&ps->ps_sock; if (sol->sll_ifindex != sll->sll_ifindex) { error = pfp_open_index(sol->sll_ifindex, &mh, &mch, cred); if (error != 0) { ks_stats.kp_send_open_fail.value.ui64++; return (error); } mac_sdu_get(mh, NULL, &maxsdu); new_open = B_TRUE; } } mpsize = uiop->uio_resid; if (mpsize > maxsdu) { ks_stats.kp_send_too_big.value.ui64++; error = EMSGSIZE; goto done; } if ((mp = allocb(mpsize, BPRI_HI)) == NULL) { ks_stats.kp_send_alloc_fail.value.ui64++; error = ENOBUFS; goto done; } mp->b_wptr = mp->b_rptr + mpsize; error = uiomove(mp->b_rptr, mpsize, UIO_WRITE, uiop); if (error != 0) { ks_stats.kp_send_uiomove_fail.value.ui64++; goto done; } if (ps->ps_type == SOCK_DGRAM) { mp0 = mac_header(mh, sol->sll_addr, sol->sll_protocol, mp, 0); if (mp0 == NULL) { ks_stats.kp_send_no_memory.value.ui64++; error = ENOBUFS; goto done; } linkb(mp0, mp); mp = mp0; } /* * As this is sending datagrams and no promise is made about * how or if a packet will be sent/delivered, no effort is to * be expended in recovering from a situation where the packet * cannot be sent - it is just dropped. */ error = mac_tx(mch, mp, 0, MAC_DROP_ON_NO_DESC, NULL); if (error == 0) { mp = NULL; ks_stats.kp_send_ok.value.ui64++; } else { ks_stats.kp_send_failed.value.ui64++; } done: if (new_open) { ASSERT(mch != ps->ps_mch); ASSERT(mh != ps->ps_mh); pfp_close(mh, mch); } if (mp != NULL) freemsg(mp); return (error); }