LinuxQuestions.org
Latest LQ Deal: Linux Power User Bundle
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 10-20-2017, 12:28 AM   #1
915086731
Member
 
Registered: Apr 2010
Posts: 130
Blog Entries: 5

Rep: Reputation: 2
How to resolve the Mac address for an IP address under kernel module developing?


I want to build a tcp package in a kernel module and send it to another host by IP address using function dev_queue_xmit(skb). But I don't want to fill the Mac address manually by hand. The following is code for package producing.
I find some kernel kernel functions call eth_rebuild_header(skb) to rebuild Mac header. However, in my case, it hangs my computer after being called. Google give some answers that arp_find will crash the OS if the arp cache contains not entry for that IP address. But I'm sure the it exists in the arp cache as printed by shell command "arp -v".

Code:
static int build_and_xmit_tcp(char * eth, u_char * smac, u_char * dmac,
             u_long sip, u_long dip,
             u_short sport, u_short dport,
             u_char * pkt, int pkt_len,
             int syn, int ack, int fin,
             __be32 seq, __be32 seq_ack)
{
  struct sk_buff * skb = NULL;
  struct net_device * dev = NULL;
  struct ethhdr * ethdr = NULL;
  struct iphdr * iph = NULL;
  struct tcphdr * tcph = NULL;
  u_char * pdata = NULL;
  if(NULL == smac || NULL == dmac)
      goto out;

  if(NULL == (dev= dev_get_by_name(&init_net, eth)))
        goto out;
  skb = alloc_skb(pkt_len + sizeof(struct iphdr) + sizeof(struct tcphdr) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);

  if(NULL == skb)
      goto out;
  skb_reserve(skb, LL_RESERVED_SPACE(dev));

  skb->dev = dev;
  skb->pkt_type = PACKET_OTHERHOST;
  skb->protocol = __constant_htons(ETH_P_IP);
  skb->ip_summed = CHECKSUM_NONE;
  skb->priority = 0;
    skb_set_network_header(skb, 0);
  skb_put(skb, sizeof(struct iphdr));
 skb_set_transport_header(skb, sizeof(struct iphdr));
  skb_put(skb, sizeof(struct tcphdr));

  pdata = skb_put(skb, pkt_len); 
  {
     if(NULL != pkt)
        memcpy(pdata, pkt, pkt_len);
  }

  tcph = tcp_hdr(skb);
  memset(tcph, 0, sizeof(struct tcphdr));
  tcph->source = sport;
  tcph->dest = dport;
  tcph->doff=5;
  tcph->seq = htonl(seq);
  tcph-> ack_seq= htonl( seq_ack);
  tcph->psh = pkt_len>0? 1:0;
  tcph ->fin = fin;
  tcph->ack = ack;
  tcph->syn=syn;
  tcph->window=__constant_htons (65535);
  skb->csum = 0;
  tcph->check = 0;
  iph = ip_hdr(skb);
  iph->version = 4;
  iph->ihl = sizeof(struct iphdr)>>2;
  iph->frag_off = 0;
  iph->protocol = IPPROTO_TCP;
  iph->tos = 0;
  iph->daddr = dip;
  iph->saddr = sip;
  iph->ttl = 0x40;
  iph->tot_len = __constant_htons(skb->len);
  iph->check = 0;
  iph->check = ip_fast_csum((unsigned char *)iph,iph->ihl);

  skb->csum = skb_checksum(skb, iph->ihl*4, skb->len - iph->ihl * 4, 0);
  tcph->check = csum_tcpudp_magic(sip, dip, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);
  skb_push(skb, 14);
  skb_set_mac_header(skb, 0);
  ethdr = (struct ethhdr *)eth_hdr(skb);
//  memcpy(ethdr->h_dest, dmac, ETH_ALEN);
 // memcpy(ethdr->h_source, smac, ETH_ALEN);
  ethdr->h_proto = __constant_htons(ETH_P_IP);

//  arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
//       dst_ha, dev->dev_addr, NULL);
    eth_rebuild_header(skb);      // kernel hang....
  if(0 > dev_queue_xmit(skb)) {
        dev_put (dev);
        kfree_skb (skb);
  }
   return(NF_ACCEPT);

 out:
        dev_put (dev);
        kfree_skb (skb);
   return(NF_ACCEPT);
}


static int __init myhook_init(void)
{
   printk("=========insert module......\n");
   build_and_xmit_tcp(ETH_O, GWMAC_O, DMAC, in_aton(GWIP_O), in_aton(DIP), htons(8888), htons(DPORT), 
                    "", 0,
                    1, 0, 0, 0, 0);
}

static void __exit myhook_fini(void)
{
   printk("=========rmmod ......\n");
}

module_init(myhook_init);
module_exit(myhook_fini);

Google gives me some other solution. They say arp_ioctl can resolve the Mac address. However, the fact is that, arp_ioctl is compiled statically into vmlinuz, which is not exported as a symbol to other modules.


Code:
int arp_get(char *ifname, char *ipStr)
{
    struct arpreq req;  
    struct sockaddr_in *sin;  
    int ret = 0;  
    int sock_fd = 0;
    struct net_device * dev = NULL;
    printk("arp  ----  \n");
    if(NULL == (dev= dev_get_by_name(&init_net, ifname))){
        dev_put (dev);
        printk("error dev get \n");
        return -1;
    }
    struct net *net_arp = dev_net(dev);
    memset(&req, 0, sizeof(struct arpreq));  

    sin = (struct sockaddr_in *)&req.arp_pa;  
    sin->sin_family = AF_INET;  
    sin->sin_addr.s_addr = in_aton(ipStr);  


    strncpy(req.arp_dev, ifname, 15);
    ret = arp_ioctl(net_arp, SIOCGARP, &req);     // can't be called
    unsigned char *hw = (unsigned char *)req.arp_ha.sa_data;  
    printk("%#x-%#x-%#x-%#x-%#x-%#x\n", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
    return 0;
}
Maybe I need make a socket structure, and try some upper functions based on a socket. But how to do it...

kernel version : 2.6.32
os version: ubuntu 9.10
gcc version : 4.41

Last edited by 915086731; 10-20-2017 at 08:36 AM.
 
Old 10-21-2017, 09:43 AM   #2
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: CentOS 6 (pre-systemd)
Posts: 2,838

Rep: Reputation: 755Reputation: 755Reputation: 755Reputation: 755Reputation: 755Reputation: 755Reputation: 755
MAC addresses are layer 2. TCP is layer 3. It is unlikely that you can send a TCP packet to another system because TCP is a large and complex protocol which is based on creating and maintaining a connection. Maybe what you want to look at is a socket.
 
Old 10-29-2017, 10:55 PM   #3
915086731
Member
 
Registered: Apr 2010
Posts: 130
Blog Entries: 5

Original Poster
Rep: Reputation: 2
To try another way, I call the function "ip_route_input" get the route destination structure "dst_entry", but get error code -113 returned.
Function "ip_local_out"can deliver the skb out, but it need skb to provide struct "dst_entry" that is valid.
 
Old 10-31-2017, 01:49 AM   #4
915086731
Member
 
Registered: Apr 2010
Posts: 130
Blog Entries: 5

Original Poster
Rep: Reputation: 2
Code:
int ip_xmit(struct sk_buff *skb) 
{
    struct iphdr *iph = ip_hdr(skb);
    struct tcphdr *tcph = tcp_hdr(skb);
    printk("dst is %d\n", skb->_skb_dst);
    int err;
//    err = ip_route_input(skb, iph->daddr, iph->saddr, 0, skb->dev);

    struct rtalbe *rt;

    {
        struct flowi fl = { .oif = 0,
                    .nl_u = { .ip4_u =
                          { .daddr = iph->daddr,
                        .saddr = iph->saddr,
                        .tos = 0 } },
                    .proto = IPPROTO_TCP,
                    .flags = 0,
                    .uli_u = { .ports =
                           { .sport = tcph->source,
                         .dport = tcph->dest } } };

        if (err = ip_route_output_key(&init_net, &rt, &fl))
            return err;
            printk("err is %d\n", err);
    }
    skb_dst_set(skb, rt);
    if(0 > ip_local_out(skb)) {
        printk("dev error\n");
        kfree_skb (skb);
        return -1;
    }
    return 0;
}
function ip_route_output_key can obtain the route destination, and ip_local_out deliver the skb out.
 
  


Reply

Tags
arp, kernel 2.6.35, modules, netfilter, skbuff


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
using arp for converting ip address to mac address in kernel module programing in c karan2386 Linux - Kernel 1 03-31-2012 06:02 AM
[SOLVED] ARP does not resolve MAC address of hosts on the same subnet chenbo Linux - Networking 1 07-26-2011 11:12 PM
how to get ip address, broadcast address, mac address of a machine sumeshstar Programming 2 03-12-2005 05:33 AM
Resolve IP to MAC Address TheRealDeal Linux - General 1 12-03-2003 08:16 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 12:29 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration