網絡編程中一些小函數,getifaddrs()等


#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>

#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <errno.h>


typedef long LONG;
typedef char CHAR;
#define CONST const

#ifndef  SUCCESS
#define  SUCCESS             0
#endif

#ifndef  FAIL
#define  FAIL               -1
#endif



LONG GetMac(CONST CHAR *pcIfName, CHAR *pcMac)
{ 
    if (NULL == pcIfName || NULL == pcMac)
    {
        printf("NULL == pcIfName || NULL == pcMac\n");
        return FAIL;
    }
    
    LONG lFd = 0, lRet = FAIL; 
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr)); 
    strcpy(ifr.ifr_name, pcIfName); 
    
    lFd = socket(AF_INET, SOCK_STREAM, 0); 
    if(lFd < 0)
    { 
        printf("socket fail\n");
        return FAIL; 
    } 

    //lRet = ioctl(lFd, SIOCGIFHWADDR, &ifr, sizeof(ifr)); 
	lRet = ioctl(lFd, SIOCGIFHWADDR, &ifr); 
    if(0 == lRet) 
    { 
        memcpy(pcMac, ifr.ifr_hwaddr.sa_data, 6);
		printf("\nifr.ifr_hwaddr.sa_data is %s   \n",ifr.ifr_hwaddr.sa_data);
        close(lFd); 
        return SUCCESS;
    }   
    else   
    { 
        printf("ioctl fail\n");
        close(lFd);
        return FAIL;
    }
}

LONG GetIp(CONST CHAR *pcIfName, CHAR *pcIp)
{ 
    if (NULL == pcIfName || NULL == pcIp)
    {
        printf("NULL == pcIfName || NULL == pcIp\n");
        return FAIL;
    }
    
    LONG lFd = 0, lRet = FAIL; 
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr)); 
    strcpy(ifr.ifr_name, pcIfName); 
    
    lFd = socket(AF_INET, SOCK_STREAM, 0); 
    if(lFd < 0)
    { 
        printf("socket fail\n");
        return FAIL; 
    } 

    lRet = ioctl(lFd, SIOCGIFADDR, &ifr); 
    if(0 == lRet) 
    { 
        strncpy(pcIp,inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr),16);
        close(lFd); 
        return SUCCESS;
    }   
    else   
    { 
        printf("ioctl fail\n");
        close(lFd);
        return FAIL;
    }
}


int main()
{
    LONG lRet = FAIL;
    CHAR szMac[6] = {0};
	CHAR szIp[16] = {0};
	
    CHAR szID[21] = {0};
	int i=0;
	int ulLen = 0;	
    
    lRet = GetMac("eth0", szMac);
	
	for(i = 0; i < sizeof(szMac); i++)
    {
        //sprintf(szID + strlen((const char*)szID), "%02X", szMac[i]);
		//ulLen = snprintf(szID, 1024, "%02X", szMac[i]);
		//ulLen +=snprintf((szID + ulLen), 1024, "%02X", szMac[i]);
		printf("%0x,",szMac[i]);
    }
	printf("\nlRet is %d,mac is %s\n",lRet,szID);
	
	lRet = GetIp("eth0", szIp);
	
	printf("lRet is %d,szIp is %s\n",lRet,szIp);

	return 0;
}

 

 

getifaddrs()和struct ifaddrs的使用,獲取本機IP 

http://canlynet.iteye.com/blog/1440054

ifaddrs結構體定義如下:

 

struct ifaddrs 
{ 
    struct ifaddrs  *ifa_next;    /* Next item in list */ 
    char            *ifa_name;    /* Name of interface */ 
    unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */ 
    struct sockaddr *ifa_addr;    /* Address of interface */ 
    struct sockaddr *ifa_netmask; /* Netmask of interface */ 
    union 
    { 
        struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */ 
        struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */ 
    } ifa_ifu; 
    #define              ifa_broadaddr ifa_ifu.ifu_broadaddr 
    #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr 
    void            *ifa_data;    /* Address-specific data */ 
}; 

 

 

ifa_next指向鏈表的下一個成員;ifa_name是接口名稱,以0結 尾的字符串,比如eth0,lo;ifa_flags是接口的標識位(比如當IFF_BROADCAST或IFF_POINTOPOINT設置到此標識位 時,影響聯合體變量ifu_broadaddr存儲廣播地址或ifu_dstaddr記錄點對點地址);ifa_netmask存儲該接口的子網掩碼;結 構體變量存儲廣播地址或點對點地址(見括弧介紹ifa_flags);ifa_data存儲了該接口協議族的特殊信息,它通常是NULL(一般不關注 他)。

    函數getifaddrs(int getifaddrs (struct ifaddrs **__ifap))獲取本地網絡接口信息,將之存儲於鏈表中,鏈表頭結點指針存儲於__ifap中帶回,函數執行成功返回0,失敗返回-1,且為errno賦值。
    很顯然,函數getifaddrs用於獲取本機接口信息,比如最典型的獲取本機IP地址。

 

 

 

/* Standard interface flags. */
enum
  {
    IFF_UP = 0x1,       /* Interface is up.  */
# define IFF_UP IFF_UP
    IFF_BROADCAST = 0x2,    /* Broadcast address valid.  */
# define IFF_BROADCAST  IFF_BROADCAST
    IFF_DEBUG = 0x4,        /* Turn on debugging.  */
# define IFF_DEBUG  IFF_DEBUG
    IFF_LOOPBACK = 0x8,     /* Is a loopback net.  */
# define IFF_LOOPBACK   IFF_LOOPBACK
    IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link.  */
# define IFF_POINTOPOINT IFF_POINTOPOINT
    IFF_NOTRAILERS = 0x20,  /* Avoid use of trailers.  */
# define IFF_NOTRAILERS IFF_NOTRAILERS
    IFF_RUNNING = 0x40,     /* Resources allocated.  */
# define IFF_RUNNING    IFF_RUNNING
    IFF_NOARP = 0x80,       /* No address resolution protocol.  */
# define IFF_NOARP  IFF_NOARP
    IFF_PROMISC = 0x100,    /* Receive all packets.  */
# define IFF_PROMISC    IFF_PROMISC

    /* Not supported */
    IFF_ALLMULTI = 0x200,   /* Receive all multicast packets.  */
# define IFF_ALLMULTI   IFF_ALLMULTI

    IFF_MASTER = 0x400,     /* Master of a load balancer.  */
# define IFF_MASTER IFF_MASTER
    IFF_SLAVE = 0x800,      /* Slave of a load balancer.  */
# define IFF_SLAVE  IFF_SLAVE

    IFF_MULTICAST = 0x1000, /* Supports multicast.  */
# define IFF_MULTICAST  IFF_MULTICAST

    IFF_PORTSEL = 0x2000,   /* Can set media type.  */
# define IFF_PORTSEL    IFF_PORTSEL
    IFF_AUTOMEDIA = 0x4000, /* Auto media select active.  */
# define IFF_AUTOMEDIA  IFF_AUTOMEDIA
    IFF_DYNAMIC = 0x8000    /* Dialup device with changing addresses.  */
# define IFF_DYNAMIC    IFF_DYNAMIC
  };

 

網絡設備 的 套接字(socket) 接口

http://blog.sina.com.cn/s/blog_4bb620d50100083u.html

#include <sys/ioctl.h>
#include <net/if.h>

描述 (DESCRIPTION)

本手冊 描述 用於 配置 網絡設備 的 套接字(socket) 接口.

Linux 支持 一些 配置 網絡設備 的 標准 ioctl. 他們用於任意的套接字 描述符, 而 無須 了解 其 類型 或 系列. 他們 傳遞一個 ifreq 結構:

struct ifreq
{
char ifr_name[IFNAMSIZ]; /* Interface name */ union { struct sockaddr ifr_addr; struct sockaddr ifr_dstaddr; struct sockaddr ifr_broadaddr; struct sockaddr ifr_netmask; struct sockaddr ifr_hwaddr; short ifr_flags; int ifr_ifindex; int ifr_metric; int ifr_mtu; struct ifmap ifr_map; char ifr_slave[IFNAMSIZ]; char ifr_newname[IFNAMSIZ]; char * ifr_data; }; }
struct ifconf { int ifc_len; /* size of buffer */
union {
char * ifc_buf; /* buffer ddress */ struct ifreq *ifc_req; /* array of structures */
}; };
一般說來, ioctl 通過 把 ifr_name 設置為 接口 的 名字 來指定 將要 操作 的 設備. 結構的 其他成員 可以 分享 內存.

IOCTLS

如果 某個 ioctl 標記為 特權操作, 那么 操作時 需要 有效uid 為 0, 或者 擁有 CAP_NET_ADMIN 能力. 否則 將 返回 EPERM .

SIOCGIFNAME

      給定 ifr_ifindex, 返回 ifr_name 中 的 接口名字. 這是唯一 返回 ifr_name 內容 的 ioctl.

SIOCGIFINDEX
把 接口 的 索引 存入 ifr_ifindex.
SIOCGIFFLAGS, SIOCSIFFLAGS
讀取 或 設置 設備的 活動標志字. ifr_flags 包含下列值的屏蔽位:
設備標志
IFF_UP 接口正在運行.
IFF_BROADCAST 有效的廣播地址集.
IFF_DEBUG 內部調試標志.
IFF_LOOPBACK 這是自環接口.
IFF_POINTOPOINT 這是點到點的鏈路接口.
IFF_RUNNING 資源已分配.
IFF_NOARP 無arp協議, 沒有設置第二層目的地址.
IFF_PROMISC 接口為雜湊(promiscuous)模式.
IFF_NOTRAILERS 避免使用trailer .
IFF_ALLMULTI 接收所有組播(multicast)報文.
IFF_MASTER 主負載平衡群(bundle).
IFF_SLAVE 從負載平衡群(bundle).
IFF_MULTICAST 支持組播(multicast).
IFF_PORTSEL 可以通過ifmap選擇介質(media)類型.
IFF_AUTOMEDIA 自動選擇介質.
IFF_DYNAMIC 接口關閉時丟棄地址.

設置 活動標志字 是 特權操作, 但是 任何進程 都可以讀取標志字.

SIOCGIFMETRIC, SIOCSIFMETRIC
使用 ifr_metric 讀取 或 設置 設備的 metric 值. 該功能目前 還沒有 實現. 讀取操作 使 ifr_metric 置 0, 而設置操作則 返回 EOPNOTSUPP.
SIOCGIFMTU, SIOCSIFMTU
使用 ifr_mtu 讀取 或 設置 設備的 MTU(最大傳輸單元). 設置 MTU 是 特權操作. 過小的 MTU 可能 導致 內核 崩潰.
SIOCGIFHWADDR, SIOCSIFHWADDR
使用 ifr_hwaddr 讀取 或 設置 設備的 硬件地址. 設置硬件地址 是 特權操作.
SIOCSIFHWBROADCAST
使用 ifr_hwaddr 讀取 或 設置 設備的 硬件廣播地址. 這是個特權操作.
SIOCGIFMAP, SIOCSIFMAP
使用 ifr_map 讀取 或 設置 接口的 硬件參數. 設置這個參數是 特權操作.
struct ifmap 
{
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
};
對 ifmap 結構 的 解釋 取決於 設備驅動程序 和 體系結構.
SIOCADDMULTI, SIOCDELMULTI
使用 ifr_hwaddr 在 設備的 鏈路層 組播過濾器 (multicase filter) 中 添加 或 刪除 地址. 這些是 特權操作. 參看 packet(7) .
SIOCGIFTXQLEN, SIOCSIFTXQLEN
使用 ifr_qlen 讀取 或 設置 設備的 傳輸隊列長度. 設置傳輸隊列長度 是 特權操作.
SIOCSIFNAME
ifr_ifindex 中 指定的 接口名字 改成 ifr_newname. 這是個 特權操作.
SIOCGIFCONF
返回 接口地址(傳輸層) 列表. 出於 兼容性, 目前 只代表 AF_INET 地址. 用戶 傳送 一個 ifconf 結構 作為 ioctl 的 參數. 其中 ifc_req 包含 一個 指針 指向 ifreq 結構數組, 他的長度以字節 為單位 存放在 ifc_len 中. 內核 用 所有 當前的 L3(第三層?) 接口地址 填充 ifreqs, 這些 接口 正在 運行: ifr_name 存放 接口名字 (eth0:1等), ifr_addr 存放地址. 內核 在 ifc_len 中 返回 實際長度; 如果 他 等於初始長度, 表示溢出了, 用戶 應該 換一個 大些的 緩沖區 重試 一下. 沒有 發生錯誤時 ioctl 返回 0, 否則 返回 -1, 溢出 不算 錯誤.

大多數 協議 使用 自己的 ioctl 配置 協議 特定的 接口 操作. 具體情況參看 協議的 幫助手冊. 要配置 IP 地址 可以 參看 ip(7).

另外, 某些 設備 有 專用的 ioctl, 這里 不做 敘述.

注意 (NOTE)

嚴格說來 SIOCGIFCONF 是 專門 針對 IP 的, 它 屬於 ip(7).

注意 (NOTE)

可以 通過 /proc/net/dev 看到 沒有 地址 或 沒有 IFF_RUNNING 標志 的 接口名字.

 

 

 

/* 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   IF_NAMESIZE
    union
      {
    char ifrn_name[IFNAMSIZ];   /* Interface 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 int ifru_flags;
    int ifru_ivalue;
    int ifru_mtu;
    struct ifmap ifru_map;
    char ifru_slave[IFNAMSIZ];  /* Just fits the size */
    char ifru_newname[IFNAMSIZ];
    __caddr_t ifru_data;
      } ifet_ifru;
  };
# define ifr_name   ifr_ifrn.ifrn_name  /* interface name   */
# define ifr_hwaddr ifr_ifru.ifru_hwaddr    /* MAC address      */
# define ifr_addr   ifr_ifru.ifru_addr  /* address      */
# define ifr_dstaddr    ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
# define ifr_broadaddr  ifr_ifru.ifru_broadaddr /* broadcast address    */
# define ifr_netmask    ifr_ifru.ifru_netmask   /* interface net mask   */
# define ifr_flags  ifr_ifru.ifru_flags /* flags        */
# define ifr_metric ifr_ifru.ifru_ivalue    /* metric       */
# define ifr_mtu    ifr_ifru.ifru_mtu   /* mtu          */
# define ifr_map    ifr_ifru.ifru_map   /* device map       */
# define ifr_slave  ifr_ifru.ifru_slave /* slave device     */
# define ifr_data   ifr_ifru.ifru_data  /* for use by interface */
# define ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index      */
# define ifr_bandwidth  ifr_ifru.ifru_ivalue    /* link bandwidth   */
# define ifr_qlen   ifr_ifru.ifru_ivalue    /* queue length     */
# define ifr_newname    ifr_ifru.ifru_newname   /* New name     */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM