1 /*-
   2  * Copyright (c) 2014      Wojciech Owczarek,
   3  *                         George V. Neville-Neil
   4  * Copyright (c) 2012-2013 George V. Neville-Neil,
   5  *                         Wojciech Owczarek.
   6  * Copyright (c) 2011-2012 George V. Neville-Neil,
   7  *                         Steven Kreuzer, 
   8  *                         Martin Burnicki, 
   9  *                         Jan Breuer,
  10  *                         Gael Mace, 
  11  *                         Alexandre Van Kempen,
  12  *                         Inaqui Delgado,
  13  *                         Rick Ratzel,
  14  *                         National Instruments.
  15  * Copyright (c) 2009-2010 George V. Neville-Neil, 
  16  *                         Steven Kreuzer, 
  17  *                         Martin Burnicki, 
  18  *                         Jan Breuer,
  19  *                         Gael Mace, 
  20  *                         Alexandre Van Kempen
  21  *
  22  * Copyright (c) 2005-2008 Kendall Correll, Aidan Williams
  23  *
  24  * All Rights Reserved
  25  * 
  26  * Redistribution and use in source and binary forms, with or without
  27  * modification, are permitted provided that the following conditions are
  28  * met:
  29  * 1. Redistributions of source code must retain the above copyright notice,
  30  *    this list of conditions and the following disclaimer.
  31  * 2. Redistributions in binary form must reproduce the above copyright
  32  *    notice, this list of conditions and the following disclaimer in the
  33  *    documentation and/or other materials provided with the distribution.
  34  * 
  35  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  36  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  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 
  77 /* choose kernel-level nanoseconds or microseconds resolution on the client-side */
  78 #if !defined(SO_TIMESTAMPING) && !defined(SO_TIMESTAMPNS) && !defined(SO_TIMESTAMP) && !defined(SO_BINTIME)
  79 #error No kernel-level support for packet timestamping detected!
  80 #endif
  81 
  82 #ifdef SO_TIMESTAMPING
  83 #include <linux/net_tstamp.h>
  84 #include <linux/sockios.h>
  85 #include <linux/ethtool.h>
  86 #endif /* SO_TIMESTAMPING */
  87 
  88 /**
  89  * shutdown the IPv4 multicast for specific address
  90  *
  91  * @param netPath
  92  * @param multicastAddr
  93  * 
  94  * @return TRUE if successful
  95  */
  96 static Boolean
  97 netShutdownMulticastIPv4(NetPath * netPath, Integer32 multicastAddr)
  98 {
  99         struct ip_mreq imr;
 100 
 101         /* Close General Multicast */
 102         imr.imr_multiaddr.s_addr = multicastAddr;
 103         imr.imr_interface.s_addr = netPath->interfaceAddr.s_addr;
 104 
 105         setsockopt(netPath->eventSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, 
 106                    &imr, sizeof(struct ip_mreq));
 107         setsockopt(netPath->generalSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, 
 108                    &imr, sizeof(struct ip_mreq));
 109         
 110         return TRUE;
 111 }
 112 
 113 /**
 114  * shutdown the multicast (both General and Peer)
 115  *
 116  * @param netPath 
 117  * 
 118  * @return TRUE if successful
 119  */
 120 static Boolean
 121 netShutdownMulticast(NetPath * netPath)
 122 {
 123         /* Close General Multicast */
 124         netShutdownMulticastIPv4(netPath, netPath->multicastAddr);
 125         netPath->multicastAddr = 0;
 126 
 127         /* Close Peer Multicast */
 128         netShutdownMulticastIPv4(netPath, netPath->peerMulticastAddr);
 129         netPath->peerMulticastAddr = 0;
 130         
 131         return TRUE;
 132 }
 133 
 134 /*
 135  * For future use: Check if IPv4 address is multiast -
 136  * If last 4 bits of an address are 0xE (1110), it's multicast
 137  */
 138 /*
 139 static Boolean
 140 isIpMulticast(struct in_addr in)
 141 {
 142         if((ntohl(in.s_addr) >> 28) == 0x0E )
 143             return TRUE;
 144         return FALSE;
 145 }
 146 */
 147 
 148 /* shut down the UDP stuff */
 149 Boolean 
 150 netShutdown(NetPath * netPath)
 151 {
 152         netShutdownMulticast(netPath);
 153 
 154         netPath->unicastAddr = 0;
 155 
 156         /* Close sockets */
 157         if (netPath->eventSock >= 0)
 158                 close(netPath->eventSock);
 159         netPath->eventSock = -1;
 160 
 161         if (netPath->generalSock >= 0)
 162                 close(netPath->generalSock);
 163         netPath->generalSock = -1;
 164 
 165 #ifdef PTPD_PCAP
 166         if (netPath->pcapEvent != NULL) {
 167                 pcap_close(netPath->pcapEvent);
 168                 netPath->pcapEventSock = -1;
 169         }
 170         if (netPath->pcapGeneral != NULL) {
 171                 pcap_close(netPath->pcapGeneral);
 172                 netPath->pcapGeneralSock = -1;
 173         }
 174 #endif
 175 
 176         freeIpv4AccessList(&netPath->timingAcl);
 177         freeIpv4AccessList(&netPath->managementAcl);
 178 
 179         return TRUE;
 180 }
 181 
 182 /* Check if interface ifaceName exists. Return 1 on success, 0 when interface doesn't exists, -1 on failure.
 183  */
 184 
 185 static int
 186 interfaceExists(char* ifaceName)
 187 {
 188 
 189     int ret;
 190     struct ifaddrs *ifaddr, *ifa;
 191 
 192     if(!strlen(ifaceName)) {
 193         DBG("interfaceExists called for an empty interface!");
 194         return 0;
 195     }
 196 
 197     if(getifaddrs(&ifaddr) == -1) {
 198         PERROR("Could not get interface list");
 199         ret = -1;
 200         goto end;
 201 
 202     }
 203 
 204     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 205 
 206         if(!strcmp(ifaceName, ifa->ifa_name)) {
 207             ret = 1;
 208             goto end;
 209         }
 210 
 211     }
 212 
 213     ret = 0;
 214     DBG("Interface not found: %s\n", ifaceName);
 215 
 216 end:
 217    freeifaddrs(ifaddr);
 218     return ret;
 219 }
 220 
 221 static int
 222 getInterfaceFlags(char* ifaceName, unsigned int* flags)
 223 {
 224 
 225     int ret;
 226     struct ifaddrs *ifaddr, *ifa;
 227 
 228     if(!strlen(ifaceName)) {
 229         DBG("interfaceExists called for an empty interface!");
 230         return 0;
 231     }
 232 
 233     if(getifaddrs(&ifaddr) == -1) {
 234         PERROR("Could not get interface list");
 235         ret = -1;
 236         goto end;
 237 
 238     }
 239 
 240     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 241 
 242         if(!strcmp(ifaceName, ifa->ifa_name)) {
 243             *flags = ifa->ifa_flags;
 244             ret = 1;
 245             goto end;
 246         }
 247 
 248     }
 249 
 250     ret = 0;
 251     DBG("Interface not found: %s\n", ifaceName);
 252 
 253 end:
 254    freeifaddrs(ifaddr);
 255     return ret;
 256 }
 257 
 258 
 259 /* Try getting addr address of family family from interface ifaceName.
 260    Return 1 on success, 0 when no suitable address available, -1 on failure.
 261  */
 262 static int
 263 getInterfaceAddress(char* ifaceName, int family, struct in_addr* addr) {
 264 
 265     int ret;
 266     struct ifaddrs *ifaddr, *ifa;
 267 
 268     if(getifaddrs(&ifaddr) == -1) {
 269         PERROR("Could not get interface list");
 270         ret = -1;
 271         goto end;
 272 
 273     }
 274 
 275     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 276 
 277         if(!strcmp(ifaceName, ifa->ifa_name) && ifa->ifa_addr->sa_family == family) {
 278 
 279                 *addr = ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
 280                 ret = 1;
 281                 goto end;
 282 
 283         }
 284 
 285     }
 286 
 287     ret = 0;
 288     DBG("Interface not found: %s\n", ifaceName);
 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 
 403     if (res == -1) {
 404 
 405         return FALSE;
 406 
 407     } else if (res == 0) {
 408 
 409         ERROR("Interface %s does not exist.\n", ifaceName);
 410         return FALSE;
 411     }
 412 
 413     res = getInterfaceAddress(ifaceName, ifaceInfo->addressFamily, &ifaceInfo->afAddress);
 414 
 415     if (res == -1) {
 416 
 417         return FALSE;
 418 
 419     }
 420 
 421     ifaceInfo->hasAfAddress = res;
 422 
 423     res = getHwAddress(ifaceName, (unsigned char*)ifaceInfo->hwAddress, 6);
 424 
 425     if (res == -1) {
 426 
 427         return FALSE;
 428 
 429     }
 430 
 431     ifaceInfo->hasHwAddress = res;
 432 
 433     res = getInterfaceFlags(ifaceName, &ifaceInfo->flags);
 434 
 435     if (res == -1) {
 436 
 437         return FALSE;
 438 
 439     }
 440 
 441     return TRUE;
 442 
 443 }
 444 
 445 Boolean
 446 testInterface(char * ifaceName, RunTimeOpts* rtOpts)
 447 {
 448 
 449         InterfaceInfo info;
 450 
 451         info.addressFamily = AF_INET;
 452 
 453         if(getInterfaceInfo(ifaceName, &info) != 1)
 454                 return FALSE;
 455 
 456         switch(rtOpts->transport) {
 457 
 458             case UDP_IPV4:
 459                 if(!info.hasAfAddress) {
 460                     ERROR("Interface %s has no IPv4 address set\n", ifaceName);
 461                     return FALSE;
 462                 }
 463                 break;
 464 
 465             case IEEE_802_3:
 466                 if(!info.hasHwAddress) {
 467                     ERROR("Interface %s has no supported hardware address - possibly not an Ethernet interface\n", ifaceName);
 468                     return FALSE;
 469                 }
 470                 break;
 471 
 472             default:
 473                 ERROR("Unsupported transport: %d\n", rtOpts->transport);
 474                 return FALSE;
 475 
 476         }
 477 
 478     if(!(info.flags & IFF_UP) || !(info.flags & IFF_RUNNING))
 479             WARNING("Interface %s seems to be down. PTPd will not operate correctly until it's up.\n", ifaceName);
 480 
 481     if(info.flags & IFF_LOOPBACK)
 482             WARNING("Interface %s is a loopback interface.\n", ifaceName);
 483 
 484     if(!(info.flags & IFF_MULTICAST) 
 485             && rtOpts->transport==UDP_IPV4 
 486             && rtOpts->ip_mode != IPMODE_UNICAST) {
 487             WARNING("Interface %s is not multicast capable.\n", ifaceName);
 488     }
 489 
 490         return TRUE;
 491 
 492 }
 493 
 494 /**
 495  * Init the multcast for specific IPv4 address
 496  * 
 497  * @param netPath 
 498  * @param multicastAddr 
 499  * 
 500  * @return TRUE if successful
 501  */
 502 static Boolean
 503 netInitMulticastIPv4(NetPath * netPath, Integer32 multicastAddr)
 504 {
 505         struct ip_mreq imr;
 506 
 507         /* multicast send only on specified interface */
 508         imr.imr_multiaddr.s_addr = multicastAddr;
 509         imr.imr_interface.s_addr = netPath->interfaceAddr.s_addr;
 510         if (setsockopt(netPath->eventSock, IPPROTO_IP, IP_MULTICAST_IF, 
 511                        &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0
 512             || setsockopt(netPath->generalSock, IPPROTO_IP, IP_MULTICAST_IF, 
 513                           &imr.imr_interface.s_addr, sizeof(struct in_addr)) 
 514             < 0) {
 515                 PERROR("failed to enable multi-cast on the interface");
 516                 return FALSE;
 517         }
 518         /* join multicast group (for receiving) on specified interface */
 519         if (setsockopt(netPath->eventSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
 520                        &imr, sizeof(struct ip_mreq)) < 0
 521             || setsockopt(netPath->generalSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
 522                           &imr, sizeof(struct ip_mreq)) < 0) {
 523                 PERROR("failed to join the multi-cast group");
 524                 return FALSE;
 525         }
 526         return TRUE;
 527 }
 528 
 529 /**
 530  * Init the multcast (both General and Peer)
 531  * 
 532  * @param netPath 
 533  * @param rtOpts 
 534  * 
 535  * @return TRUE if successful
 536  */
 537 static Boolean
 538 netInitMulticast(NetPath * netPath,  RunTimeOpts * rtOpts)
 539 {
 540         struct in_addr netAddr;
 541         char addrStr[NET_ADDRESS_LENGTH+1];
 542 
 543         
 544         /* Init General multicast IP address */
 545         strncpy(addrStr, DEFAULT_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);
 546         if (!inet_aton(addrStr, &netAddr)) {
 547                 ERROR("failed to encode multicast address: %s\n", addrStr);
 548                 return FALSE;
 549         }
 550 
 551         netPath->multicastAddr = netAddr.s_addr;
 552         if(!netInitMulticastIPv4(netPath, netPath->multicastAddr)) {
 553                 return FALSE;
 554         }
 555 
 556         /* End of General multicast Ip address init */
 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;
 614         fd_set tmpSet;
 615         struct timeval timeOut = {0,0};
 616         int val = 1;
 617         if(netPath->txTimestampFailure)
 618                 goto end;
 619 
 620         FD_ZERO(&tmpSet);
 621         FD_SET(netPath->eventSock, &tmpSet);
 622 
 623         if(select(netPath->eventSock + 1, &tmpSet, NULL, NULL, &timeOut) > 0) {
 624                 if (FD_ISSET(netPath->eventSock, &tmpSet)) {
 625                         length = netRecvEvent(G_ptpClock->msgIbuf, timeStamp, 
 626                             netPath, MSG_ERRQUEUE);
 627 
 628                         if (length > 0) {
 629                                 DBG("Grabbed sent msg via errqueue: %d bytes, at %d.%d\n", length, timeStamp->seconds, timeStamp->nanoseconds);
 630                                 return TRUE;
 631                         } else if (length < 0) {
 632                                 DBG("Failed to poll error queue for SO_TIMESTAMPING transmit time");
 633                                 G_ptpClock->counters.messageRecvErrors++;
 634                                 goto end;
 635                         } else if (length == 0) {
 636                                 DBG("Received no data from TX error queue");
 637                                 goto end;
 638                         }
 639                 }
 640         } else {
 641                 DBG("SO_TIMESTAMPING - t timeout on TX timestamp - will use loop from now on\n");
 642                 return FALSE;
 643         }
 644 end:
 645                 if(setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMPNS, &val, sizeof(int)) < 0) {
 646                         DBG("gettxtimestamp: failed to revert to SO_TIMESTAMPNS");
 647                 }
 648 
 649                 return FALSE;
 650 }
 651 #endif /* SO_TIMESTAMPING */
 652 
 653 
 654 /**
 655  * Initialize timestamping of packets
 656  *
 657  * @param netPath 
 658  * 
 659  * @return TRUE if successful
 660  */
 661 static Boolean 
 662 netInitTimestamping(NetPath * netPath, RunTimeOpts * rtOpts)
 663 {
 664 
 665         int val = 1;
 666         Boolean result = TRUE;
 667 #if defined(SO_TIMESTAMPING) && defined(SO_TIMESTAMPNS)/* Linux - current API */
 668         DBG("netInitTimestamping: trying to use SO_TIMESTAMPING\n");
 669         val = SOF_TIMESTAMPING_TX_SOFTWARE |
 670             SOF_TIMESTAMPING_RX_SOFTWARE |
 671             SOF_TIMESTAMPING_SOFTWARE;
 672 
 673 /* unless compiled with PTPD_EXPERIMENTAL, check if we support the desired tstamp capabilities */
 674 #ifndef PTPD_EXPERIMENTAL
 675 #ifdef ETHTOOL_GET_TS_INFO
 676 
 677        struct ethtool_ts_info tsInfo;
 678         struct ifreq ifRequest;
 679         int res;
 680 
 681         memset(&tsInfo, 0, sizeof(tsInfo));
 682         memset(&ifRequest, 0, sizeof(ifRequest));
 683         tsInfo.cmd = ETHTOOL_GET_TS_INFO;
 684         strncpy( ifRequest.ifr_name, rtOpts->ifaceName, IFNAMSIZ - 1);
 685         ifRequest.ifr_data = (char *) &tsInfo;
 686         res = ioctl(netPath->eventSock, SIOCETHTOOL, &ifRequest);
 687 
 688         if (res < 0) {
 689                 PERROR("Could not retrieve ethtool timestamping capabilities for %s - reverting to SO_TIMESTAMPNS",
 690                             rtOpts->ifaceName);
 691                 val = 1;
 692                 netPath->txTimestampFailure = FALSE;
 693         } else if((tsInfo.so_timestamping & val) != val) {
 694                 DBGV("Required SO_TIMESTAMPING flags not supported - reverting to SO_TIMESTAMPNS\n");
 695                 val = 1;
 696                 netPath->txTimestampFailure = TRUE;
 697         }
 698 #else
 699         netPath->txTimestampFailure = FALSE;
 700         val = 1;
 701 #endif /* ETHTOOL_GET_TS_INFO */
 702 #endif /* PTPD_EXPERIMENTAL */
 703 
 704         if((val==1 && (setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMPNS, &val, sizeof(int)) < 0)) ||
 705                 (setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(int)) < 0)) {
 706                 PERROR("netInitTimestamping: failed to enable SO_TIMESTAMP%s",(val==1)?"NS":"ING");
 707                 result = FALSE;
 708         } else {
 709         DBG("SO_TIMESTAMP%s initialised\n",(val==1)?"NS":"ING");
 710         }
 711 #elif defined(SO_TIMESTAMPNS) /* Linux, Apple */
 712         DBG("netInitTimestamping: trying to use SO_TIMESTAMPNS\n");
 713         
 714         if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_TIMESTAMPNS, &val, sizeof(int)) < 0) {
 715                 PERROR("netInitTimestamping: failed to enable SO_TIMESTAMPNS");
 716                 result = FALSE;
 717         }
 718 #elif defined(SO_BINTIME) /* FreeBSD */
 719         DBG("netInitTimestamping: trying to use SO_BINTIME\n");
 720                 
 721         if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_BINTIME, &val, sizeof(int)) < 0) {
 722                 PERROR("netInitTimestamping: failed to enable SO_BINTIME");
 723                 result = FALSE;
 724         }
 725 #else
 726         result = FALSE;
 727 #endif
 728                         
 729 /* fallback method */
 730 #if defined(SO_TIMESTAMP) /* Linux, Apple, FreeBSD */
 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                 }
 772         }
 773 
 774 return FALSE;
 775 
 776 }
 777 
 778 
 779 /**
 780  * Init all network transports
 781  *
 782  * @param netPath 
 783  * @param rtOpts 
 784  * @param ptpClock 
 785  * 
 786  * @return TRUE if successful
 787  */
 788 Boolean 
 789 netInit(NetPath * netPath, RunTimeOpts * rtOpts, PtpClock * ptpClock)
 790 {
 791         int temp;
 792         struct sockaddr_in addr;
 793 
 794 #ifdef PTPD_PCAP
 795         struct bpf_program program;
 796         char errbuf[PCAP_ERRBUF_SIZE];
 797 #endif
 798 
 799         DBG("netInit\n");
 800 
 801 #ifdef PTPD_PCAP
 802         netPath->pcapEvent = NULL;
 803         netPath->pcapGeneral = NULL;
 804         netPath->pcapEventSock = -1;
 805         netPath->pcapGeneralSock = -1;
 806 #endif
 807         netPath->generalSock = -1;
 808         netPath->eventSock = -1;
 809 
 810 #ifdef PTPD_PCAP
 811         if (rtOpts->transport == IEEE_802_3) {
 812                 netPath->headerOffset = PACKET_BEGIN_ETHER;
 813 #ifdef HAVE_STRUCT_ETHER_ADDR_OCTET
 814                 memcpy(netPath->etherDest.octet, ether_aton(PTP_ETHER_DST), ETHER_ADDR_LEN);
 815                 memcpy(netPath->peerEtherDest.octet, ether_aton(PTP_ETHER_PEER), ETHER_ADDR_LEN);
 816 #else
 817                 memcpy(netPath->etherDest.ether_addr_octet, ether_aton(PTP_ETHER_DST), ETHER_ADDR_LEN);
 818                 memcpy(netPath->peerEtherDest.ether_addr_octet, ether_aton(PTP_ETHER_PEER), ETHER_ADDR_LEN);
 819 #endif /* HAVE_STRUCT_ETHER_ADDR_OCTET */
 820         } else
 821 #endif
 822                 netPath->headerOffset = PACKET_BEGIN_UDP;
 823 
 824         /* open sockets */
 825         if ((netPath->eventSock = socket(PF_INET, SOCK_DGRAM, 
 826                                          IPPROTO_UDP)) < 0
 827             || (netPath->generalSock = socket(PF_INET, SOCK_DGRAM, 
 828                                               IPPROTO_UDP)) < 0) {
 829                 PERROR("failed to initialize sockets");
 830                 return FALSE;
 831         }
 832 
 833         if(!testInterface(rtOpts->ifaceName, rtOpts))
 834                 return FALSE;
 835 
 836         netPath->interfaceInfo.addressFamily = AF_INET;
 837 
 838         /* the if is here only to get rid of an unused result warning. */
 839         if( getInterfaceInfo(rtOpts->ifaceName, &netPath->interfaceInfo)!= 1)
 840                 return FALSE;
 841 
 842         /* No HW address, we'll use the protocol address to form interfaceID -> clockID */
 843         if( !netPath->interfaceInfo.hasHwAddress && netPath->interfaceInfo.hasAfAddress ) {
 844                 uint32_t addr = netPath->interfaceInfo.afAddress.s_addr;
 845                 memcpy(netPath->interfaceID, &addr, 2);
 846                 memcpy(netPath->interfaceID + 4, &addr + 2, 2);
 847         /* Initialise interfaceID with hardware address */
 848         } else {
 849                     memcpy(&netPath->interfaceID, &netPath->interfaceInfo.hwAddress, 
 850                             sizeof(netPath->interfaceID) <= sizeof(netPath->interfaceInfo.hwAddress) ?
 851                                     sizeof(netPath->interfaceID) : sizeof(netPath->interfaceInfo.hwAddress)
 852                             );
 853         }
 854 
 855         DBG("Listening on IP: %s\n",inet_ntoa(netPath->interfaceInfo.afAddress));
 856 
 857 #ifdef PTPD_PCAP
 858         if (rtOpts->pcap == TRUE) {
 859                 int promisc = (rtOpts->transport == IEEE_802_3 ) ? 1 : 0;
 860                 if ((netPath->pcapEvent = pcap_open_live(rtOpts->ifaceName,
 861                                                          PACKET_SIZE, promisc,
 862                                                          PCAP_TIMEOUT,
 863                                                          errbuf)) == NULL) {
 864                         PERROR("failed to open event pcap");
 865                         return FALSE;
 866                 }
 867                 if (pcap_compile(netPath->pcapEvent, &program, 
 868                                  ( rtOpts->transport == IEEE_802_3 ) ?
 869                                     "ether proto 0x88f7":
 870                                  ( rtOpts->ip_mode != IPMODE_MULTICAST ) ?
 871                                          "udp port 319" :
 872                                  "host (224.0.1.129 or 224.0.0.107) and udp port 319" ,
 873                                  1, 0) < 0) {
 874                         PERROR("failed to compile pcap event filter");
 875                         pcap_perror(netPath->pcapEvent, "ptpd2");
 876                         return FALSE;
 877                 }
 878                 if (pcap_setfilter(netPath->pcapEvent, &program) < 0) {
 879                         PERROR("failed to set pcap event filter");
 880                         return FALSE;
 881                 }
 882                 pcap_freecode(&program);
 883                 if ((netPath->pcapEventSock = 
 884                      pcap_get_selectable_fd(netPath->pcapEvent)) < 0) {
 885                         PERROR("failed to get pcap event fd");
 886                         return FALSE;
 887                 }               
 888                 if ((netPath->pcapGeneral = pcap_open_live(rtOpts->ifaceName,
 889                                                            PACKET_SIZE, promisc,
 890                                                            PCAP_TIMEOUT,
 891                                                          errbuf)) == NULL) {
 892                         PERROR("failed to open general pcap");
 893                         return FALSE;
 894                 }
 895                 if (rtOpts->transport != IEEE_802_3) {
 896                         if (pcap_compile(netPath->pcapGeneral, &program,
 897                                          ( rtOpts->ip_mode != IPMODE_MULTICAST ) ?
 898                                                  "udp port 320" :
 899                                          "host (224.0.1.129 or 224.0.0.107) and udp port 320" ,
 900                                          1, 0) < 0) {
 901                                 PERROR("failed to compile pcap general filter");
 902                                 pcap_perror(netPath->pcapGeneral, "ptpd2");
 903                                 return FALSE;
 904                         }
 905                         if (pcap_setfilter(netPath->pcapGeneral, &program) < 0) {
 906                                 PERROR("failed to set pcap general filter");
 907                                 return FALSE;
 908                         }
 909                         pcap_freecode(&program);
 910                         if ((netPath->pcapGeneralSock = 
 911                              pcap_get_selectable_fd(netPath->pcapGeneral)) < 0) {
 912                                 PERROR("failed to get pcap general fd");
 913                                 return FALSE;
 914                         }
 915                 }
 916         }
 917 #endif
 918 
 919 #ifdef PTPD_PCAP
 920         if(rtOpts->transport == IEEE_802_3) {
 921                 close(netPath->eventSock);
 922                 netPath->eventSock = -1;
 923                 close(netPath->generalSock);
 924                 netPath->generalSock = -1;
 925                 /* TX timestamp is not generated for PCAP mode and Ethernet transport */
 926 #ifdef SO_TIMESTAMPING
 927                 netPath->txTimestampFailure = TRUE;
 928 #endif /* SO_TIMESTAMPING */
 929         } else {
 930 #endif
 931                 /* save interface address for IGMP refresh */
 932                 netPath->interfaceAddr = netPath->interfaceInfo.afAddress;
 933 
 934                 DBG("Local IP address used : %s \n", inet_ntoa(netPath->interfaceInfo.afAddress));
 935 
 936                 temp = 1;                       /* allow address reuse */
 937                 if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_REUSEADDR, 
 938                                &temp, sizeof(int)) < 0
 939                     || setsockopt(netPath->generalSock, SOL_SOCKET, SO_REUSEADDR, 
 940                                   &temp, sizeof(int)) < 0) {
 941                         DBG("failed to set socket reuse\n");
 942                 }
 943                 /* bind sockets */
 944                 /*
 945                  * need INADDR_ANY to allow receipt of multi-cast and uni-cast
 946                  * messages
 947                  */
 948 
 949                 /* why??? */
 950                 if (rtOpts->pidAsClockId) {
 951                         if (inet_pton(AF_INET, DEFAULT_PTP_DOMAIN_ADDRESS, &addr.sin_addr) < 0) {
 952                                 PERROR("failed to convert address");
 953                                 return FALSE;
 954                         }
 955                 } else
 956                         addr.sin_addr.s_addr = htonl(INADDR_ANY);
 957 
 958                 addr.sin_family = AF_INET;
 959                 addr.sin_port = htons(PTP_EVENT_PORT);
 960                 if (bind(netPath->eventSock, (struct sockaddr *)&addr, 
 961                         sizeof(struct sockaddr_in)) < 0) {
 962                         PERROR("failed to bind event socket");
 963                         return FALSE;
 964                 }
 965                 addr.sin_port = htons(PTP_GENERAL_PORT);
 966                 if (bind(netPath->generalSock, (struct sockaddr *)&addr, 
 967                         sizeof(struct sockaddr_in)) < 0) {
 968                         PERROR("failed to bind general socket");
 969                         return FALSE;
 970                 }
 971 
 972 #ifdef USE_BINDTODEVICE
 973 #ifdef linux
 974                 /*
 975                  * The following code makes sure that the data is only
 976                  * received on the specified interface.  Without this option,
 977                  * it's possible to receive PTP from another interface, and
 978                  * confuse the protocol.  Calling bind() with the IP address
 979                  * of the device instead of INADDR_ANY does not work.
 980                  *
 981                  * More info:
 982                  *   http://developerweb.net/viewtopic.php?id=6471
 983                  *   http://stackoverflow.com/questions/1207746/problems-with-so-bindtodevice-linux-socket-option
 984                  */
 985 
 986                 if ( rtOpts->ip_mode != IPMODE_HYBRID )
 987                 if (setsockopt(netPath->eventSock, SOL_SOCKET, SO_BINDTODEVICE,
 988                                 rtOpts->ifaceName, strlen(rtOpts->ifaceName)) < 0
 989                         || setsockopt(netPath->generalSock, SOL_SOCKET, SO_BINDTODEVICE,
 990                                 rtOpts->ifaceName, strlen(rtOpts->ifaceName)) < 0){
 991                         PERROR("failed to call SO_BINDTODEVICE on the interface");
 992                         return FALSE;
 993                 }
 994 #endif
 995 #endif
 996 
 997                 /* Set socket dscp */
 998                 if(rtOpts->dscpValue) {
 999 
1000                         if (setsockopt(netPath->eventSock, IPPROTO_IP, IP_TOS,
1001                                  &rtOpts->dscpValue, sizeof(int)) < 0
1002                             || setsockopt(netPath->generalSock, IPPROTO_IP, IP_TOS,
1003                                 &rtOpts->dscpValue, sizeof(int)) < 0) {
1004                                     PERROR("Failed to set socket DSCP bits");
1005                                     return FALSE;
1006                                 }
1007                 }
1008 
1009                 /* send a uni-cast address if specified (useful for testing) */
1010                 if(!hostLookup(rtOpts->unicastAddress, &netPath->unicastAddr)) {
1011                         netPath->unicastAddr = 0;
1012                 }
1013 
1014 
1015                 if(rtOpts->ip_mode != IPMODE_UNICAST)  {
1016 
1017                         /* init UDP Multicast on both Default and Peer addresses */
1018                         if (!netInitMulticast(netPath, rtOpts))
1019                                 return FALSE;
1020 
1021                         /* set socket time-to-live  */
1022                         if(!netSetMulticastTTL(netPath->eventSock,rtOpts->ttl) ||
1023                             !netSetMulticastTTL(netPath->generalSock,rtOpts->ttl))
1024                                 return FALSE;
1025 
1026                         /* start tracking TTL */
1027                         netPath->ttlEvent = rtOpts->ttl;
1028                         netPath->ttlGeneral = rtOpts->ttl;
1029                 }
1030 
1031 #ifdef SO_TIMESTAMPING
1032                         /* Reset the failure indicator when (re)starting network */
1033                         netPath->txTimestampFailure = FALSE;
1034                         /* for SO_TIMESTAMPING we're receiving transmitted packets via ERRQUEUE */
1035                         temp = 0;
1036 #else
1037                         /* enable loopback */
1038                         temp = 1;
1039 #endif
1040 
1041                 /* make timestamps available through recvmsg() */
1042                 if (!netInitTimestamping(netPath,rtOpts)) {
1043                         ERROR("Failed to enable packet time stamping\n");
1044                         return FALSE;
1045                 }
1046 
1047 #ifdef SO_TIMESTAMPING
1048                 /* If we failed to initialise SO_TIMESTAMPING, enable mcast loopback */
1049                 if(netPath->txTimestampFailure)
1050                         temp = 1;
1051 #endif
1052 
1053                         if(!netSetMulticastLoopback(netPath, temp)) {
1054                                 return FALSE;
1055                         }
1056 
1057 #ifdef PTPD_PCAP
1058         }
1059 #endif
1060 
1061         /* Compile ACLs */
1062         if(rtOpts->timingAclEnabled) {
1063                 freeIpv4AccessList(&netPath->timingAcl);
1064                 netPath->timingAcl=createIpv4AccessList(rtOpts->timingAclPermitText,
1065                         rtOpts->timingAclDenyText, rtOpts->timingAclOrder);
1066         }
1067         if(rtOpts->managementAclEnabled) {
1068                 freeIpv4AccessList(&netPath->managementAcl);
1069                 netPath->managementAcl=createIpv4AccessList(rtOpts->managementAclPermitText,
1070                         rtOpts->managementAclDenyText, rtOpts->managementAclOrder);
1071         }
1072 
1073         return TRUE;
1074 }
1075 
1076 /*Check if data has been received*/
1077 int 
1078 netSelect(TimeInternal * timeout, NetPath * netPath, fd_set *readfds)
1079 {
1080         int ret, nfds;
1081         struct timeval tv, *tv_ptr;
1082 
1083 
1084 #if defined PTPD_SNMP
1085         extern RunTimeOpts rtOpts;
1086         struct timeval snmp_timer_wait = { 0, 0}; // initialise to avoid unused warnings when SNMP disabled
1087         int snmpblock = 0;
1088 #endif
1089 
1090         if (timeout) {
1091                 if(isTimeInternalNegative(timeout)) {
1092                         ERROR("Negative timeout attempted for select()\n");
1093                         return -1;
1094                 }
1095                 tv.tv_sec = timeout->seconds;
1096                 tv.tv_usec = timeout->nanoseconds / 1000;
1097                 tv_ptr = &tv;
1098         } else {
1099                 tv_ptr = NULL;
1100         }
1101 
1102         FD_ZERO(readfds);
1103         nfds = 0;
1104 #ifdef PTPD_PCAP
1105         if (netPath->pcapEventSock >= 0) {
1106                 FD_SET(netPath->pcapEventSock, readfds);
1107                 if (netPath->pcapGeneralSock >= 0)
1108                         FD_SET(netPath->pcapGeneralSock, readfds);
1109 
1110                 nfds = netPath->pcapEventSock;
1111                 if (netPath->pcapEventSock < netPath->pcapGeneralSock)
1112                         nfds = netPath->pcapGeneralSock;
1113 
1114         } else if (netPath->eventSock >= 0) {
1115 #endif
1116                 FD_SET(netPath->eventSock, readfds);
1117                 if (netPath->generalSock >= 0)
1118                         FD_SET(netPath->generalSock, readfds);
1119 
1120                 nfds = netPath->eventSock;
1121                 if (netPath->eventSock < netPath->generalSock)
1122                         nfds = netPath->generalSock;
1123 #ifdef PTPD_PCAP
1124         }
1125 #endif
1126         nfds++;
1127 
1128 #if defined PTPD_SNMP
1129 if (rtOpts.snmp_enabled) {
1130         snmpblock = 1;
1131         if (tv_ptr) {
1132                 snmpblock = 0;
1133                 memcpy(&snmp_timer_wait, tv_ptr, sizeof(struct timeval));
1134         }
1135         snmp_select_info(&nfds, readfds, &snmp_timer_wait, &snmpblock);
1136         if (snmpblock == 0)
1137                 tv_ptr = &snmp_timer_wait;
1138 }
1139 #endif
1140 
1141         ret = select(nfds, readfds, 0, 0, tv_ptr);
1142 
1143         if (ret < 0) {
1144                 if (errno == EAGAIN || errno == EINTR)
1145                         return 0;
1146         }
1147 #if defined PTPD_SNMP
1148 if (rtOpts.snmp_enabled) {
1149         /* Maybe we have received SNMP related data */
1150         if (ret > 0) {
1151                 snmp_read(readfds);
1152         } else if (ret == 0) {
1153                 snmp_timeout();
1154                 run_alarms();
1155         }
1156         netsnmp_check_outstanding_agent_requests();
1157 }
1158 #endif
1159         return ret;
1160 }
1161 
1162 /** 
1163  * store received data from network to "buf" , get and store the
1164  * SO_TIMESTAMP value in "time" for an event message
1165  *
1166  * @note Should this function be merged with netRecvGeneral(), below?
1167  * Jan Breuer: I think that netRecvGeneral should be
1168  * simplified. Timestamp returned by this function is never
1169  * used. According to this, netInitTimestamping can be also simplified
1170  * to initialize timestamping only on eventSock.
1171  *
1172  * @param buf 
1173  * @param time 
1174  * @param netPath 
1175  *
1176  * @return
1177  */
1178 
1179 ssize_t 
1180 netRecvEvent(Octet * buf, TimeInternal * time, NetPath * netPath, int flags)
1181 {
1182         ssize_t ret = 0;
1183         struct msghdr msg;
1184         struct iovec vec[1];
1185         struct sockaddr_in from_addr;
1186 
1187 #ifdef PTPD_PCAP
1188         struct pcap_pkthdr *pkt_header;
1189         const u_char *pkt_data;
1190 #endif
1191 
1192         union {
1193                 struct cmsghdr cm;
1194                 char    control[256];
1195         }     cmsg_un;
1196 
1197         struct cmsghdr *cmsg;
1198 
1199 #if defined(SO_TIMESTAMPNS) || defined(SO_TIMESTAMPING)
1200         struct timespec * ts;
1201 #elif defined(SO_BINTIME)
1202         struct bintime * bt;
1203         struct timespec ts;
1204 #endif
1205         
1206 #if defined(SO_TIMESTAMP)
1207         struct timeval * tv;
1208 #endif
1209         Boolean timestampValid = FALSE;
1210 
1211 #ifdef PTPD_PCAP
1212         if (netPath->pcapEvent == NULL) { /* Using sockets */
1213 #endif
1214                 vec[0].iov_base = buf;
1215                 vec[0].iov_len = PACKET_SIZE;
1216 
1217                 memset(&msg, 0, sizeof(msg));
1218                 memset(&from_addr, 0, sizeof(from_addr));
1219                 memset(buf, 0, PACKET_SIZE);
1220                 memset(&cmsg_un, 0, sizeof(cmsg_un));
1221 
1222                 msg.msg_name = (caddr_t)&from_addr;
1223                 msg.msg_namelen = sizeof(from_addr);
1224                 msg.msg_iov = vec;
1225                 msg.msg_iovlen = 1;
1226                 msg.msg_control = cmsg_un.control;
1227                 msg.msg_controllen = sizeof(cmsg_un.control);
1228                 msg.msg_flags = 0;
1229 
1230                 ret = recvmsg(netPath->eventSock, &msg, flags | MSG_DONTWAIT);
1231                 if (ret <= 0) {
1232                         if (errno == EAGAIN || errno == EINTR)
1233                                 return 0;
1234 
1235                         return ret;
1236                 };
1237                 if (msg.msg_flags & MSG_TRUNC) {
1238                         ERROR("received truncated message\n");
1239                         return 0;
1240                 }
1241                 /* get time stamp of packet */
1242                 if (!time) {
1243                         ERROR("null receive time stamp argument\n");
1244                         return 0;
1245                 }
1246                 if (msg.msg_flags & MSG_CTRUNC) {
1247                         ERROR("received truncated ancillary data\n");
1248                         return 0;
1249                 }
1250 
1251 #if defined(HAVE_DECL_MSG_ERRQUEUE) && HAVE_DECL_MSG_ERRQUEUE
1252                 if(!(flags & MSG_ERRQUEUE))
1253 #endif
1254                         netPath->lastRecvAddr = from_addr.sin_addr.s_addr;
1255                 netPath->receivedPackets++;
1256 
1257                 if (msg.msg_controllen <= 0) {
1258                         ERROR("received short ancillary data (%ld/%ld)\n",
1259                               (long)msg.msg_controllen, (long)sizeof(cmsg_un.control));
1260 
1261                         return 0;
1262                 }
1263 
1264                 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
1265                      cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1266                         if (cmsg->cmsg_level == SOL_SOCKET) {
1267 #if defined(SO_TIMESTAMPING) && defined(SO_TIMESTAMPNS)
1268                                 if(cmsg->cmsg_type == SO_TIMESTAMPING || 
1269                                     cmsg->cmsg_type == SO_TIMESTAMPNS) {
1270                                         ts = (struct timespec *)CMSG_DATA(cmsg);
1271                                         time->seconds = ts->tv_sec;
1272                                         time->nanoseconds = ts->tv_nsec;
1273                                         timestampValid = TRUE;
1274                                         DBG("rcvevent: SO_TIMESTAMP%s %s time stamp: %us %dns\n", netPath->txTimestampFailure ?
1275                                             "NS" : "ING",
1276                                             (flags & MSG_ERRQUEUE) ? "(TX)" : "(RX)" , time->seconds, time->nanoseconds);
1277                                         break;
1278                                 }
1279 #elif defined(SO_TIMESTAMPNS)
1280                                 if(cmsg->cmsg_type == SCM_TIMESTAMPNS) {
1281                                         ts = (struct timespec *)CMSG_DATA(cmsg);
1282                                         time->seconds = ts->tv_sec;
1283                                         time->nanoseconds = ts->tv_nsec;
1284                                         timestampValid = TRUE;
1285                                         DBGV("kernel NANO recv time stamp %us %dns\n", 
1286                                              time->seconds, time->nanoseconds);
1287                                         break;
1288                                 }
1289 #elif defined(SO_BINTIME)
1290                                 if(cmsg->cmsg_type == SCM_BINTIME) {
1291                                         bt = (struct bintime *)CMSG_DATA(cmsg);
1292                                         bintime2timespec(bt, &ts);
1293                                         time->seconds = ts.tv_sec;
1294                                         time->nanoseconds = ts.tv_nsec;
1295                                         timestampValid = TRUE;
1296                                         DBGV("kernel NANO recv time stamp %us %dns\n",
1297                                              time->seconds, time->nanoseconds);
1298                                         break;
1299                                 }
1300 #endif
1301                         
1302 #if defined(SO_TIMESTAMP)
1303                                 if(cmsg->cmsg_type == SCM_TIMESTAMP) {
1304                                         tv = (struct timeval *)CMSG_DATA(cmsg);
1305                                         time->seconds = tv->tv_sec;
1306                                         time->nanoseconds = tv->tv_usec * 1000;
1307                                         timestampValid = TRUE;
1308                                         DBGV("kernel MICRO recv time stamp %us %dns\n",
1309                                              time->seconds, time->nanoseconds);
1310                                 }
1311 #endif
1312                         }
1313                 }
1314 
1315                 if (!timestampValid) {
1316                         /*
1317                          * do not try to get by with recording the time here, better
1318                          * to fail because the time recorded could be well after the
1319                          * message receive, which would put a big spike in the
1320                          * offset signal sent to the clock servo
1321                          */
1322                         DBG("netRecvEvent: no receive time stamp\n");
1323                         return 0;
1324                 }
1325 #ifdef PTPD_PCAP
1326         }
1327 #endif
1328 
1329 #ifdef PTPD_PCAP
1330         else { /* Using PCAP */
1331                 /* Discard packet on socket */
1332                 if (netPath->eventSock >= 0) {
1333                         recv(netPath->eventSock, buf, PACKET_SIZE, MSG_DONTWAIT);
1334                 }
1335                 
1336                 if ((ret = pcap_next_ex(netPath->pcapEvent, &pkt_header, 
1337                                         &pkt_data)) < 1) {
1338                         if (ret < 0)
1339                                 DBGV("netRecvEvent: pcap_next_ex failed %s\n",
1340                                      pcap_geterr(netPath->pcapEvent));
1341                         return 0;
1342                 }
1343 
1344         /* Make sure this is IP (could dot1q get here?) */
1345         if( ntohs(*(u_short *)(pkt_data + 12)) != ETHERTYPE_IP)
1346                 DBGV("PCAP payload received is not Ethernet: 0x%04x\n",
1347                     ntohs(*(u_short *)(pkt_data + 12)));
1348         /* Retrieve source IP from the payload - 14 eth + 12 IP */
1349         netPath->lastRecvAddr = *(Integer32 *)(pkt_data + 26);
1350 
1351                 netPath->receivedPackets++;
1352                 /* XXX Total cheat */
1353                 memcpy(buf, pkt_data + netPath->headerOffset, 
1354                        pkt_header->caplen - netPath->headerOffset);
1355                 time->seconds = pkt_header->ts.tv_sec;
1356                 time->nanoseconds = pkt_header->ts.tv_usec * 1000;
1357                 timestampValid = TRUE;
1358                 DBGV("netRecvEvent: kernel PCAP recv time stamp %us %dns\n",
1359                      time->seconds, time->nanoseconds);
1360                 fflush(NULL);
1361                 ret = pkt_header->caplen - netPath->headerOffset;
1362         }
1363 #endif
1364         return ret;
1365 }
1366 
1367 
1368 
1369 /** 
1370  * 
1371  * store received data from network to "buf" get and store the
1372  * SO_TIMESTAMP value in "time" for a general message
1373  * 
1374  * @param buf 
1375  * @param time 
1376  * @param netPath 
1377  * 
1378  * @return 
1379  */
1380 
1381 ssize_t 
1382 netRecvGeneral(Octet * buf, NetPath * netPath)
1383 {
1384         ssize_t ret = 0;
1385         struct sockaddr_in from_addr;
1386 
1387 #ifdef PTPD_PCAP
1388         struct pcap_pkthdr *pkt_header;
1389         const u_char *pkt_data;
1390 #endif
1391         socklen_t from_addr_len = sizeof(from_addr);
1392 
1393 #ifdef PTPD_PCAP
1394         if (netPath->pcapGeneral == NULL) {
1395 #endif
1396                 ret=recvfrom(netPath->generalSock, buf, PACKET_SIZE, MSG_DONTWAIT, (struct sockaddr*)&from_addr, &from_addr_len);
1397                 netPath->lastRecvAddr = from_addr.sin_addr.s_addr;
1398                 return ret;
1399 #ifdef PTPD_PCAP
1400         }
1401 #endif
1402 
1403 #ifdef PTPD_PCAP
1404         else { /* Using PCAP */
1405                 /* Discard packet on socket */
1406                 if (netPath->generalSock >= 0)
1407                         recv(netPath->generalSock, buf, PACKET_SIZE, MSG_DONTWAIT);
1408 
1409                 
1410                 if (( ret = pcap_next_ex(netPath->pcapGeneral, &pkt_header, 
1411                                          &pkt_data)) < 1) {
1412                         if (ret < 0) 
1413                                 DBGV("netRecvGeneral: pcap_next_ex failed %d %s\n",
1414                                      ret, pcap_geterr(netPath->pcapGeneral));
1415                         return 0;
1416                 }
1417         /* Make sure this is IP (could dot1q get here?) */
1418         if( ntohs(*(u_short *)(pkt_data + 12)) != ETHERTYPE_IP)
1419                 DBGV("PCAP payload received is not Ethernet: 0x%04x\n",
1420                         ntohs(*(u_short *)(pkt_data + 12)));
1421         /* Retrieve source IP from the payload - 14 eth + 12 IP src*/
1422         netPath->lastRecvAddr = *(Integer32 *)(pkt_data + 26);
1423 
1424                 netPath->receivedPackets++;
1425                 /* XXX Total cheat */
1426                 memcpy(buf, pkt_data + netPath->headerOffset, 
1427                        pkt_header->caplen - netPath->headerOffset);
1428                 fflush(NULL);
1429                 ret = pkt_header->caplen - netPath->headerOffset;
1430         }
1431 #endif
1432         return ret;
1433 }
1434 
1435 
1436 #ifdef PTPD_PCAP
1437 ssize_t
1438 netSendPcapEther(Octet * buf,  UInteger16 length,
1439                         struct ether_addr * dst, struct ether_addr * src,
1440                         pcap_t * pcap) {
1441         Octet ether[ETHER_HDR_LEN + PACKET_SIZE];
1442 #ifdef HAVE_STRUCT_ETHER_ADDR_OCTET
1443         memcpy(ether, dst->octet, ETHER_ADDR_LEN);
1444         memcpy(ether + ETHER_ADDR_LEN, src->octet, ETHER_ADDR_LEN);
1445 #else
1446         memcpy(ether, dst->ether_addr_octet, ETHER_ADDR_LEN);
1447         memcpy(ether + ETHER_ADDR_LEN, src->ether_addr_octet, ETHER_ADDR_LEN);
1448 #endif /* HAVE_STRUCT_ETHER_ADDR_OCTET */
1449         *((short *)&ether[2 * ETHER_ADDR_LEN]) = htons(PTP_ETHER_TYPE);
1450         memcpy(ether + ETHER_HDR_LEN, buf, length);
1451 
1452         return pcap_inject(pcap, ether, ETHER_HDR_LEN + length);
1453 }
1454 #endif
1455 
1456 //
1457 // alt_dst: alternative destination.
1458 //   if filled, send to this unicast dest;
1459 //   if zero, do the normal operation (send to unicast with -u, or send to the multcast group)
1460 //
1461 ///
1462 /// TODO: merge these 2 functions into one
1463 ///
1464 ssize_t 
1465 netSendEvent(Octet * buf, UInteger16 length, NetPath * netPath,
1466              RunTimeOpts *rtOpts, Integer32 alt_dst, TimeInternal * tim)
1467 {
1468         ssize_t ret;
1469         struct sockaddr_in addr;
1470 
1471         addr.sin_family = AF_INET;
1472         addr.sin_port = htons(PTP_EVENT_PORT);
1473 
1474 #ifdef PTPD_PCAP
1475         /* In PCAP Ethernet mode, we use pcapEvent for receiving all messages 
1476          * and pcapGeneral for sending all messages
1477          */
1478         if ((netPath->pcapGeneral != NULL) && (rtOpts->transport == IEEE_802_3 )) {
1479                 ret = netSendPcapEther(buf, length,
1480                         &netPath->etherDest,
1481                         (struct ether_addr *)netPath->interfaceID,
1482                         netPath->pcapGeneral);
1483                 
1484                 if (ret <= 0) 
1485                         DBG("Error sending ether multicast event message\n");
1486                 else
1487                         netPath->sentPackets++;
1488         } else {
1489 #endif
1490                 if (netPath->unicastAddr || alt_dst ) {
1491                         if (netPath->unicastAddr) {
1492                                 addr.sin_addr.s_addr = netPath->unicastAddr;
1493                         } else {
1494                                 addr.sin_addr.s_addr = alt_dst;
1495                         }
1496 
1497                         /*
1498                          * This function is used for PTP only anyway...
1499                          * If we're sending to a unicast address, set the UNICAST flag.
1500                          */
1501                         *(char *)(buf + 6) |= PTP_UNICAST;
1502 
1503                         ret = sendto(netPath->eventSock, buf, length, 0, 
1504                                      (struct sockaddr *)&addr, 
1505                                      sizeof(struct sockaddr_in));
1506                         if (ret <= 0)
1507                                 DBG("Error sending unicast event message\n");
1508                         else
1509                                 netPath->sentPackets++;
1510 #ifndef SO_TIMESTAMPING
1511                         /* 
1512                          * Need to forcibly loop back the packet since
1513                          * we are not using multicast. 
1514                          */
1515 
1516                         addr.sin_addr.s_addr = netPath->interfaceAddr.s_addr;
1517                         ret = sendto(netPath->eventSock, buf, length, 0, 
1518                                      (struct sockaddr *)&addr, 
1519                                      sizeof(struct sockaddr_in));
1520                         if (ret <= 0)
1521                                 DBG("Error looping back unicast event message\n");
1522 #else
1523                         if(!netPath->txTimestampFailure) {
1524                                 if(!getTxTimestamp(netPath, tim)) {
1525                                         netPath->txTimestampFailure = TRUE;
1526                                         if (tim) {
1527                                                 clearTime(tim);
1528                                         }
1529                                 }
1530                         }
1531 
1532                         if(netPath->txTimestampFailure)
1533                         {
1534                                 /* We've had a TX timestamp receipt timeout - falling back to packet looping */
1535                                 addr.sin_addr.s_addr = netPath->interfaceAddr.s_addr;
1536                                 ret = sendto(netPath->eventSock, buf, length, 0, 
1537                                      (struct sockaddr *)&addr, 
1538                                      sizeof(struct sockaddr_in));
1539                                 if (ret <= 0)
1540                                         DBG("Error looping back unicast event message\n");
1541                         }
1542 #endif /* SO_TIMESTAMPING */            
1543                 } else {
1544                         addr.sin_addr.s_addr = netPath->multicastAddr;
1545                         /* Is TTL OK? */
1546                         if(netPath->ttlEvent != rtOpts->ttl) {
1547                                 /* Try restoring TTL */
1548                         /* set socket time-to-live  */
1549                         if (netSetMulticastTTL(netPath->eventSock,rtOpts->ttl)) {
1550                                     netPath->ttlEvent = rtOpts->ttl;
1551                                 }
1552                         }
1553                         ret = sendto(netPath->eventSock, buf, length, 0, 
1554                                      (struct sockaddr *)&addr, 
1555                                      sizeof(struct sockaddr_in));
1556                         if (ret <= 0)
1557                                 DBG("Error sending multicast event message\n");
1558                         else
1559                                 netPath->sentPackets++;
1560 #ifdef SO_TIMESTAMPING
1561                         if(!netPath->txTimestampFailure) {
1562                                 if(!getTxTimestamp(netPath, tim)) {
1563                                         if (tim) {
1564                                                 clearTime(tim);
1565                                         }
1566                                         
1567                                         netPath->txTimestampFailure = TRUE;
1568 
1569                                         /* Try re-enabling MULTICAST_LOOP */
1570                                         netSetMulticastLoopback(netPath, TRUE);
1571                                 }
1572                         }
1573 #endif /* SO_TIMESTAMPING */
1574                 }
1575 
1576 #ifdef PTPD_PCAP
1577         }
1578 #endif
1579         return ret;
1580 }
1581 
1582 ssize_t 
1583 netSendGeneral(Octet * buf, UInteger16 length, NetPath * netPath,
1584                RunTimeOpts *rtOpts, Integer32 alt_dst)
1585 {
1586         ssize_t ret;
1587         struct sockaddr_in addr;
1588 
1589         addr.sin_family = AF_INET;
1590         addr.sin_port = htons(PTP_GENERAL_PORT);
1591 
1592 #ifdef PTPD_PCAP
1593         if ((netPath->pcapGeneral != NULL) && (rtOpts->transport == IEEE_802_3)) {
1594                 ret = netSendPcapEther(buf, length,
1595                         &netPath->etherDest,
1596                         (struct ether_addr *)netPath->interfaceID,
1597                         netPath->pcapGeneral);
1598 
1599                 if (ret <= 0) 
1600                         DBG("Error sending ether multicast general message\n");
1601                 else
1602                         netPath->sentPackets++;
1603         } else {
1604 #endif
1605                 if(netPath->unicastAddr || alt_dst ){
1606                         if (netPath->unicastAddr) {
1607                                 addr.sin_addr.s_addr = netPath->unicastAddr;
1608                         } else {
1609                                 addr.sin_addr.s_addr = alt_dst;
1610                         }
1611 
1612                         /*
1613                          * This function is used for PTP only anyway...
1614                          * If we're sending to a unicast address, set the UNICAST flag.
1615                          */
1616                         *(char *)(buf + 6) |= PTP_UNICAST;
1617 
1618                         ret = sendto(netPath->generalSock, buf, length, 0, 
1619                                      (struct sockaddr *)&addr, 
1620                                      sizeof(struct sockaddr_in));
1621                         if (ret <= 0)
1622                                 DBG("Error sending unicast general message\n");
1623                         else
1624                                 netPath->sentPackets++;
1625                 } else {
1626                         addr.sin_addr.s_addr = netPath->multicastAddr;
1627 
1628                         /* Is TTL OK? */
1629                         if(netPath->ttlGeneral != rtOpts->ttl) {
1630                                 /* Try restoring TTL */
1631                                 if (netSetMulticastTTL(netPath->generalSock,rtOpts->ttl)) {
1632                                     netPath->ttlGeneral = rtOpts->ttl;
1633                                 }
1634                         }
1635 
1636                         ret = sendto(netPath->generalSock, buf, length, 0, 
1637                                      (struct sockaddr *)&addr, 
1638                                      sizeof(struct sockaddr_in));
1639                         if (ret <= 0)
1640                                 DBG("Error sending multicast general message\n");
1641                         else
1642                                 netPath->sentPackets++;
1643                 }
1644 
1645 #ifdef PTPD_PCAP
1646         }
1647 #endif
1648         return ret;
1649 }
1650 
1651 ssize_t 
1652 netSendPeerGeneral(Octet * buf, UInteger16 length, NetPath * netPath, RunTimeOpts *rtOpts)
1653 {
1654 
1655         ssize_t ret;
1656         struct sockaddr_in addr;
1657 
1658         addr.sin_family = AF_INET;
1659         addr.sin_port = htons(PTP_GENERAL_PORT);
1660 
1661 #ifdef PTPD_PCAP
1662         if ((netPath->pcapGeneral != NULL) && (rtOpts->transport == IEEE_802_3)) {
1663                 ret = netSendPcapEther(buf, length,
1664                         &netPath->peerEtherDest,
1665                         (struct ether_addr *)netPath->interfaceID,
1666                         netPath->pcapGeneral);
1667 
1668                 if (ret <= 0) 
1669                         DBG("error sending ether multi-cast general message\n");
1670         } else if (netPath->unicastAddr)
1671 #else
1672         if (netPath->unicastAddr)
1673 #endif
1674         {
1675                 addr.sin_addr.s_addr = netPath->unicastAddr;
1676 
1677                 ret = sendto(netPath->generalSock, buf, length, 0, 
1678                              (struct sockaddr *)&addr, 
1679                              sizeof(struct sockaddr_in));
1680                 if (ret <= 0)
1681                         DBG("Error sending unicast peer general message\n");
1682 
1683         } else {
1684                 addr.sin_addr.s_addr = netPath->peerMulticastAddr;
1685                 
1686                 /* is TTL already 1 ? */
1687                 if(netPath->ttlGeneral != 1) {
1688                         /* Try setting TTL to 1 */
1689                         if (netSetMulticastTTL(netPath->generalSock,1)) {
1690                                 netPath->ttlGeneral = 1;
1691                         }
1692                 }
1693                 ret = sendto(netPath->generalSock, buf, length, 0, 
1694                              (struct sockaddr *)&addr, 
1695                              sizeof(struct sockaddr_in));
1696                 if (ret <= 0)
1697                         DBG("Error sending multicast peer general message\n");
1698         }
1699 
1700         if (ret > 0)
1701                 netPath->sentPackets++;
1702         
1703         return ret;
1704 
1705 }
1706 
1707 ssize_t 
1708 netSendPeerEvent(Octet * buf, UInteger16 length, NetPath * netPath, RunTimeOpts *rtOpts, TimeInternal * tim)
1709 {
1710         ssize_t ret;
1711         struct sockaddr_in addr;
1712 
1713         addr.sin_family = AF_INET;
1714         addr.sin_port = htons(PTP_EVENT_PORT);
1715 
1716 #ifdef PTPD_PCAP
1717         if ((netPath->pcapGeneral != NULL) && (rtOpts->transport == IEEE_802_3)) {
1718                 ret = netSendPcapEther(buf, length,
1719                         &netPath->peerEtherDest,
1720                         (struct ether_addr *)netPath->interfaceID,
1721                         netPath->pcapGeneral);
1722 
1723                 if (ret <= 0) 
1724                         DBG("error sending ether multi-cast general message\n");
1725         } else if (netPath->unicastAddr)
1726 #else
1727         if (netPath->unicastAddr)
1728 #endif
1729         {
1730                 addr.sin_addr.s_addr = netPath->unicastAddr;
1731 
1732                 ret = sendto(netPath->eventSock, buf, length, 0, 
1733                              (struct sockaddr *)&addr, 
1734                              sizeof(struct sockaddr_in));
1735                 if (ret <= 0)
1736                         DBG("Error sending unicast peer event message\n");
1737                 else
1738                         netPath->sentPackets++;
1739 
1740 #ifndef SO_TIMESTAMPING
1741                 /* 
1742                  * Need to forcibly loop back the packet since
1743                  * we are not using multicast. 
1744                  */
1745                 addr.sin_addr.s_addr = netPath->interfaceAddr.s_addr;
1746                 
1747                 ret = sendto(netPath->eventSock, buf, length, 0, 
1748                              (struct sockaddr *)&addr, 
1749                              sizeof(struct sockaddr_in));
1750                 if (ret <= 0)
1751                         DBG("Error looping back unicast peer event message\n");
1752 #else
1753                 if(!netPath->txTimestampFailure) {
1754                         if(!getTxTimestamp(netPath, tim)) {
1755                                 netPath->txTimestampFailure = TRUE;
1756                                 if (tim) {
1757                                         clearTime(tim);
1758                                 }
1759                         }
1760                 }
1761 
1762                 if(netPath->txTimestampFailure) {
1763                         /* We've had a TX timestamp receipt timeout - falling back to packet looping */
1764                         addr.sin_addr.s_addr = netPath->interfaceAddr.s_addr;
1765                         ret = sendto(netPath->eventSock, buf, length, 0, 
1766                                      (struct sockaddr *)&addr, 
1767                                      sizeof(struct sockaddr_in));
1768                         if (ret <= 0)
1769                                 DBG("Error looping back unicast event message\n");
1770                 }
1771 #endif /* SO_TIMESTAMPING */
1772 
1773         } else {
1774                 addr.sin_addr.s_addr = netPath->peerMulticastAddr;
1775 
1776                 /* is TTL already 1 ? */
1777                 if(netPath->ttlEvent != 1) {
1778                         /* Try setting TTL to 1 */
1779                         if (netSetMulticastTTL(netPath->eventSock,1)) {
1780                             netPath->ttlEvent = 1;
1781                         }
1782                 }
1783                 ret = sendto(netPath->eventSock, buf, length, 0, 
1784                              (struct sockaddr *)&addr, 
1785                              sizeof(struct sockaddr_in));
1786                 if (ret <= 0)
1787                         DBG("Error sending multicast peer event message\n");
1788                 else
1789                         netPath->sentPackets++;
1790 #ifdef SO_TIMESTAMPING
1791                 if(!netPath->txTimestampFailure) {
1792                         if(!getTxTimestamp(netPath, tim)) {
1793                                 if (tim) {
1794                                         clearTime(tim);
1795                                 }
1796                                         
1797                                 netPath->txTimestampFailure = TRUE;
1798 
1799                                 /* Try re-enabling MULTICAST_LOOP */
1800                                 netSetMulticastLoopback(netPath, TRUE);
1801                         }
1802                 }
1803 #endif /* SO_TIMESTAMPING */
1804         }
1805 
1806         if (ret > 0)
1807                 netPath->sentPackets++;
1808 
1809         return ret;
1810 }
1811 
1812 
1813 
1814 /*
1815  * refresh IGMP on a timeout
1816  */
1817 /*
1818  * @return TRUE if successful
1819  */
1820 Boolean
1821 netRefreshIGMP(NetPath * netPath, RunTimeOpts * rtOpts, PtpClock * ptpClock)
1822 {
1823         DBG("netRefreshIGMP\n");
1824         
1825         netShutdownMulticast(netPath);
1826         
1827         /* suspend process 100 milliseconds, to make sure the kernel sends the IGMP_leave properly */
1828         usleep(100*1000);
1829 
1830         if (!netInitMulticast(netPath, rtOpts)) {
1831                 return FALSE;
1832         }
1833         return TRUE;
1834 }