Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send a raw ethernet packet from inside a kernel module

I found out that I need to build a new sk_buff struct in the kernel module and pass it to my network device, but what I can't figure out is how to set the struct variables for a simple raw ethernet packet.

This has to be easy, but I would really appreciate it, if someone could give me a sample code of how to put the sk_buff together.

like image 466
Kai Avatar asked Dec 07 '09 17:12

Kai


People also ask

What is raw Ethernet packet?

A raw Ethernet packet is the complete Layer 2 network frame that is sent to the physical wire. Sending a frame like this allows you to manipulate the target and source MAC addresses and the Layer 3 protocol fields.

What is a raw packet?

Raw packet is used when you dont have any, the first bytes captured are directly the IPv6 or IPv4 header. Raw IP; the packet begins with an IPv4 or IPv6 header, with the "version" field of the header indicating whether it's an IPv4 or IPv6 header. From http://www.tcpdump.org/linktypes.html.

What is a raw socket connection?

A raw socket is a type of socket that allows access to the underlying transport provider. This topic focuses only on raw sockets and the IPv4 and IPv6 protocols. This is because most other protocols with the exception of ATM do not support raw sockets.

What is a raw socket in Linux?

Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers. The IPv4 layer generates an IP header when sending a packet unless the IP_HDRINCL socket option is enabled on the socket.


1 Answers

Take a look at the function packet_sendmsg_spkt in net/packet/af_packet.c for inspiration. The hard part is getting a struct sock if you don't have a socket...

Edit: Added a basic code shell:

int sendpacket(struct socket *sock, struct net_device *dev, __be16 proto, void *data, size_t len)
{
    struct sock *sk = sock->sk;
    struct sk_buff *skb;

    if (!(dev->flags & IFF_UP))
        return -ENETDOWN;

    if (len > dev->mtu + dev->hard_header_len)
        return -EMSGSIZE;

    skb = sock_wmalloc(sk, len + LL_RESERVED_SPACE(dev), 0, GFP_KERNEL);

    if (skb == NULL)
        return -ENOBUFS;

    /* FIXME: Save some space for broken drivers that write a
     * hard header at transmission time by themselves. PPP is the
     * notable one here. This should really be fixed at the driver level.
     */
    skb_reserve(skb, LL_RESERVED_SPACE(dev));
    skb_reset_network_header(skb);

    /* Try to align data part correctly */
    if (dev->header_ops) {
        skb->data -= dev->hard_header_len;
        skb->tail -= dev->hard_header_len;
        if (len < dev->hard_header_len)
            skb_reset_network_header(skb);
    }

    memcpy(skb_put(skb, len), data, len);
    skb->protocol = proto;
    skb->dev = dev;
    skb->priority = sk->sk_priority;

    dev_queue_xmit(skb);

    return len;
}
like image 141
caf Avatar answered Oct 27 '22 07:10

caf