37  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38  * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  39  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  40  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  41  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  42  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  43  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  44  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  45  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  46  */
  47 
  48 /**
  49  * @file   net.c
  50  * @date   Tue Jul 20 16:17:49 2010
  51  *
  52  * @brief  Functions to interact with the network sockets and NIC driver.
  53  *
  54  *
  55  */
  56 
  57 #include "../ptpd.h"
  58 
  59 #ifdef PTPD_PCAP
  60 #ifdef HAVE_PCAP_PCAP_H
  61 #include <pcap/pcap.h>
  62 #else /* !HAVE_PCAP_PCAP_H */
  63 /* Cases like RHEL5 and others where only pcap.h exists */
  64 #ifdef HAVE_PCAP_H
  65 #include <pcap.h>
  66 #endif /* HAVE_PCAP_H */
  67 #endif
  68 #define PCAP_TIMEOUT 1 /* expressed in milliseconds */
  69 #endif
  70 
  71 #if defined PTPD_SNMP
  72 #include <net-snmp/net-snmp-config.h>
  73 #include <net-snmp/net-snmp-includes.h>
  74 #include <net-snmp/agent/net-snmp-agent-includes.h>
  75 #endif
  76 
 
 
 289 
 290 end:
 291 
 292     freeifaddrs(ifaddr);
 293     return ret;
 294 }
 295 
 296 
 297 /* Try getting hwAddrSize bytes of ifaceName hardware address,
 298    and place them in hwAddr. Return 1 on success, 0 when no suitable
 299    hw address available, -1 on failure.
 300  */
 301 static int
 302 getHwAddress (char* ifaceName, unsigned char* hwAddr, int hwAddrSize)
 303 {
 304 
 305     int ret;
 306     if(!strlen(ifaceName))
 307         return 0;
 308 
 309 /* BSD* - AF_LINK gives us access to the hw address via struct sockaddr_dl */
 310 #ifdef AF_LINK
 311 
 312     struct ifaddrs *ifaddr, *ifa;
 313 
 314     if(getifaddrs(&ifaddr) == -1) {
 315         PERROR("Could not get interface list");
 316         ret = -1;
 317         goto end;
 318 
 319     }
 320 
 321     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 322 
 323         if(!strcmp(ifaceName, ifa->ifa_name) && ifa->ifa_addr->sa_family == AF_LINK) {
 324 
 325                 struct sockaddr_dl* sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 326                 if(sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_L2VLAN) {
 327 
 328                         memcpy(hwAddr, LLADDR(sdl),
 329                         hwAddrSize <= sizeof(sdl->sdl_data) ?
 330                         hwAddrSize : sizeof(sdl->sdl_data));
 331                         ret = 1;
 332                         goto end;
 333                 } else {
 334                         DBGV("Unsupported hardware address family on %s\n", ifaceName);
 335                         ret = 0;
 336                         goto end;
 337                 }
 338         }
 339 
 340     }
 341 
 342     ret = 0;
 343     DBG("Interface not found: %s\n", ifaceName);
 344 
 345 end:
 346 
 347     freeifaddrs(ifaddr);
 348     return ret;
 349 
 350 /* Linux, basically */
 351 #else
 352 
 353     int sockfd;
 354     struct ifreq ifr;
 355 
 356     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 357 
 358     if(sockfd < 0) {
 359         PERROR("Could not open test socket");
 360         return -1;
 361     }
 362 
 363     memset(&ifr, 0, sizeof(struct ifreq));
 364 
 365     strncpy(ifr.ifr_name, ifaceName, IFACE_NAME_LENGTH);
 366 
 367     if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
 368             DBGV("failed to request hardware address for %s", ifaceName);
 369             ret = -1;
 370             goto end;
 371     }
 372 
 373 
 374     int af = ifr.ifr_hwaddr.sa_family;
 375 
 376     if (    af == ARPHRD_ETHER
 377          || af == ARPHRD_IEEE802
 378 #ifdef ARPHRD_INFINIBAND
 379          || af == ARPHRD_INFINIBAND
 380 #endif
 381         ) {
 382             memcpy(hwAddr, ifr.ifr_hwaddr.sa_data, hwAddrSize);
 383             ret = 1;
 384         } else {
 385             DBGV("Unsupported hardware address family on %s\n", ifaceName);
 386             ret = 0;
 387         }
 388 end:
 389     close(sockfd);
 390     return ret;
 391 
 392 #endif /* AF_LINK */
 393 
 394 }
 395 
 396 static Boolean getInterfaceInfo(char* ifaceName, InterfaceInfo* ifaceInfo)
 397 {
 398 
 399     int res;
 400 
 401     res = interfaceExists(ifaceName);
 402 
 
 557 
 558 
 559         /* Init Peer multicast IP address */
 560         strncpy(addrStr, PEER_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);
 561         if (!inet_aton(addrStr, &netAddr)) {
 562                 ERROR("failed to encode multi-cast address: %s\n", addrStr);
 563                 return FALSE;
 564         }
 565         netPath->peerMulticastAddr = netAddr.s_addr;
 566         if(!netInitMulticastIPv4(netPath, netPath->peerMulticastAddr)) {
 567                 return FALSE;
 568         }
 569         /* End of Peer multicast Ip address init */
 570         
 571         return TRUE;
 572 }
 573 
 574 static Boolean
 575 netSetMulticastTTL(int sockfd, int ttl) {
 576 
 577 #ifdef __OpenBSD__
 578         uint8_t temp = (uint8_t) ttl;
 579 #else
 580         int temp = ttl;
 581 #endif
 582 
 583         if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
 584                        &temp, sizeof(temp)) < 0) {
 585             PERROR("Failed to set socket multicast time-to-live");
 586             return FALSE;
 587         }
 588         return TRUE;
 589 }
 590 
 591 static Boolean
 592 netSetMulticastLoopback(NetPath * netPath, Boolean value) {
 593 #ifdef __OpenBSD__
 594         uint8_t temp = value ? 1 : 0;
 595 #else
 596         int temp = value ? 1 : 0;
 597 #endif
 598         DBG("Going to set multicast loopback with %d \n", temp);
 599 
 600         if (setsockopt(netPath->eventSock, IPPROTO_IP, IP_MULTICAST_LOOP, 
 601                &temp, sizeof(temp)) < 0) {
 602                 PERROR("Failed to set multicast loopback");
 603                 return FALSE;
 604         }
 605         
 606         return TRUE;
 607 }
 608 
 609 #if defined(SO_TIMESTAMPING) && defined(SO_TIMESTAMPNS)
 610 static Boolean
 611 getTxTimestamp(NetPath* netPath,TimeInternal* timeStamp) {
 612         extern PtpClock *G_ptpClock;
 613         ssize_t length;
 
 731         if (!result) {
 732                 DBG("netInitTimestamping: trying to use SO_TIMESTAMP\n");
 733                 
 734                 if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMP, &val, sizeof(int)) < 0) {
 735                         PERROR("netInitTimestamping: failed to enable SO_TIMESTAMP");
 736                         result = FALSE;
 737                 }
 738                 result = TRUE;
 739         }
 740 #endif
 741 
 742         return result;
 743 }
 744 
 745 Boolean
 746 hostLookup(const char* hostname, Integer32* addr)
 747 {
 748         if (hostname[0]) {
 749                 /* Attempt a DNS lookup first. */
 750                 struct hostent *host;
 751                 host = gethostbyname2(hostname, AF_INET);
 752                 if (host != NULL) {
 753                         if (host->h_length != 4) {
 754                                 PERROR("unicast host resolved to non ipv4"
 755                                        "address");
 756                                 return FALSE;
 757                         }
 758                         *addr = 
 759                                 *(uint32_t *)host->h_addr_list[0];
 760                         return TRUE;
 761                 } else {
 762                         struct in_addr netAddr;
 763                         /* Maybe it's a dotted quad. */
 764                         if (!inet_aton(hostname, &netAddr)) {
 765                                 ERROR("failed to encode unicast address: %s\n",
 766                                       hostname);
 767                                 return FALSE;
 768                                 *addr = netAddr.s_addr;
 769                                 return TRUE;
 770                         }
 771                 }
 
 | 
 
 
  37  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38  * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  39  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  40  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  41  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  42  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  43  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  44  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  45  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  46  */
  47 
  48 /**
  49  * @file   net.c
  50  * @date   Tue Jul 20 16:17:49 2010
  51  *
  52  * @brief  Functions to interact with the network sockets and NIC driver.
  53  *
  54  *
  55  */
  56 
  57 #ifdef __sun
  58 /*
  59  * These are needed to enable control messages on sendmsg().
  60  * I'll save the commentary on why the bend-over-backwards old way of doing
  61  * sendmsg() is still around.
  62  *
  63  * STRICTLY SPEAKING this program should be linked against libxnet instead
  64  * of libsocket because of these interfaces, but we'll cross that bridge
  65  * when we get to it.
  66  */
  67 #define _XOPEN_SOURCE 500
  68 #define __EXTENSIONS__
  69 #endif
  70 
  71 #include "../ptpd.h"
  72 
  73 #ifdef PTPD_PCAP
  74 #ifdef HAVE_PCAP_PCAP_H
  75 #include <pcap/pcap.h>
  76 #else /* !HAVE_PCAP_PCAP_H */
  77 /* Cases like RHEL5 and others where only pcap.h exists */
  78 #ifdef HAVE_PCAP_H
  79 #include <pcap.h>
  80 #endif /* HAVE_PCAP_H */
  81 #endif
  82 #define PCAP_TIMEOUT 1 /* expressed in milliseconds */
  83 #endif
  84 
  85 #if defined PTPD_SNMP
  86 #include <net-snmp/net-snmp-config.h>
  87 #include <net-snmp/net-snmp-includes.h>
  88 #include <net-snmp/agent/net-snmp-agent-includes.h>
  89 #endif
  90 
 
 
 303 
 304 end:
 305 
 306     freeifaddrs(ifaddr);
 307     return ret;
 308 }
 309 
 310 
 311 /* Try getting hwAddrSize bytes of ifaceName hardware address,
 312    and place them in hwAddr. Return 1 on success, 0 when no suitable
 313    hw address available, -1 on failure.
 314  */
 315 static int
 316 getHwAddress (char* ifaceName, unsigned char* hwAddr, int hwAddrSize)
 317 {
 318 
 319     int ret;
 320     if(!strlen(ifaceName))
 321         return 0;
 322 
 323 #if defined(AF_LINK) && !defined(__sun)
 324 /* BSD* - AF_LINK gives us access to the hw address via struct sockaddr_dl */
 325 
 326     struct ifaddrs *ifaddr, *ifa;
 327 
 328     if(getifaddrs(&ifaddr) == -1) {
 329         PERROR("Could not get interface list");
 330         ret = -1;
 331         goto end;
 332 
 333     }
 334 
 335     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 336 
 337         if(!strcmp(ifaceName, ifa->ifa_name) && ifa->ifa_addr->sa_family == AF_LINK) {
 338 
 339                 struct sockaddr_dl* sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 340                 if(sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_L2VLAN) {
 341 
 342                         memcpy(hwAddr, LLADDR(sdl),
 343                         hwAddrSize <= sizeof(sdl->sdl_data) ?
 344                         hwAddrSize : sizeof(sdl->sdl_data));
 345                         ret = 1;
 346                         goto end;
 347                 } else {
 348                         DBGV("Unsupported hardware address family on %s\n", ifaceName);
 349                         ret = 0;
 350                         goto end;
 351                 }
 352         }
 353 
 354     }
 355 
 356     ret = 0;
 357     DBG("Interface not found: %s\n", ifaceName);
 358 
 359 end:
 360 
 361     freeifaddrs(ifaddr);
 362     return ret;
 363 
 364 #else
 365 /* Linux and Solarish systems have SIOCGIFHWADDR/SIOCGLIFHWADDR.  Use it. */
 366 
 367     int sockfd;
 368     struct ifreq ifr;
 369 
 370     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 371 
 372     if(sockfd < 0) {
 373         PERROR("Could not open test socket");
 374         return -1;
 375     }
 376 
 377     memset(&ifr, 0, sizeof (ifr));
 378 
 379     strncpy(ifr.ifr_name, ifaceName, IFACE_NAME_LENGTH);
 380 
 381     if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
 382             DBGV("failed to request hardware address for %s", ifaceName);
 383             ret = -1;
 384             goto end;
 385     }
 386 
 387 
 388 #ifdef __sun
 389     int af = ifr.ifr_addr.sa_family;
 390 #else
 391     int af = ifr.ifr_hwaddr.sa_family;
 392 #endif
 393 
 394     if (    af == ARPHRD_ETHER
 395          || af == ARPHRD_IEEE802
 396 #ifdef ARPHRD_INFINIBAND
 397          || af == ARPHRD_INFINIBAND
 398 #endif
 399         ) {
 400 #ifdef __sun
 401             memcpy(hwAddr, ifr.ifr_addr.sa_data, hwAddrSize);
 402 #else
 403             memcpy(hwAddr, ifr.ifr_hwaddr.sa_data, hwAddrSize);
 404 #endif
 405             ret = 1;
 406         } else {
 407             DBGV("Unsupported hardware address family on %s\n", ifaceName);
 408             ret = 0;
 409         }
 410 end:
 411     close(sockfd);
 412     return ret;
 413 
 414 #endif /* AF_LINK */
 415 
 416 }
 417 
 418 static Boolean getInterfaceInfo(char* ifaceName, InterfaceInfo* ifaceInfo)
 419 {
 420 
 421     int res;
 422 
 423     res = interfaceExists(ifaceName);
 424 
 
 579 
 580 
 581         /* Init Peer multicast IP address */
 582         strncpy(addrStr, PEER_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);
 583         if (!inet_aton(addrStr, &netAddr)) {
 584                 ERROR("failed to encode multi-cast address: %s\n", addrStr);
 585                 return FALSE;
 586         }
 587         netPath->peerMulticastAddr = netAddr.s_addr;
 588         if(!netInitMulticastIPv4(netPath, netPath->peerMulticastAddr)) {
 589                 return FALSE;
 590         }
 591         /* End of Peer multicast Ip address init */
 592         
 593         return TRUE;
 594 }
 595 
 596 static Boolean
 597 netSetMulticastTTL(int sockfd, int ttl) {
 598 
 599 #if defined(__OpenBSD__) || defined(__sun)
 600         uint8_t temp = (uint8_t) ttl;
 601 #else
 602         int temp = ttl;
 603 #endif
 604 
 605         if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
 606                        &temp, sizeof(temp)) < 0) {
 607             PERROR("Failed to set socket multicast time-to-live");
 608             return FALSE;
 609         }
 610         return TRUE;
 611 }
 612 
 613 static Boolean
 614 netSetMulticastLoopback(NetPath * netPath, Boolean value) {
 615 #if defined(__OpenBSD__) || defined(__sun)
 616         uint8_t temp = value ? 1 : 0;
 617 #else
 618         int temp = value ? 1 : 0;
 619 #endif
 620         DBG("Going to set multicast loopback with %d \n", temp);
 621 
 622         if (setsockopt(netPath->eventSock, IPPROTO_IP, IP_MULTICAST_LOOP, 
 623                &temp, sizeof(temp)) < 0) {
 624                 PERROR("Failed to set multicast loopback");
 625                 return FALSE;
 626         }
 627         
 628         return TRUE;
 629 }
 630 
 631 #if defined(SO_TIMESTAMPING) && defined(SO_TIMESTAMPNS)
 632 static Boolean
 633 getTxTimestamp(NetPath* netPath,TimeInternal* timeStamp) {
 634         extern PtpClock *G_ptpClock;
 635         ssize_t length;
 
 753         if (!result) {
 754                 DBG("netInitTimestamping: trying to use SO_TIMESTAMP\n");
 755                 
 756                 if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMP, &val, sizeof(int)) < 0) {
 757                         PERROR("netInitTimestamping: failed to enable SO_TIMESTAMP");
 758                         result = FALSE;
 759                 }
 760                 result = TRUE;
 761         }
 762 #endif
 763 
 764         return result;
 765 }
 766 
 767 Boolean
 768 hostLookup(const char* hostname, Integer32* addr)
 769 {
 770         if (hostname[0]) {
 771                 /* Attempt a DNS lookup first. */
 772                 struct hostent *host;
 773 #ifdef __sun
 774                 host = getipnodebyname(hostname, AF_INET, AI_DEFAULT, &errno);
 775 #else
 776                 host = gethostbyname2(hostname, AF_INET);
 777 #endif
 778                 if (host != NULL) {
 779                         if (host->h_length != 4) {
 780                                 PERROR("unicast host resolved to non ipv4"
 781                                        "address");
 782                                 return FALSE;
 783                         }
 784                         *addr = 
 785                                 *(uint32_t *)host->h_addr_list[0];
 786                         return TRUE;
 787                 } else {
 788                         struct in_addr netAddr;
 789                         /* Maybe it's a dotted quad. */
 790                         if (!inet_aton(hostname, &netAddr)) {
 791                                 ERROR("failed to encode unicast address: %s\n",
 792                                       hostname);
 793                                 return FALSE;
 794                                 *addr = netAddr.s_addr;
 795                                 return TRUE;
 796                         }
 797                 }
 
 |