Android源码--网络--libnetutils

因为要解决Android4.4.2系统Ethernet 设置断电重启后,IP地址子网掩码等设置无效的问题,故对底层用到的 libnetutils 代码做了简单的分析

/system/core/libnetutils/ifc_utils.c ----- libnetutils的核心接口文件

主要用到了如下几个函数

1》 open close

int ifc_init(void)
{
    int ret;
    if (ifc_ctl_sock == -1) {
        ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (ifc_ctl_sock < 0) {
            printerr("socket() failed: %s\n", strerror(errno));
        }
    }


    ret = ifc_ctl_sock < 0 ? -1 : 0;
    if (DBG) printerr("ifc_init_returning %d", ret);
    return ret;
}


int ifc_init6(void)
{
    if (ifc_ctl_sock6 == -1) {
        ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
        if (ifc_ctl_sock6 < 0) {
            printerr("socket() failed: %s\n", strerror(errno));
        }
    }
    return ifc_ctl_sock6 < 0 ? -1 : 0;
}


void ifc_close(void)
{
    if (DBG) printerr("ifc_close");
    if (ifc_ctl_sock != -1) {
        (void)close(ifc_ctl_sock);
        ifc_ctl_sock = -1;
    }
}



void ifc_close6(void)
{
    if (ifc_ctl_sock6 != -1) {
        (void)close(ifc_ctl_sock6);
        ifc_ctl_sock6 = -1;
    }
}

 

分为IPV4和IPV6两种接口,通过 socket  方法实现


2》 通过 ioctl 实现对 Out-of-band(带外)数据的读写,实现IP地址 子网掩码等参数的管理

int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags)
{
    struct ifreq ifr;
    ifc_init_ifr(name, &ifr);


    if (addr != NULL) {
        if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) {
            *addr = 0;
        } else {
            *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
        }
    }


    if (prefixLength != NULL) {
        if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) {
            *prefixLength = 0;
        } else {
            *prefixLength = ipv4NetmaskToPrefixLength(
                    ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr);
        }
    }


    if (flags != NULL) {
        if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) {
            *flags = 0;
        } else {
            *flags = ifr.ifr_flags;
        }
    }


    return 0;
}



3》下面三个函数实现了网卡的开关复位操作

int ifc_enable(const char *ifname)
{
    int result;


    ifc_init();
    result = ifc_up(ifname);
    ifc_close();
    return result;
}


int ifc_disable(const char *ifname)
{
    unsigned addr, count;
    int result;


    ifc_init();
    result = ifc_down(ifname);


    ifc_set_addr(ifname, 0);
    for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
       if (ifc_get_addr(ifname, &addr) < 0)
            break;
       if (addr)
          ifc_set_addr(ifname, 0);
    }


    ifc_close();
    return result;
}


int ifc_reset_connections(const char *ifname, const int reset_mask)
{
#ifdef HAVE_ANDROID_OS
    int result, success;
    in_addr_t myaddr;
    struct ifreq ifr;
    struct in6_ifreq ifr6;


    if (reset_mask & RESET_IPV4_ADDRESSES) {
        /* IPv4. Clear connections on the IP address. */
        ifc_init();
        ifc_get_info(ifname, &myaddr, NULL, NULL);
        ifc_init_ifr(ifname, &ifr);
        init_sockaddr_in(&ifr.ifr_addr, myaddr);
        result = ioctl(ifc_ctl_sock, SIOCKILLADDR,  &ifr);
        ifc_close();
    } else {
        result = 0;
    }


    if (reset_mask & RESET_IPV6_ADDRESSES) {
        /*
         * IPv6. On Linux, when an interface goes down it loses all its IPv6
         * addresses, so we don't know which connections belonged to that interface
         * So we clear all unused IPv6 connections on the device by specifying an
         * empty IPv6 address.
         */
        ifc_init6();
        // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets.
        memset(&ifr6, 0, sizeof(ifr6));
        success = ioctl(ifc_ctl_sock6, SIOCKILLADDR,  &ifr6);
        if (result == 0) {
            result = success;
        }
        ifc_close6();
    }


    return result;
#else
    return 0;
#endif
}


注:关于 ioctl

用 法: int ioctl(int handle, int cmd,[int *argdx, int argcx]);
返回值:成功为0,出错为-1

控制I/O设备 ,提供了一种获得设备信息和向设备发送控制参数的手段。用于向设备发控制和配置命令 ,有些命令需要控制参数,这些数据是不能用read / write 读写的,称为Out-of-band数据。也就是说,read / write 读写的数据是in-band数据,是I/O操作的主体,而ioctl 命令传送的是控制信息,其中的数据是辅助的数据。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值