📄 net.c
字号:
/* 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -