本文整理汇总了C++中skb_copy_from_linear_data_offset函数的典型用法代码示例。如果您正苦于以下问题:C++ skb_copy_from_linear_data_offset函数的具体用法?C++ skb_copy_from_linear_data_offset怎么用?C++ skb_copy_from_linear_data_offset使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了skb_copy_from_linear_data_offset函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: br_nf_pre_routing_finish_bridge
/* Obtain the correct destination MAC address, while preserving the original
* source MAC address. If we already know this address, we just copy it. If we
* don't, we use the neighbour framework to find out. In both cases, we make
* sure that br_handle_frame_finish() is called afterwards.
*/
static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge = skb->nf_bridge;
struct neighbour *neigh;
struct dst_entry *dst;
skb->dev = bridge_parent(skb->dev);
if (!skb->dev)
goto free_skb;
dst = skb_dst(skb);
neigh = dst_get_neighbour(dst);
if (neigh->hh.hh_len) {
neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev;
return br_handle_frame_finish(skb);
} else {
/* the neighbour function below overwrites the complete
* MAC header, so we save the Ethernet source address and
* protocol number. */
skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN);
/* tell br_dev_xmit to continue with forwarding */
nf_bridge->mask |= BRNF_BRIDGED_DNAT;
return neigh->output(neigh, skb);
}
free_skb:
kfree_skb(skb);
return 0;
}
示例2: nf_bridge_save_header
static inline void nf_bridge_save_header(struct sk_buff *skb)
{
int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
skb_copy_from_linear_data_offset(skb, -header_size,
skb->nf_bridge->data, header_size);
}
示例3: b1dma_dispatch_tx
static void b1dma_dispatch_tx(avmcard *card)
{
avmcard_dmainfo *dma = card->dma;
struct sk_buff *skb;
u8 cmd, subcmd;
u16 len;
u32 txlen;
void *p;
skb = skb_dequeue(&dma->send_queue);
len = CAPIMSG_LEN(skb->data);
if (len) {
cmd = CAPIMSG_COMMAND(skb->data);
subcmd = CAPIMSG_SUBCOMMAND(skb->data);
p = dma->sendbuf.dmabuf;
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
u16 dlen = CAPIMSG_DATALEN(skb->data);
_put_byte(&p, SEND_DATA_B3_REQ);
_put_slice(&p, skb->data, len);
_put_slice(&p, skb->data + len, dlen);
} else {
_put_byte(&p, SEND_MESSAGE);
_put_slice(&p, skb->data, len);
}
txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
#ifdef AVM_B1DMA_DEBUG
printk(KERN_DEBUG "tx: put msg len=%d\n", txlen);
#endif
} else {
txlen = skb->len - 2;
#ifdef AVM_B1DMA_POLLDEBUG
if (skb->data[2] == SEND_POLLACK)
printk(KERN_INFO "%s: send ack\n", card->name);
#endif
#ifdef AVM_B1DMA_DEBUG
printk(KERN_DEBUG "tx: put 0x%x len=%d\n",
skb->data[2], txlen);
#endif
skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf,
skb->len - 2);
}
txlen = (txlen + 3) & ~3;
b1dma_writel(card, dma->sendbuf.dmaaddr, AMCC_TXPTR);
b1dma_writel(card, txlen, AMCC_TXLEN);
card->csr |= EN_TX_TC_INT;
dev_kfree_skb_any(skb);
}
示例4: build_inline_wqe
static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc,
const struct sk_buff *skb,
const struct skb_shared_info *shinfo,
void *fragptr)
{
struct mlx4_wqe_inline_seg *inl = &tx_desc->inl;
int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - sizeof(*inl);
unsigned int hlen = skb_headlen(skb);
if (skb->len <= spc) {
if (likely(skb->len >= MIN_PKT_LEN)) {
inl->byte_count = cpu_to_be32(1 << 31 | skb->len);
} else {
inl->byte_count = cpu_to_be32(1 << 31 | MIN_PKT_LEN);
memset(((void *)(inl + 1)) + skb->len, 0,
MIN_PKT_LEN - skb->len);
}
skb_copy_from_linear_data(skb, inl + 1, hlen);
if (shinfo->nr_frags)
memcpy(((void *)(inl + 1)) + hlen, fragptr,
skb_frag_size(&shinfo->frags[0]));
} else {
inl->byte_count = cpu_to_be32(1 << 31 | spc);
if (hlen <= spc) {
skb_copy_from_linear_data(skb, inl + 1, hlen);
if (hlen < spc) {
memcpy(((void *)(inl + 1)) + hlen,
fragptr, spc - hlen);
fragptr += spc - hlen;
}
inl = (void *) (inl + 1) + spc;
memcpy(((void *)(inl + 1)), fragptr, skb->len - spc);
} else {
skb_copy_from_linear_data(skb, inl + 1, spc);
inl = (void *) (inl + 1) + spc;
skb_copy_from_linear_data_offset(skb, spc, inl + 1,
hlen - spc);
if (shinfo->nr_frags)
memcpy(((void *)(inl + 1)) + hlen - spc,
fragptr,
skb_frag_size(&shinfo->frags[0]));
}
dma_wmb();
inl->byte_count = cpu_to_be32(1 << 31 | (skb->len - spc));
}
}
示例5: __nr_transmit_reply
/*
* This routine is called to send an error reply.
*/
void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags)
{
struct sk_buff *skbn;
unsigned char *dptr;
int len;
len = NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1;
if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL)
return;
skb_reserve(skbn, 0);
dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
skb_copy_from_linear_data_offset(skb, 7, dptr, AX25_ADDR_LEN);
dptr[6] &= ~AX25_CBIT;
dptr[6] &= ~AX25_EBIT;
dptr[6] |= AX25_SSSID_SPARE;
dptr += AX25_ADDR_LEN;
skb_copy_from_linear_data(skb, dptr, AX25_ADDR_LEN);
dptr[6] &= ~AX25_CBIT;
dptr[6] |= AX25_EBIT;
dptr[6] |= AX25_SSSID_SPARE;
dptr += AX25_ADDR_LEN;
*dptr++ = sysctl_netrom_network_ttl_initialiser;
if (mine) {
*dptr++ = 0;
*dptr++ = 0;
*dptr++ = skb->data[15];
*dptr++ = skb->data[16];
} else {
*dptr++ = skb->data[15];
*dptr++ = skb->data[16];
*dptr++ = 0;
*dptr++ = 0;
}
*dptr++ = cmdflags;
*dptr++ = 0;
if (!nr_route_frame(skbn, NULL))
kfree_skb(skbn);
}
示例6: build_inline_wqe
static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *skb,
int real_size, u16 *vlan_tag, int tx_ind, void *fragptr)
{
struct mlx4_wqe_inline_seg *inl = &tx_desc->inl;
int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - sizeof *inl;
if (skb->len <= spc) {
inl->byte_count = cpu_to_be32(1 << 31 | skb->len);
skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb));
if (skb_shinfo(skb)->nr_frags)
memcpy(((void *)(inl + 1)) + skb_headlen(skb), fragptr,
skb_frag_size(&skb_shinfo(skb)->frags[0]));
} else {
inl->byte_count = cpu_to_be32(1 << 31 | spc);
if (skb_headlen(skb) <= spc) {
skb_copy_from_linear_data(skb, inl + 1, skb_headlen(skb));
if (skb_headlen(skb) < spc) {
memcpy(((void *)(inl + 1)) + skb_headlen(skb),
fragptr, spc - skb_headlen(skb));
fragptr += spc - skb_headlen(skb);
}
inl = (void *) (inl + 1) + spc;
memcpy(((void *)(inl + 1)), fragptr, skb->len - spc);
} else {
skb_copy_from_linear_data(skb, inl + 1, spc);
inl = (void *) (inl + 1) + spc;
skb_copy_from_linear_data_offset(skb, spc, inl + 1,
skb_headlen(skb) - spc);
if (skb_shinfo(skb)->nr_frags)
memcpy(((void *)(inl + 1)) + skb_headlen(skb) - spc,
fragptr, skb_frag_size(&skb_shinfo(skb)->frags[0]));
}
wmb();
inl->byte_count = cpu_to_be32(1 << 31 | (skb->len - spc));
}
tx_desc->ctrl.vlan_tag = cpu_to_be16(*vlan_tag);
tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN *
(!!vlan_tx_tag_present(skb));
tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
}
示例7: dn_nsp_conn_conf
static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
{
struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct dn_scp *scp = DN_SK(sk);
unsigned char *ptr;
if (skb->len < 4)
goto out;
ptr = skb->data;
cb->services = *ptr++;
cb->info = *ptr++;
cb->segsize = le16_to_cpu(*(__le16 *)ptr);
if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
scp->persist = 0;
scp->addrrem = cb->src_port;
sk->sk_state = TCP_ESTABLISHED;
scp->state = DN_RUN;
scp->services_rem = cb->services;
scp->info_rem = cb->info;
scp->segsize_rem = cb->segsize;
if ((scp->services_rem & NSP_FC_MASK) == NSP_FC_NONE)
scp->max_window = decnet_no_fc_max_cwnd;
if (skb->len > 0) {
u16 dlen = *skb->data;
if ((dlen <= 16) && (dlen <= skb->len)) {
scp->conndata_in.opt_optl = cpu_to_le16(dlen);
skb_copy_from_linear_data_offset(skb, 1,
scp->conndata_in.opt_data, dlen);
}
}
dn_nsp_send_link(sk, DN_NOCHANGE, 0);
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
}
out:
kfree_skb(skb);
}
示例8: br_nf_pre_routing_finish_bridge
/* Obtain the correct destination MAC address, while preserving the original
* source MAC address. If we already know this address, we just copy it. If we
* don't, we use the neighbour framework to find out. In both cases, we make
* sure that br_handle_frame_finish() is called afterwards.
*/
int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct neighbour *neigh;
struct dst_entry *dst;
skb->dev = bridge_parent(skb->dev);
if (!skb->dev)
goto free_skb;
dst = skb_dst(skb);
neigh = dst_neigh_lookup_skb(dst, skb);
if (neigh) {
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
int ret;
if (neigh->hh.hh_len) {
neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev;
ret = br_handle_frame_finish(net, sk, skb);
} else {
/* the neighbour function below overwrites the complete
* MAC header, so we save the Ethernet source address and
* protocol number.
*/
skb_copy_from_linear_data_offset(skb,
-(ETH_HLEN-ETH_ALEN),
nf_bridge->neigh_header,
ETH_HLEN-ETH_ALEN);
/* tell br_dev_xmit to continue with forwarding */
nf_bridge->bridged_dnat = 1;
/* FIXME Need to refragment */
ret = neigh->output(neigh, skb);
}
neigh_release(neigh);
return ret;
}
free_skb:
kfree_skb(skb);
return 0;
}
示例9: br_nf_dev_queue_xmit
static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb)
{
int ret;
int frag_max_size;
unsigned int mtu_reserved;
if (skb_is_gso(skb) || skb->protocol != htons(ETH_P_IP))
return br_dev_queue_push_xmit(sk, skb);
mtu_reserved = nf_bridge_mtu_reduction(skb);
/* This is wrong! We should preserve the original fragment
* boundaries by preserving frag_list rather than refragmenting.
*/
if (skb->len + mtu_reserved > skb->dev->mtu) {
struct brnf_frag_data *data;
frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
if (br_parse_ip_options(skb))
/* Drop invalid packet */
return NF_DROP;
IPCB(skb)->frag_max_size = frag_max_size;
nf_bridge_update_protocol(skb);
data = this_cpu_ptr(&brnf_frag_data_storage);
data->encap_size = nf_bridge_encap_header_len(skb);
data->size = ETH_HLEN + data->encap_size;
skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
data->size);
ret = ip_fragment(sk, skb, br_nf_push_frag_xmit);
} else {
ret = br_dev_queue_push_xmit(sk, skb);
}
return ret;
}
示例10: capi_decode_conn_actv_ind
int capi_decode_conn_actv_ind(struct pcbit_chan *chan, struct sk_buff *skb)
{
ushort len;
#ifdef DEBUG
char str[32];
#endif
/* Yet Another Bearer Capability */
skb_pull(skb, *(skb->data) + 1);
/* Connected Party Number */
len = *(skb->data);
#ifdef DEBUG
if (len > 1 && len < 31) {
skb_copy_from_linear_data_offset(skb, 2, str, len - 1);
str[len] = 0;
printk(KERN_DEBUG "Connected Party Number: %s\n", str);
}
else
printk(KERN_DEBUG "actv_ind CPN len = %d\n", len);
#endif
skb_pull(skb, len + 1);
/* Connected Subaddress */
skb_pull(skb, *(skb->data) + 1);
/* Low Layer Capability */
skb_pull(skb, *(skb->data) + 1);
/* High Layer Capability */
skb_pull(skb, *(skb->data) + 1);
return 0;
}
示例11: skb_copy_from_linear_data_offset
struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
{
struct iphdr iph;
u32 len;
if (skb->protocol != htons(ETH_P_IP))
return skb;
#if 0
if (!skb_copy_bits(skb, 0, &iph, skb,sizeof(iph)))
return skb;
#else
skb_copy_from_linear_data_offset(skb,0,&iph,sizeof(iph));
#endif
if (iph.ihl < 5 || iph.version != 4)
return skb;
len = ntohs(iph.tot_len);
if (skb->len < len || len < (iph.ihl * 4))
return skb;
if (ip_is_fragment(&iph)) {
skb = skb_share_check(skb, GFP_ATOMIC);
if (skb) {
if (!pskb_may_pull(skb, iph.ihl*4))
return skb;
if (pskb_trim_rcsum(skb, len))
return skb;
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
if (ip_defrag(skb, user))
return NULL;
skb_clear_hash(skb);
}
}
return skb;
}
示例12: dn_nsp_disc_init
static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
{
struct dn_scp *scp = DN_SK(sk);
struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned short reason;
if (skb->len < 2)
goto out;
reason = le16_to_cpu(*(__le16 *)skb->data);
skb_pull(skb, 2);
scp->discdata_in.opt_status = cpu_to_le16(reason);
scp->discdata_in.opt_optl = 0;
memset(scp->discdata_in.opt_data, 0, 16);
if (skb->len > 0) {
u16 dlen = *skb->data;
if ((dlen <= 16) && (dlen <= skb->len)) {
scp->discdata_in.opt_optl = cpu_to_le16(dlen);
skb_copy_from_linear_data_offset(skb, 1, scp->discdata_in.opt_data, dlen);
}
}
scp->addrrem = cb->src_port;
sk->sk_state = TCP_CLOSE;
switch (scp->state) {
case DN_CI:
case DN_CD:
scp->state = DN_RJ;
sk->sk_err = ECONNREFUSED;
break;
case DN_RUN:
sk->sk_shutdown |= SHUTDOWN_MASK;
scp->state = DN_DN;
break;
case DN_DI:
scp->state = DN_DIC;
break;
}
if (!sock_flag(sk, SOCK_DEAD)) {
if (sk->sk_socket->state != SS_UNCONNECTED)
sk->sk_socket->state = SS_DISCONNECTING;
sk->sk_state_change(sk);
}
/*
* It appears that its possible for remote machines to send disc
* init messages with no port identifier if we are in the CI and
* possibly also the CD state. Obviously we shouldn't reply with
* a message if we don't know what the end point is.
*/
if (scp->addrrem) {
dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
}
scp->persist_fxn = dn_destroy_timer;
scp->persist = dn_nsp_persist(sk);
out:
kfree_skb(skb);
}
示例13: bgmac_dma_rx_read
static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
int weight)
{
u32 end_slot;
int handled = 0;
end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS);
end_slot &= BGMAC_DMA_RX_STATDPTR;
end_slot /= sizeof(struct bgmac_dma_desc);
ring->end = end_slot;
while (ring->start != ring->end) {
struct device *dma_dev = bgmac->core->dma_dev;
struct bgmac_slot_info *slot = &ring->slots[ring->start];
struct sk_buff *skb = slot->skb;
struct sk_buff *new_skb;
struct bgmac_rx_header *rx;
u16 len, flags;
/* Unmap buffer to make it accessible to the CPU */
dma_sync_single_for_cpu(dma_dev, slot->dma_addr,
BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
/* Get info from the header */
rx = (struct bgmac_rx_header *)skb->data;
len = le16_to_cpu(rx->len);
flags = le16_to_cpu(rx->flags);
/* Check for poison and drop or pass the packet */
if (len == 0xdead && flags == 0xbeef) {
bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
ring->start);
} else {
/* Omit CRC. */
len -= ETH_FCS_LEN;
new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len);
if (new_skb) {
skb_put(new_skb, len);
skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET,
new_skb->data,
len);
skb_checksum_none_assert(skb);
new_skb->protocol =
eth_type_trans(new_skb, bgmac->net_dev);
netif_receive_skb(new_skb);
handled++;
} else {
bgmac->net_dev->stats.rx_dropped++;
bgmac_err(bgmac, "Allocation of skb for copying packet failed!\n");
}
/* Poison the old skb */
rx->len = cpu_to_le16(0xdead);
rx->flags = cpu_to_le16(0xbeef);
}
/* Make it back accessible to the hardware */
dma_sync_single_for_device(dma_dev, slot->dma_addr,
BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
if (++ring->start >= BGMAC_RX_RING_SLOTS)
ring->start = 0;
if (handled >= weight) /* Should never be greater */
break;
}
return handled;
}
示例14: br_nf_dev_queue_xmit
static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge;
unsigned int mtu_reserved;
mtu_reserved = nf_bridge_mtu_reduction(skb);
if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) {
nf_bridge_info_free(skb);
return br_dev_queue_push_xmit(net, sk, skb);
}
nf_bridge = nf_bridge_info_get(skb);
/* This is wrong! We should preserve the original fragment
* boundaries by preserving frag_list rather than refragmenting.
*/
if (IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) &&
skb->protocol == htons(ETH_P_IP)) {
struct brnf_frag_data *data;
if (br_validate_ipv4(net, skb))
goto drop;
IPCB(skb)->frag_max_size = nf_bridge->frag_max_size;
nf_bridge_update_protocol(skb);
data = this_cpu_ptr(&brnf_frag_data_storage);
data->vlan_tci = skb->vlan_tci;
data->vlan_proto = skb->vlan_proto;
data->encap_size = nf_bridge_encap_header_len(skb);
data->size = ETH_HLEN + data->encap_size;
skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
data->size);
return br_nf_ip_fragment(net, sk, skb, br_nf_push_frag_xmit);
}
if (IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) &&
skb->protocol == htons(ETH_P_IPV6)) {
const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
struct brnf_frag_data *data;
if (br_validate_ipv6(net, skb))
goto drop;
IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size;
nf_bridge_update_protocol(skb);
data = this_cpu_ptr(&brnf_frag_data_storage);
data->encap_size = nf_bridge_encap_header_len(skb);
data->size = ETH_HLEN + data->encap_size;
skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
data->size);
if (v6ops)
return v6ops->fragment(net, sk, skb, br_nf_push_frag_xmit);
kfree_skb(skb);
return -EMSGSIZE;
}
nf_bridge_info_free(skb);
return br_dev_queue_push_xmit(net, sk, skb);
drop:
kfree_skb(skb);
return 0;
}
示例15: hostap_data_start_xmit
/* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta)
* Convert Ethernet header into a suitable IEEE 802.11 header depending on
* device configuration. */
netdev_tx_t hostap_data_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct hostap_interface *iface;
local_info_t *local;
int need_headroom, need_tailroom = 0;
struct ieee80211_hdr hdr;
u16 fc, ethertype = 0;
enum {
WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME
} use_wds = WDS_NO;
u8 *encaps_data;
int hdr_len, encaps_len, skip_header_bytes;
int to_assoc_ap = 0;
struct hostap_skb_tx_data *meta;
iface = netdev_priv(dev);
local = iface->local;
if (skb->len < ETH_HLEN) {
printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb "
"(len=%d)\n", dev->name, skb->len);
kfree_skb(skb);
return NETDEV_TX_OK;
}
if (local->ddev != dev) {
use_wds = (local->iw_mode == IW_MODE_MASTER &&
!(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ?
WDS_OWN_FRAME : WDS_COMPLIANT_FRAME;
if (dev == local->stadev) {
to_assoc_ap = 1;
use_wds = WDS_NO;
} else if (dev == local->apdev) {
printk(KERN_DEBUG "%s: prism2_tx: trying to use "
"AP device with Ethernet net dev\n", dev->name);
kfree_skb(skb);
return NETDEV_TX_OK;
}
} else {
if (local->iw_mode == IW_MODE_REPEAT) {
printk(KERN_DEBUG "%s: prism2_tx: trying to use "
"non-WDS link in Repeater mode\n", dev->name);
kfree_skb(skb);
return NETDEV_TX_OK;
} else if (local->iw_mode == IW_MODE_INFRA &&
(local->wds_type & HOSTAP_WDS_AP_CLIENT) &&
!ether_addr_equal(skb->data + ETH_ALEN, dev->dev_addr)) {
/* AP client mode: send frames with foreign src addr
* using 4-addr WDS frames */
use_wds = WDS_COMPLIANT_FRAME;
}
}
/* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload
* ==>
* Prism2 TX frame with 802.11 header:
* txdesc (address order depending on used mode; includes dst_addr and
* src_addr), possible encapsulation (RFC1042/Bridge-Tunnel;
* proto[2], payload {, possible addr4[6]} */
ethertype = (skb->data[12] << 8) | skb->data[13];
memset(&hdr, 0, sizeof(hdr));
/* Length of data after IEEE 802.11 header */
encaps_data = NULL;
encaps_len = 0;
skip_header_bytes = ETH_HLEN;
if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
encaps_data = bridge_tunnel_header;
encaps_len = sizeof(bridge_tunnel_header);
skip_header_bytes -= 2;
} else if (ethertype >= 0x600) {
encaps_data = rfc1042_header;
encaps_len = sizeof(rfc1042_header);
skip_header_bytes -= 2;
}
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
hdr_len = IEEE80211_DATA_HDR3_LEN;
if (use_wds != WDS_NO) {
/* Note! Prism2 station firmware has problems with sending real
* 802.11 frames with four addresses; until these problems can
* be fixed or worked around, 4-addr frames needed for WDS are
* using incompatible format: FromDS flag is not set and the
* fourth address is added after the frame payload; it is
* assumed, that the receiving station knows how to handle this
* frame format */
if (use_wds == WDS_COMPLIANT_FRAME) {
fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
/* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA,
* Addr4 = SA */
skb_copy_from_linear_data_offset(skb, ETH_ALEN,
&hdr.addr4, ETH_ALEN);
//.........这里部分代码省略.........