利用net_device取本机ip地址 + 网络设备的IP地址结构

网络设备的IP地址结构
====================

(1) 在TCPIP协议环境下, 网络设备结构(net_device)具有一个ip_ptr指针指向IP协议的设备参数块(in_device), 它包含设备IP地址结构(in_ifaddr)的链表指针(ifa_list). IP地址结构链可以为一个网络设备配置多个IP地址, 使得局域网中的单台主机能模拟多台主机的作用.

(2) 设备IP地址的配置由应用程序通过ioctl()系统调用使用ifreq参数结构来完成. 同一设备的不同IP地址用不同的设备别名来标识, 例如"eth0:1"和"eth0:2"分别代表设备eht0的两个地址. 当增加一个别名设备时, 如果它的地址与已有地址属于同一子网, 则它的地址被标记为"从属"(IFA_F_SECONDARY). 当设备最后一个别名被删除时, 设备的IP参数块将被释放.设备地址参数发生改变时, 将通过地址消息链(inetaddr_chain)向有关子系统发送通知消息, 例如路由子系统用来刷新转发表和路由缓冲表.

struct net_device
{
...
void *ip_ptr; /* IPv4 specific data */ 
...
}
struct in_device
{
struct net_device *dev;
atomic_t refcnt;
rwlock_t lock;
int dead;
struct in_ifaddr *ifa_list; /* IP ifaddr chain */
struct ip_mc_list *mc_list; /* IP multicast filter chain    */
unsigned long mr_v1_seen;
struct neigh_parms *arp_parms;
struct ipv4_devconf cnf;
};
struct in_ifaddr
{
struct in_ifaddr *ifa_next;
struct in_device *ifa_dev;
u32 ifa_local; 设备地址
u32 ifa_address; 点对点设备的对端地址
u32 ifa_mask; 网络地址掩码
u32 ifa_broadcast; 设备的广播地址
u32 ifa_anycast;
unsigned char ifa_scope; 设备地址的寻址范围
unsigned char ifa_flags; 地址标志
unsigned char ifa_prefixlen; 设备网络地址长度
char ifa_label[IFNAMSIZ]; 设备IP地址标签
};

/*
* Interface request structure used for socket
* ioctl's.  All interface ioctl's must have parameter
* definitions which begin with ifr_name.  The
* remainder may be interface specific.
*/

struct ifreq
{
#define IFHWADDRLEN 6
#define IFNAMSIZ 16
union
{
char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
} ifr_ifrn;

union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct  sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct  ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
char * ifru_data;
} ifr_ifru;
};

; net/ipv4/devinet.c:

int devinet_ioctl(unsigned int cmd, void *arg)
{
struct ifreq ifr;
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
struct in_device *in_dev;
struct in_ifaddr **ifap = NULL;
struct in_ifaddr *ifa = NULL;
struct net_device *dev;
char *colon;
int ret = 0;

/*
* Fetch the caller's info block into kernel space
*/

if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
ifr.ifr_name[IFNAMSIZ-1] = 0;

colon = strchr(ifr.ifr_name, ':'); 从设备地址标签中取设备名称
if (colon)
*colon = 0;

#ifdef CONFIG_KMOD
dev_load(ifr.ifr_name); 加载相应名称的设备驱动模块
#endif

switch(cmd) {
case SIOCGIFADDR: /* Get interface address */
case SIOCGIFBRDADDR: /* Get the broadcast address */
case SIOCGIFDSTADDR: /* Get the destination address */
case SIOCGIFNETMASK: /* Get the netmask for the interface */
/* Note that this ioctls will not sleep,
   so that we do not impose a lock.
   One day we will be forced to put shlock here (I mean SMP)
*/
memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
break;

case SIOCSIFFLAGS:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
break;
case SIOCSIFADDR: /* Set interface address (and family) */
case SIOCSIFBRDADDR: /* Set the broadcast address */
case SIOCSIFDSTADDR: /* Set the destination address */
case SIOCSIFNETMASK: /* Set the netmask for the interface */
if (!capable(CAP_NET_ADMIN))
return -EACCES;
if (sin->sin_family != AF_INET)
return -EINVAL;
break;
default:
return -EINVAL;
}

dev_probe_lock();
rtnl_lock();

if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL) { 取设备结构
ret = -ENODEV;
goto done;
}

if (colon)
*colon = ':'; 恢复用户地址标签

if ((in_dev=__in_dev_get(dev)) != NULL) { 取IP设备块
for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0)
break; 取用户地址标签对应的设备地址结构
}

if (ifa == NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) { 除了设置地址和设置标志
ret = -EADDRNOTAVAIL;
goto done;
}

switch(cmd) {
case SIOCGIFADDR: /* Get interface address */
sin->sin_addr.s_addr = ifa->ifa_local; 取设备IP地址
goto rarok;

case SIOCGIFBRDADDR: /* Get the broadcast address */
sin->sin_addr.s_addr = ifa->ifa_broadcast; 取设备IP广播地址
goto rarok;

case SIOCGIFDSTADDR: /* Get the destination address */
sin->sin_addr.s_addr = ifa->ifa_address; 取点对点设备的对端IP地址
goto rarok;

case SIOCGIFNETMASK: /* Get the netmask for the interface */
sin->sin_addr.s_addr = ifa->ifa_mask; 取设备的IP地址掩码
goto rarok;

case SIOCSIFFLAGS: 设置设备标志
if (colon) {
if (ifa == NULL) {
ret = -EADDRNOTAVAIL;
break;
}
if (!(ifr.ifr_flags&IFF_UP)) 如果标志为关闭设备
inet_del_ifa(in_dev, ifap, 1); 破环性删除该地址结构
break;
}
ret = dev_change_flags(dev, ifr.ifr_flags);
break;

case SIOCSIFADDR: /* Set interface address (and family) */
if (inet_abc_len(sin->sin_addr.s_addr) < 0) { 取网络地址位长
ret = -EINVAL;
break;
}

if (!ifa) { 如果设备尚无地址结构
if ((ifa = inet_alloc_ifa()) == NULL) { 分配地址结构
ret = -ENOBUFS;
break;
}
if (colon) 如果地址标签为设备别名标签
memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
else
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
} else {  如果修改设备地址
ret = 0;
if (ifa->ifa_local == sin->sin_addr.s_addr)
break;
inet_del_ifa(in_dev, ifap, 0); 从链接中删除该地址结构
ifa->ifa_broadcast = 0;
ifa->ifa_anycast = 0;
}

ifa->ifa_address =
ifa->ifa_local = sin->sin_addr.s_addr; 将设备地址和对端地址设置为新地址

if (!(dev->flags&IFF_POINTOPOINT)) { 如果非点对点设备
ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address); 取地址的网络地址长度
ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen); 求网络掩码
if ((dev->flags&IFF_BROADCAST) && ifa->ifa_prefixlen < 31)
ifa->ifa_broadcast = ifa->ifa_address|~ifa->ifa_mask; 设置标准广播地址
} else {  如果是点对点设备
ifa->ifa_prefixlen = 32; 网络地址长度为32
ifa->ifa_mask = inet_make_mask(32);
}
ret = inet_set_ifa(dev, ifa); 添加设备地址
break;

case SIOCSIFBRDADDR: /* Set the broadcast address */
if (ifa->ifa_broadcast != sin->sin_addr.s_addr) {
inet_del_ifa(in_dev, ifap, 0);
ifa->ifa_broadcast = sin->sin_addr.s_addr;
inet_insert_ifa(ifa);
}
break;

case SIOCSIFDSTADDR: /* Set the destination address */
if (ifa->ifa_address != sin->sin_addr.s_addr) {
if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
ret = -EINVAL;
break;
}
inet_del_ifa(in_dev, ifap, 0);
ifa->ifa_address = sin->sin_addr.s_addr;
inet_insert_ifa(ifa);
}
break;

case SIOCSIFNETMASK: /* Set the netmask for the interface */

/*
* The mask we set must be legal.
*/
if (bad_mask(sin->sin_addr.s_addr, 0)) {
ret = -EINVAL;
break;
}

if (ifa->ifa_mask != sin->sin_addr.s_addr) {
inet_del_ifa(in_dev, ifap, 0);
ifa->ifa_mask = sin->sin_addr.s_addr;
ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
inet_insert_ifa(ifa);
}
break;
}
done:
rtnl_unlock();
dev_probe_unlock();
return ret;

rarok:
rtnl_unlock();
dev_probe_unlock();
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
return -EFAULT;
return 0;
}
static int
inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
{
struct in_device *in_dev = __in_dev_get(dev);

ASSERT_RTNL();

if (in_dev == NULL) { 如果IP设备块不存在
in_dev = inetdev_init(dev); 分配IP设备块
if (in_dev == NULL) {
inet_free_ifa(ifa);
return -ENOBUFS;
}
}
if (ifa->ifa_dev != in_dev) {
BUG_TRAP(ifa->ifa_dev==NULL);
in_dev_hold(in_dev);
ifa->ifa_dev=in_dev; 将地址结构绑定到IP设备块上
}
if (LOOPBACK(ifa->ifa_local)) 如果设备地址是回送地址
ifa->ifa_scope = RT_SCOPE_HOST; 地址的寻址范围为主机内部
return inet_insert_ifa(ifa);
}
static int
inet_insert_ifa(struct in_ifaddr *ifa)
{
struct in_device *in_dev = ifa->ifa_dev;
struct in_ifaddr *ifa1, **ifap, **last_primary;

ASSERT_RTNL();

if (ifa->ifa_local == 0) {
inet_free_ifa(ifa);
return 0;
}

ifa->ifa_flags &= ~IFA_F_SECONDARY; 清除地址结构的从属标志
last_primary = &in_dev->ifa_list; 取IP设备块地址链表指针地址

for (ifap=&in_dev->ifa_list; (ifa1=*ifap)!=NULL; ifap=&ifa1->ifa_next) { 扫描IP设备块上的地址链
if (!(ifa1->ifa_flags&IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope)
last_primary = &ifa1->ifa_next;
if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) {
; 如果与链中某个地址具有相同的网络地址
if (ifa1->ifa_local == ifa->ifa_local) { 如果两者地址相同
inet_free_ifa(ifa);
return -EEXIST;
}
if (ifa1->ifa_scope != ifa->ifa_scope) { 如果两者寻址范围不同
inet_free_ifa(ifa);
return -EINVAL;
}
ifa->ifa_flags |= IFA_F_SECONDARY; 标记为从属地址
}
}

if (!(ifa->ifa_flags&IFA_F_SECONDARY)) {
net_srandom(ifa->ifa_local);
ifap = last_primary;
}

ifa->ifa_next = *ifap;
write_lock_bh(&in_dev->lock);
*ifap = ifa;
write_unlock_bh(&in_dev->lock);

/* Send message first, then call notifier.
   Notifier will trigger FIB update, so that
   listeners of netlink will know about new ifaddr */
rtmsg_ifa(RTM_NEWADDR, ifa);
notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); 发布设备启动消息

return 0;
}
static void
inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy)
{
struct in_ifaddr *ifa1 = *ifap; 取要删除地址结构的地址

ASSERT_RTNL();

/* 1. Deleting primary ifaddr forces deletion all secondaries */

if (!(ifa1->ifa_flags&IFA_F_SECONDARY)) { 如果删除的是设备主地址结构
struct in_ifaddr *ifa;
struct in_ifaddr **ifap1 = &ifa1->ifa_next; 取下一地址指针的地址

while ((ifa=*ifap1) != NULL) {
if (!(ifa->ifa_flags&IFA_F_SECONDARY) || 如果为主地址
    ifa1->ifa_mask != ifa->ifa_mask ||
    !inet_ifa_match(ifa1->ifa_address, ifa)) {
ifap1 = &ifa->ifa_next;
continue;
}
write_lock_bh(&in_dev->lock);
*ifap1 = ifa->ifa_next;
write_unlock_bh(&in_dev->lock);

rtmsg_ifa(RTM_DELADDR, ifa);
notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); 发布设备停机消息
inet_free_ifa(ifa);
}
}

/* 2. Unlink it */

write_lock_bh(&in_dev->lock);
*ifap = ifa1->ifa_next; 从设备地址链中删除该地址标签
write_unlock_bh(&in_dev->lock);

/* 3. Announce address deletion */

/* Send message first, then call notifier.
   At first sight, FIB update triggered by notifier
   will refer to already deleted ifaddr, that could confuse
   netlink listeners. It is not true: look, gated sees
   that route deleted and if it still thinks that ifaddr
   is valid, it will try to restore deleted routes... Grr.
   So that, this order is correct.
*/
rtmsg_ifa(RTM_DELADDR, ifa1);
notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
inet_free_ifa(ifa1);

if (in_dev->ifa_list == NULL)
inetdev_destroy(in_dev);
}
}
static void inetdev_destroy(struct in_device *in_dev)
{
struct in_ifaddr *ifa;

ASSERT_RTNL();

in_dev->dead = 1;

ip_mc_destroy_dev(in_dev);

while ((ifa = in_dev->ifa_list) != NULL) {
inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
inet_free_ifa(ifa);
}

#ifdef CONFIG_SYSCTL
devinet_sysctl_unregister(&in_dev->cnf);
#endif
write_lock_bh(&inetdev_lock);
in_dev->dev->ip_ptr = NULL;
/* in_dev_put following below will kill the in_device */
write_unlock_bh(&inetdev_lock);


neigh_parms_release(&arp_tbl, in_dev->arp_parms);
in_dev_put(in_dev);
}
struct in_device *inetdev_init(struct net_device *dev)
{
struct in_device *in_dev;

ASSERT_RTNL();

in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
if (!in_dev)
return NULL;
memset(in_dev, 0, sizeof(*in_dev));
in_dev->lock = RW_LOCK_UNLOCKED;
memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
in_dev->cnf.sysctl = NULL;
in_dev->dev = dev;
if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) {
kfree(in_dev);
return NULL;
}
inet_dev_count++;
/* Reference in_dev->dev */
dev_hold(dev);
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
#endif
write_lock_bh(&inetdev_lock);
dev->ip_ptr = in_dev;
/* Account for reference dev->ip_ptr */
in_dev_hold(in_dev);
write_unlock_bh(&inetdev_lock);
#ifdef CONFIG_SYSCTL
devinet_sysctl_register(in_dev, &in_dev->cnf);
#endif
if (dev->flags&IFF_UP)
ip_mc_up(in_dev);
return in_dev;
}
static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
{
if (ifa->ifa_dev)
__in_dev_put(ifa->ifa_dev);
kfree(ifa);
inet_ifa_count--;
}
static struct in_ifaddr * inet_alloc_ifa(void)
{
struct in_ifaddr *ifa;

ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
if (ifa) {
memset(ifa, 0, sizeof(*ifa));
inet_ifa_count++;
}

return ifa;
}
extern __inline__ struct in_device *
in_dev_get(const struct net_device *dev)
{
struct in_device *in_dev;

read_lock(&inetdev_lock);
in_dev = dev->ip_ptr;
if (in_dev)
atomic_inc(&in_dev->refcnt);
read_unlock(&inetdev_lock);
return in_dev;
}

extern __inline__ struct in_device *
__in_dev_get(const struct net_device *dev)
{
return (struct in_device*)dev->ip_ptr;
}

extern __inline__ void
in_dev_put(struct in_device *idev)
{
if (atomic_dec_and_test(&idev->refcnt))
in_dev_finish_destroy(idev);
}
void in_dev_finish_destroy(struct in_device *idev)
{
struct net_device *dev = idev->dev;

BUG_TRAP(idev->ifa_list==NULL);
BUG_TRAP(idev->mc_list==NULL);
#ifdef NET_REFCNT_DEBUG
printk(KERN_DEBUG "in_dev_finish_destroy: %p=%s/n", idev, dev ? dev->name : "NIL");
#endif
dev_put(dev);
if (!idev->dead) {
printk("Freeing alive in_device %p/n", idev);
return;
}
inet_dev_count--;
kfree(idev);
}

 

 

=============================================================================

=============================================================================

利用net_device取本机ip地址
2007-10-11 16:08:00
linux/netdevice.h

struct net_device
{

    /*
     * This is the first field of the "visible" part of this structure
     * (i.e. as seen by users in the "Space.c" file).  It is the name
     * the interface.
     */
    char            name[IFNAMSIZ];

    /*
     *    I/O specific fields
     *    FIXME: Merge these and struct ifmap into one
     */
    unsigned long        mem_end;    /* shared mem end    */
    unsigned long        mem_start;    /* shared mem start    */
    unsigned long        base_addr;    /* device I/O address    */
    unsigned int        irq;        /* device IRQ number    */

    /*
     *    Some hardware also needs these fields, but they are not
     *    part of the usual set specified in Space.c.
     */

    unsigned char        if_port;    /* Selectable AUI, TP,..*/
    unsigned char        dma;        /* DMA channel        */

    unsigned long        state;

    struct net_device    *next;
   
    /* The device initialization function. Called only once. */
    int            (*init)(struct net_device *dev);

    /* ------- Fields preinitialized in Space.c finish here ------- */

    struct net_device    *next_sched;

    /* Interface index. Unique device identifier    */
    int            ifindex;
    int            iflink;


    struct net_device_stats* (*get_stats)(struct net_device *dev);
    struct iw_statistics*    (*get_wireless_stats)(struct net_device *dev);

    /* List of functions to handle Wireless Extensions (instead of ioctl).
     * See <net/iw_handler.h> for details. Jean II */
    const struct iw_handler_def *    wireless_handlers;
    /* Instance data managed by the core of Wireless Extensions. */
    struct iw_public_data *    wireless_data;

    struct ethtool_ops *ethtool_ops;

    /*
     * This marks the end of the "visible" part of the structure. All
     * fields hereafter are internal to the system, and may change at
     * will (read: may be cleaned up at will).
     */

    /* These may be needed for future network-power-down code. */
    unsigned long        trans_start;    /* Time (in jiffies) of last Tx    */
    unsigned long        last_rx;    /* Time of last Rx    */

    unsigned short        flags;    /* interface flags (a la BSD)    */
    unsigned short        gflags;
        unsigned short          priv_flags; /* Like 'flags' but invisible to userspace. */
        unsigned short          unused_alignment_fixer; /* Because we need priv_flags,
                                                         * and we want to be 32-bit aligned.
                                                         */

    unsigned        mtu;    /* interface MTU value        */
    unsigned short        type;    /* interface hardware type    */
    unsigned short        hard_header_len;    /* hardware hdr length    */
    void            *priv;    /* pointer to private data    */

    struct net_device    *master; /* Pointer to master device of a group,
                      * which this device is member of.
                      */

    /* Interface address info. */
    unsigned char        broadcast[MAX_ADDR_LEN];    /* hw bcast add    */
    unsigned char        dev_addr[MAX_ADDR_LEN];    /* hw address    */
    unsigned char        addr_len;    /* hardware address length    */
    unsigned short          dev_id;        /* for shared network cards */

    struct dev_mc_list    *mc_list;    /* Multicast mac addresses    */
    int            mc_count;    /* Number of installed mcasts    */
    int            promiscuity;
    int            allmulti;

    int            watchdog_timeo;
    struct timer_list    watchdog_timer;

    /* Protocol specific pointers */
   
    void             *atalk_ptr;    /* AppleTalk link     */
    void            *ip_ptr;    /* IPv4 specific data    */ 
    void                    *dn_ptr;        /* DECnet specific data */
    void                    *ip6_ptr;       /* IPv6 specific data */
    void            *ec_ptr;    /* Econet specific data    */
    void            *ax25_ptr;    /* AX.25 specific data */

    struct list_head    poll_list;    /* Link to poll list    */
    int            quota;
    int            weight;

    struct Qdisc        *qdisc;
    struct Qdisc        *qdisc_sleeping;
    struct Qdisc        *qdisc_ingress;
    struct list_head    qdisc_list;
    unsigned long        tx_queue_len;    /* Max frames per queue allowed */

    /* ingress path synchronizer */
    spinlock_t        ingress_lock;
    /* hard_start_xmit synchronizer */
    spinlock_t        xmit_lock;
    /* cpu id of processor entered to hard_start_xmit or -1,
       if nobody entered there.
     */
    int            xmit_lock_owner;
    /* device queue lock */
    spinlock_t        queue_lock;
    /* Number of references to this device */
    atomic_t        refcnt;
    /* delayed register/unregister */
    struct list_head    todo_list;
    /* device name hash chain */
    struct hlist_node    name_hlist;
    /* device index hash chain */
    struct hlist_node    index_hlist;

    /* register/unregister state machine */
    enum { NETREG_UNINITIALIZED=0,
           NETREG_REGISTERING,    /* called register_netdevice */
           NETREG_REGISTERED,    /* completed register todo */
           NETREG_UNREGISTERING,    /* called unregister_netdevice */
           NETREG_UNREGISTERED,    /* completed unregister todo */
           NETREG_RELEASED,        /* called free_netdev */
    } reg_state;

    /* Net device features */
    int            features;
#define NETIF_F_SG        1    /* Scatter/gather IO. */
#define NETIF_F_IP_CSUM        2    /* Can checksum only TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM        4    /* Does not require checksum. F.e. loopack. */
#define NETIF_F_HW_CSUM        8    /* Can checksum all the packets. */
#define NETIF_F_HIGHDMA        32    /* Can DMA to high memory. */
#define NETIF_F_FRAGLIST    64    /* Scatter/gather IO. */
#define NETIF_F_HW_VLAN_TX    128    /* Transmit VLAN hw acceleration */
#define NETIF_F_HW_VLAN_RX    256    /* Receive VLAN hw acceleration */
#define NETIF_F_HW_VLAN_FILTER    512    /* Receive filtering on VLAN */
#define NETIF_F_VLAN_CHALLENGED    1024    /* Device cannot handle VLAN packets */
#define NETIF_F_TSO        2048    /* Can offload TCP/IP segmentation */
#define NETIF_F_LLTX        4096    /* LockLess TX */

    /* Called after device is detached from network. */
    void            (*uninit)(struct net_device *dev);
    /* Called after last user reference disappears. */
    void            (*destructor)(struct net_device *dev);

    /* Pointers to interface service routines.    */
    int            (*open)(struct net_device *dev);
    int            (*stop)(struct net_device *dev);
    int            (*hard_start_xmit) (struct sk_buff *skb,
                            struct net_device *dev);
#define HAVE_NETDEV_POLL
    int            (*poll) (struct net_device *dev, int *quota);
    int            (*hard_header) (struct sk_buff *skb,
                        struct net_device *dev,
                        unsigned short type,
                        void *daddr,
                        void *saddr,
                        unsigned len);
    int            (*rebuild_header)(struct sk_buff *skb);
#define HAVE_MULTICAST             
    void            (*set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR           
    int            (*set_mac_address)(struct net_device *dev,
                           void *addr);
#define HAVE_PRIVATE_IOCTL
    int            (*do_ioctl)(struct net_device *dev,
                        struct ifreq *ifr, int cmd);
#define HAVE_SET_CONFIG
    int            (*set_config)(struct net_device *dev,
                          struct ifmap *map);
#define HAVE_HEADER_CACHE
    int            (*hard_header_cache)(struct neighbour *neigh,
                             struct hh_cache *hh);
    void            (*header_cache_update)(struct hh_cache *hh,
                               struct net_device *dev,
                               unsigned char *  haddr);
#define HAVE_CHANGE_MTU
    int            (*change_mtu)(struct net_device *dev, int new_mtu);

#define HAVE_TX_TIMEOUT
    void            (*tx_timeout) (struct net_device *dev);

    void            (*vlan_rx_register)(struct net_device *dev,
                            struct vlan_group *grp);
    void            (*vlan_rx_add_vid)(struct net_device *dev,
                           unsigned short vid);
    void            (*vlan_rx_kill_vid)(struct net_device *dev,
                            unsigned short vid);

    int            (*hard_header_parse)(struct sk_buff *skb,
                             unsigned char *haddr);
    int            (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
    int            (*accept_fastpath)(struct net_device *, struct dst_entry*);
#ifdef CONFIG_NETPOLL
    int            netpoll_rx;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
    void                    (*poll_controller)(struct net_device *dev);
#endif

    /* bridge stuff */
    struct net_bridge_port    *br_port;

#ifdef CONFIG_NET_DIVERT
    /* this will get initialized at each interface type init routine */
    struct divert_blk    *divert;
#endif /* CONFIG_NET_DIVERT */

    /* class/net/name entry */
    struct class_device    class_dev;
    /* how much padding had been added by alloc_netdev() */
    int padded;
};


利用其ip_ptr指针,该指针指向in_device结构(在上文中以作介绍)
       
        //测试读取本机ip的代码
        struct in_device *ipout=out->ip_ptr;
        printk("ip is %i/n",ipout->ifa_list->ifa_address);
        printk("ip is %i/n",(*skb)->nh.iph->saddr);
        **************/

通过上面一段代码,(该代码位于发送的钩子函数之中)
测试结果分析
当访问其他机器时
[ 2021.743108] ip is -150951744
[ 2021.743116] ip is -150951744
当访问自己的机器,即ping自己时
ping 127.0.0.1
[ 2143.502997] ip is 16777343
[ 2143.503004] ip is 16777343
ping 192.168.0.247
[ 2153.257999] ip is 16777343
[ 2153.258001] ip is -150951744


其中 -150951744为-1000 11111111 01010111 01000000
取补码后为       11110111 000000 1010100 11000000
对应于             247     0      168    192
即为本机ip  192.168.0.247
对应的 16777343  应对应127.0.0.1

可以看出,这种方法在访问地址非本机时可以取得正确的结果
但在访问本机地址时 无论是ping 127.0.0.1 还是ping实际的 192.168.0.247 都只能取得127.0.0.1这个结果,不能正确的反应本机ip

但在使用过程中,一般可以忽略这个的影响,因为一般不会访问本机。

算美中不足吧
在任何情况下返回正确本机ip地址的方法
我还要继续的寻找。。。。。。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值