原创 linux应用编程之网络(2)

2011-3-3 20:58 1903 8 8 分类: MCU/ 嵌入式

好久没更新博客了,2011年了,也得有个开端才行,所以特意对linux应用编程做了一些总结,现晒出来,希望能给大家一点参考,同时也作为自己的备忘录,何乐而不为之................(学海无涯)-------------------------------------------water

               网络编程(2)续上

几个网络相关的地址的获得;

/********************************************************************

* 函数名: get_mac

* 参数名: char *mac_addr ( out)

*     

* 返回值: 0                成功

*         -1              失败

* 功  能:  获取本机物理地址,以字符串形式返回

* 版本  :  water-2010-07-08--first

********************************************************************/

 

int get_mac(char *mac_addr)

{

    int nSocket;

    struct ifreq struReq;

 

    if ( (nSocket = socket(PF_INET,SOCK_STREAM,0)) < 0)

    {

        error("socket");

        return  -1;

    }

    memset(&struReq,0,sizeof(struReq));

    strncpy(struReq.ifr_name, "eth0", sizeof(struReq.ifr_name));

    if( ioctl(nSocket,SIOCGIFHWADDR,&struReq) < 0)

   

    {  

        perror("ioctl");

        return -1;

    }

    close(nSocket);

    memcpy(mac_addr,( char *)ether_ntoa(struReq.ifr_hwaddr.sa_data),strlen(( char*)ether_ntoa(struReq.ifr_hwaddr.sa_data))+1);

    return 0;

}

 

/********************************************************************

* 函数名: get_ip

* 参数名: char *ip_addr ( out)

*     

* 返回值: 0                成功

*         -1              失败

* 功  能:  获取本机ip地址,以字符串形式返回

* 版本  :  water-2010-07-08--first

********************************************************************/

 

int get_ip(char *ip_addr)

{

    int sock;

    struct sockaddr_in sin;

    struct ifreq ifr;

    if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )

    {

        perror("socket");

        return  -1;

    }

    strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));

    if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)

    {  

        perror("ioctl");

        return -1;

    }

    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));

    close(sock);

    memcpy(ip_addr,inet_ntoa(sin.sin_addr),strlen(inet_ntoa(sin.sin_addr))+1);

    return 0;

   

}

//这里用一个函数来完成获得ip,netmask,mac.这个函数非常好用。

 

/********************************************************************

* 函数名: get_host_info

* 参数名: local_ip(out)    my_ip

*      local_mask(out)  my_mask

        local_mac(out) my_mac

* 返回值: 0                成功

*         -1              失败

* 功  能:获取本地机的ip,掩码,物理地址

* 版本  :  water-2010-07-08--first

********************************************************************/

int get_host_info(char *const local_ip, char *const local_mask, char *const local_mac)

{

    struct sockaddr_in my_ip, my_mask, my_mac;

    struct ifreq ifr;

    int sock;

 

    if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)

    {

        perror("socket");     

        return -1;

    }

    memset(&ifr,0,sizeof(ifr));

    strcpy(ifr.ifr_name, "eth0");

    //取本机IP地址

    if(ioctl(sock, SIOCGIFADDR, &ifr) < 0)

    {

        perror("ioctl_get_ip");        

        return -1;

    }

    memcpy(&my_ip, &ifr.ifr_addr, sizeof(my_ip));

    memcpy( local_ip, inet_ntoa(my_ip.sin_addr), strlen( inet_ntoa(my_ip.sin_addr) ) +1);

   

    //取本机掩码

    if( ioctl( sock, SIOCGIFNETMASK, &ifr) == -1 )

    {

        perror("ioctl_get_mask");

        return -1;

    }

 

    memcpy(&my_mask, &ifr.ifr_addr, sizeof(my_mask));

    memcpy( local_mask, inet_ntoa(my_mask.sin_addr), strlen( inet_ntoa(my_mask.sin_addr) )+1 );

    //取本机mac

    if ( ioctl( sock,SIOCGIFHWADDR,&ifr) < 0 )

    {

        perror("ioctl_get_mac");       

        return -1;

    }

    memcpy(local_mac,(char *)ether_ntoa(ifr.ifr_hwaddr.sa_data),strlen((char*)ether_ntoa(ifr.ifr_hwaddr.sa_data))+1);

    close(sock);

    return 0;

}

 

//获取网关相当繁琐些,具体代码如下:

/********************************************************************

* 函数名: get_gateway

* 参数名: gateway(out)   网关

* 返回值: 0            成功

*          -1             失败

* 功  能:获取本地机的网关

********************************************************************/

int get_gateway(char *gateway)

{

    struct nlmsghdr *nlMsg;

    struct rtmsg *rtMsg;

    struct route_info *rtInfo;

    char msgBuf[BUFSIZE];

 

    int sock, len, msgSeq = 0;

 //创建 Socket

    if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)

    {

        perror("Socket Creation: ");

        return -1;

    }

 

    /* Initialize the buffer */

    memset(msgBuf, 0, BUFSIZE);

 

    /* point the header and the msg structure pointers into the buffer */

    nlMsg = (struct nlmsghdr *)msgBuf;

    rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);

 

    /* Fill in the nlmsg header*/

    nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.

    nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .

 

    nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.

    nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.

    nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.

 

    /* Send the request */

    if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0){

        printf("Write To Socket Failed...\n");

        return -1;

    }

 

    /* Read the response */

    if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {

        printf("Read From Socket Failed...\n");

        return -1;

    }

    /* Parse and print the response */

    rtInfo = (struct route_info *)malloc(sizeof(struct route_info));

    for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)){

        memset(rtInfo, 0, sizeof(struct route_info));

        parseRoutes(nlMsg, rtInfo,gateway);

    }

    free(rtInfo);

    close(sock);

    return 0;

}

// the follow sources for get the gateway

//下面两个函数是获取网关是用到的

 

int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId)

{

    struct nlmsghdr *nlHdr;

    int readLen = 0, msgLen = 0;

    do{

    //收到内核的应答

        if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0)

        {

            perror("SOCK READ: ");

            return -1;

        }

  

        nlHdr = (struct nlmsghdr *)bufPtr;

    //检查header是否有效

        if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))

        {

            perror("Error in recieved packet");

            return -1;

        }

  

        /* Check if the its the last message */

        if(nlHdr->nlmsg_type == NLMSG_DONE)

        {

            break;

        }

        else

        {

            /* Else move the pointer to buffer appropriately */

            bufPtr += readLen;

            msgLen += readLen;

        }

  

        /* Check if its a multi part message */

        if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0)

        {

            /* return if its not */

            break;

        }

    } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));

    return msgLen;

}

 

//分析返回的路由信息

void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo,char *gateway)

{

    struct rtmsg *rtMsg;

    struct rtattr *rtAttr;

    int rtLen;

    char *tempBuf = NULL;

 //2007-12-10

    struct in_addr dst;

    struct in_addr gate;

 

    tempBuf = (char *)malloc(100);

    rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);

  // If the route is not for AF_INET or does not belong to main routing table

  //then return.

    if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))

        return;

    /* get the rtattr field */

    rtAttr = (struct rtattr *)RTM_RTA(rtMsg);

    rtLen = RTM_PAYLOAD(nlHdr);

    for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)){

        switch(rtAttr->rta_type) {

            case RTA_OIF:

                if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);

                break;

            case RTA_GATEWAY:

                rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);

                break;

            case RTA_PREFSRC:

                rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);

                break;

            case RTA_DST:

                rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);

                break;

        }

    }

  //2007-12-10

    dst.s_addr = rtInfo->dstAddr;

    if (strstr((char *)inet_ntoa(dst), "0.0.0.0"))

    {

        gate.s_addr = rtInfo->gateWay;

        sprintf(gateway, (char *)inet_ntoa(gate));

   

    }

    free(tempBuf);

    return;

}

文章评论0条评论)

登录后参与讨论
我要评论
0
8
关闭 站长推荐上一条 /2 下一条