net.c
来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· C语言 代码 · 共 585 行 · 第 1/2 页
C
585 行
/* net.c */
#include "../ptpd.h"
Boolean lookupSubdomainAddress(Octet *subdomainName, Octet *subdomainAddress)
{
UInteger32 h;
/* set multicast group address based on subdomainName */
if (!memcmp(subdomainName, DEFAULT_PTP_DOMAIN_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, DEFAULT_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);
else if(!memcmp(subdomainName, ALTERNATE_PTP_DOMAIN1_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN1_ADDRESS, NET_ADDRESS_LENGTH);
else if(!memcmp(subdomainName, ALTERNATE_PTP_DOMAIN2_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN2_ADDRESS, NET_ADDRESS_LENGTH);
else if(!memcmp(subdomainName, ALTERNATE_PTP_DOMAIN3_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN3_ADDRESS, NET_ADDRESS_LENGTH);
else
{
h = crc_algorithm(subdomainName, PTP_SUBDOMAIN_NAME_LENGTH) % 3;
switch(h)
{
case 0:
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN1_ADDRESS, NET_ADDRESS_LENGTH);
break;
case 1:
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN2_ADDRESS, NET_ADDRESS_LENGTH);
break;
case 2:
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN3_ADDRESS, NET_ADDRESS_LENGTH);
break;
default:
ERROR("handle out of range for '%s'!\n", subdomainName);
return FALSE;
}
}
return TRUE;
}
UInteger8 lookupCommunicationTechnology(UInteger8 communicationTechnology)
{
#if defined(linux)
switch(communicationTechnology)
{
case ARPHRD_ETHER:
case ARPHRD_EETHER:
case ARPHRD_IEEE802:
return PTP_ETHER;
default:
break;
}
#elif defined(BSD_INTERFACE_FUNCTIONS)
#endif
return PTP_DEFAULT;
}
UInteger32 findIface(Octet *ifaceName, UInteger8 *communicationTechnology,
Octet *uuid, NetPath *netPath)
{
#if defined(linux)
/* depends on linux specific ioctls (see 'netdevice' man page) */
int i, flags;
struct ifconf data;
struct ifreq device[IFCONF_LENGTH];
data.ifc_len = sizeof(device);
data.ifc_req = device;
memset(data.ifc_buf,0,data.ifc_len);
flags = IFF_UP|IFF_RUNNING|IFF_MULTICAST;
/* look for an interface if none specified */
if(ifaceName[0] != '\0')
{
i = 0;
memcpy(device[i].ifr_name, ifaceName, IFACE_NAME_LENGTH);
if(ioctl(netPath->eventSock, SIOCGIFHWADDR, &device[i]) < 0)
DBGV("failed to get hardware address\n");
else if((*communicationTechnology = lookupCommunicationTechnology(device[i].ifr_hwaddr.sa_family)) == PTP_DEFAULT)
DBGV("unsupported communication technology (%d)\n", *communicationTechnology);
else
memcpy(uuid, device[i].ifr_hwaddr.sa_data, PTP_UUID_LENGTH);
}
else
{
/* no iface specified */
/* get list of network interfaces*/
if(ioctl(netPath->eventSock, SIOCGIFCONF, &data) < 0)
{
PERROR("failed query network interfaces");
return 0;
}
if(data.ifc_len >= sizeof(device))
DBG("device list may exceed allocated space\n");
/* search through interfaces */
for(i=0; i < data.ifc_len/sizeof(device[0]); ++i)
{
DBGV("%d %s %s\n",i,device[i].ifr_name,inet_ntoa(((struct sockaddr_in *)&device[i].ifr_addr)->sin_addr));
if(ioctl(netPath->eventSock, SIOCGIFFLAGS, &device[i]) < 0)
DBGV("failed to get device flags\n");
else if((device[i].ifr_flags&flags) != flags)
DBGV("does not meet requirements (%08x, %08x)\n", device[i].ifr_flags, flags);
else if(ioctl(netPath->eventSock, SIOCGIFHWADDR, &device[i]) < 0)
DBGV("failed to get hardware address\n");
else if((*communicationTechnology = lookupCommunicationTechnology(device[i].ifr_hwaddr.sa_family)) == PTP_DEFAULT)
DBGV("unsupported communication technology (%d)\n", *communicationTechnology);
else
{
DBGV("found interface (%s)\n", device[i].ifr_name);
memcpy(uuid, device[i].ifr_hwaddr.sa_data, PTP_UUID_LENGTH);
memcpy(ifaceName, device[i].ifr_name, IFACE_NAME_LENGTH);
break;
}
}
}
if(ifaceName[0] == '\0')
{
ERROR("failed to find a usable interface\n");
return 0;
}
if(ioctl(netPath->eventSock, SIOCGIFADDR, &device[i]) < 0)
{
PERROR("failed to get ip address");
return 0;
}
return ((struct sockaddr_in *)&device[i].ifr_addr)->sin_addr.s_addr;
#elif defined(BSD_INTERFACE_FUNCTIONS)
struct ifaddrs *if_list, *ifv4, *ifh;
if (getifaddrs(&if_list) < 0)
{
PERROR("getifaddrs() failed");
return FALSE;
}
/* find an IPv4, multicast, UP interface, right name(if supplied) */
for (ifv4 = if_list; ifv4 != NULL; ifv4 = ifv4->ifa_next)
{
if ((ifv4->ifa_flags & IFF_UP) == 0)
continue;
if ((ifv4->ifa_flags & IFF_RUNNING) == 0)
continue;
if ((ifv4->ifa_flags & IFF_LOOPBACK))
continue;
if ((ifv4->ifa_flags & IFF_MULTICAST) == 0)
continue;
if (ifv4->ifa_addr->sa_family != AF_INET) /* must have IPv4 address */
continue;
if (ifaceName[0] && strncmp(ifv4->ifa_name, ifaceName, IF_NAMESIZE) != 0)
continue;
break;
}
if (ifv4 == NULL)
{
if (ifaceName[0])
{
ERROR("interface \"%s\" does not exist, or is not appropriate\n", ifaceName);
return FALSE;
}
ERROR("no suitable interfaces found!");
return FALSE;
}
/* find the AF_LINK info associated with the chosen interface */
for (ifh = if_list; ifh != NULL; ifh = ifh->ifa_next)
{
if (ifh->ifa_addr->sa_family != AF_LINK)
continue;
if (strncmp(ifv4->ifa_name, ifh->ifa_name, IF_NAMESIZE) == 0)
break;
}
if (ifh == NULL)
{
ERROR("could not get hardware address for interface \"%s\"\n", ifv4->ifa_name);
return FALSE;
}
/* check that the interface TYPE is OK */
if ( ((struct sockaddr_dl *)ifh->ifa_addr)->sdl_type != IFT_ETHER )
{
ERROR("\"%s\" is not an ethernet interface!\n", ifh->ifa_name);
return FALSE;
}
printf("==> %s %s %s\n", ifv4->ifa_name,
inet_ntoa(((struct sockaddr_in *)ifv4->ifa_addr)->sin_addr),
ether_ntoa((struct ether_addr *)LLADDR((struct sockaddr_dl *)ifh->ifa_addr))
);
*communicationTechnology = PTP_ETHER;
memcpy(ifaceName, ifh->ifa_name, IFACE_NAME_LENGTH);
memcpy(uuid, LLADDR((struct sockaddr_dl *)ifh->ifa_addr), PTP_UUID_LENGTH);
return ((struct sockaddr_in *)ifv4->ifa_addr)->sin_addr.s_addr;
#endif
}
/* start all of the UDP stuff */
/* must specify 'subdomainName', optionally 'ifaceName', if not then pass ifaceName == "" */
/* returns other args */
/* on socket options, see the 'socket(7)' and 'ip' man pages */
Boolean netInit(NetPath *netPath, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
int temp, i;
struct in_addr interfaceAddr, netAddr;
struct sockaddr_in addr;
struct ip_mreq imr;
char addrStr[NET_ADDRESS_LENGTH];
char *s;
DBG("netInit\n");
/* open sockets */
if( (netPath->eventSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) ) < 0
|| (netPath->generalSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) ) < 0 )
{
PERROR("failed to initalize sockets");
return FALSE;
}
/* find a network interface */
if( !(interfaceAddr.s_addr = findIface(rtOpts->ifaceName, &ptpClock->port_communication_technology,
ptpClock->port_uuid_field, netPath)) )
return FALSE;
temp = 1; /* allow address reuse */
if( setsockopt(netPath->eventSock, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(int)) < 0
|| setsockopt(netPath->generalSock, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(int)) < 0 )
{
DBG("failed to set socket reuse\n");
}
/* bind sockets */
/* need INADDR_ANY to allow receipt of multi-cast and uni-cast messages */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PTP_EVENT_PORT);
if(bind(netPath->eventSock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
PERROR("failed to bind event socket");
return FALSE;
}
addr.sin_port = htons(PTP_GENERAL_PORT);
if(bind(netPath->generalSock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
{
PERROR("failed to bind general socket");
return FALSE;
}
/* set general and port address */
*(Integer16*)ptpClock->event_port_address = PTP_EVENT_PORT;
*(Integer16*)ptpClock->general_port_address = PTP_GENERAL_PORT;
/* send a uni-cast address if specified (useful for testing) */
if(rtOpts->unicastAddress[0])
{
if(!inet_aton(rtOpts->unicastAddress, &netAddr))
{
ERROR("failed to encode uni-cast address: %s\n", rtOpts->unicastAddress);
return FALSE;
}
netPath->unicastAddr = netAddr.s_addr;
}
else
netPath->unicastAddr = 0;
/* resolve PTP subdomain */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?