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