【Linux网络内核】常用函数总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wr132/article/details/79113640

以下函数全部基于3.10.90版本的内核,对于更老或者更新的内核,可能会有所区别。

用于LOG输出的宏

  • LOG宏的使用方式与printk完全相同
  • 可以自定义tag,用于在dmesg输出的日志中过滤出属于本模块的信息
  • 可以通过debug宏控制是否输出日志,当关闭日志后,所有日志代码不会被编译
#define debug 1
#define MOD_TAG "custom tag"
#if debug
#define LOG(fmt, args...) \
do{\
    printk("[%s]:", MOD_TAG);\
    printk(fmt, ##args);\
    printk("\n");\
}while(0)
#else
#define LOG(msg)
#endif

获取sk_buff中的saddr和daddr

在获取IP的时候,一定要确定此时sk_buff中是存在IP的。
因为可能在很多函数中都会调用这个函数,为了区分调用者,增加了caller这个参数,可以传入一个字符串或者直接使用__FUNCTION__

static void show_skb_ip(struct sk_buff *skb, const char *caller)
{
    LOG("called by %s", caller);
    struct iphdr *iph = NULL;
    unsigned char *ip = NULL;
    iph = ip_hdr(skb);
    ip = (unsigned char*)&iph->daddr;
    LOG("daddr:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
    ip = (unsigned char*)&iph->saddr;
    LOG("saddr:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}

获取网卡设备的IP地址

static __be32 get_dev_addr(char *dev_name)
{
    struct net_device *net_dev;
    struct in_ifaddr *ifaddr;
    if(!dev_name)
        goto err_name_null;
    net_dev = dev_get_by_name(&init_net, dev_name);
    ifaddr = net_dev->ip_ptr->ifa_list;
    if(!ifaddr)
        goto err_ifaddr_null;
    LOG("%s %x", __FUNCTION__, ifaddr->ifa_local);
    return ifaddr->ifa_local;
err_name_null:
    LOG("device name is NULL");
    return 0;
err_ifaddr_null:
    LOG("ifaddr is NULL, maybe it has no ip address");
    return 0;
}

获取局域网其它设备的MAC地址

利用邻居子系统的arp_table查询其它设备的MAC地址,需要知道对方的IP地址,以及所查找设备所对应的网卡接口。

static char *get_neigh_ha(struct net_device *dev, __be32 ip)
{
    struct neighbour *neigh;
    if(!dev)
        goto err_no_such_dev;
    neigh = neigh_lookup(&arp_tbl, &ip, dev);
    if(!neigh)
        goto err_no_such_neigh;
    return neigh->ha;
err_no_such_dev:
    LOG("%s:no such device", __FUNCTION__);
    return NULL;
err_no_such_neigh:
    LOG("%s:no such neigh", __FUNCTION__);
    return NULL;
}

获取网卡当前的IP地址

static __be32 get_dev_addr(char *dev_name)
{
    struct net_device *net_dev;
    struct in_ifaddr *ifaddr;
    if(!dev_name)
        goto err_name_null;
    net_dev = dev_get_by_name(&init_net, dev_name);
    ifaddr = net_dev->ip_ptr->ifa_list;
    if(!ifaddr)
        goto err_ifaddr_null;
    LOG("%s %x", __FUNCTION__, ifaddr->ifa_local);
    return ifaddr->ifa_local;
err_name_null:
    LOG("device name is NULL");
    return 0;
err_ifaddr_null:
    LOG("ifaddr is NULL, maybe it has no ip address");
    return 0;
}

强制向局域网中的某台设备发送数据包,而忽略目的IP

static int dev_xmit(struct sk_buff *skb, char *dev_name, __be32 target_ip)
{
    int err;
    unsigned char *neigh_ha,
                  *local_ha;
    struct ethhdr *mac_h;
    struct net_device *dev;

    dev = dev_get_by_name(&init_net, dev_name);
    if(!dev)
        goto err_get_dev;

    neigh_ha = get_neigh_ha(dev, target_ip);
    if(!neigh_ha)
        goto err_get_neigh;
    show_ha("neighbor", neigh_ha);

    local_ha = dev->dev_addr;
    if(!local_ha)
        goto err_get_local;
    show_ha("local", dev->dev_addr);

    skb->dev = dev;
    skb->pkt_type = PACKET_OTHERHOST;
    skb->protocol = __constant_htons(ETH_P_IP);
    skb->ip_summed = CHECKSUM_UNNECESSARY;
    skb->priority = 0;

    show_skb_ip(skb, __FUNCTION__);

    skb_push(skb, sizeof(struct ethhdr));
    skb_reset_mac_header(skb);
    mac_h = eth_hdr(skb);

    memset(mac_h, 0, sizeof(struct ethhdr));
    mac_h->h_proto = __constant_htons(ETH_P_IP);
    memcpy(mac_h->h_source, local_ha, ETH_ALEN);
    memcpy(mac_h->h_dest, neigh_ha, ETH_ALEN);

    err = dev_queue_xmit(skb);
    if(err < 0)
        goto err_xmit;
    return 0;
err_get_dev:
    LOG("fail to get dev %s", dev_name);
    return -1;
err_get_neigh:
    LOG("fail to get neighbor %x 's mac address over %s", target_ip, dev_name);
    return -1;
err_get_local:
    LOG("fail to get local mac address");
    return -1;
err_xmit:
    LOG("fail to xmit skb");
    return -1;
}

猜你喜欢

转载自blog.csdn.net/wr132/article/details/79113640
今日推荐