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 }
|