4

I want to transmit an skb that contains a valid tcp and ip header in the linux kernel. It should go out a specific interface without being routed. My problem is, that I cannot use dev_queue_xmit because I dont know the destination mac-address. My attempts to find out the mac-address with arp_find failed:

...
mh = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
...
arp_find(mh->h_dest, skb); //this or the next line
val = dev_queue_xmit(skb); //crashes kernel

Experiments with ip_local_out also failed. I set the ip header information and call ip_local_out which also results in a kernel crash.

I could not use ip_queue_xmit because I was not able to find out, what data to provide in the struct flowi *fl field.

So my questions:

  • How can I send out an skb on a device with ip information and no knowledge about lower levels?
  • If there is no answer to the first question: How can I find out the destination mac/trigger an arp request for the destination ip?

Remark:

  • I would like to avoid using (raw) sockets.
  • I have successfully transmitted self-made skbs via dev_queue_xmit if I had the destination mac address. So the code building the skb is not an issue.
kaidowei
  • 105
  • 1
  • 9

2 Answers2

3

If you still want to use ip_local_out or ip_queue_xmit, then you can create your flowinfo like this.

struct flowi4 fl4 = {
    .flowi4_oif = skb->dev->ifindex,
    .daddr = iph->daddr,
    .saddr = iph->saddr,
};

then create dst(rtable) with

ip_route_output_key

set to skb_buff with

skb_dst_set
bummi
  • 27,123
  • 14
  • 62
  • 101
Hollando Romi
  • 144
  • 1
  • 1
  • 8
1

I think it's a cleaner solution to use socket programming in kernel to send it as RAW IP packet. You can create socket like this. sock_create_kern(&sk, AF_INET, SOCK_RAW, IPPROTO_RAW, net);

then call kernel_sendmsg

to let your packet going through the protocol stack.

Hollando Romi
  • 144
  • 1
  • 1
  • 8