Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
P
PPSi
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
47
Issues
47
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
PPSi
Commits
ef9aa57f
Commit
ef9aa57f
authored
Feb 26, 2012
by
Alessandro Rubini
Committed by
Aurelio Colosimo
Mar 03, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tools: new dir with ptpdump program
parent
ff2cf609
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
419 additions
and
0 deletions
+419
-0
Makefile
tools/Makefile
+25
-0
decent_types.h
tools/decent_types.h
+68
-0
ptpdump.c
tools/ptpdump.c
+326
-0
No files found.
tools/Makefile
0 → 100644
View file @
ef9aa57f
# classic cross-compilation tool-set
AS
=
$(CROSS_COMPILE)
as
LD
=
$(CROSS_COMPILE)
ld
CC
=
$(CROSS_COMPILE)
gcc
CPP
=
$(CC)
-E
AR
=
$(CROSS_COMPILE)
ar
NM
=
$(CROSS_COMPILE)
nm
STRIP
=
$(CROSS_COMPILE)
strip
OBJCOPY
=
$(CROSS_COMPILE)
objcopy
OBJDUMP
=
$(CROSS_COMPILE)
objdump
CFLAGS
=
-Wall
-ggdb
-I
../include/pptp
PROGS
=
ptpdump
all
:
$(PROGS)
$(PROGS)
:
$(wildcard *.h) $(wildcard ../include/pptp/*.h)
%
:
%.c
$(CC)
$(CFLAGS)
$*
.c
$(LDFLAGS)
-o
$@
clean
:
rm
-f
$(PROGS)
*
.o
*
~
tools/decent_types.h
0 → 100644
View file @
ef9aa57f
/* copied from /usr/include/netinet/ip.h */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#elif __BYTE_ORDER == __BIG_ENDIAN
# error "big endian not supported, yet"
#else
# error "Please fix <bits/endian.h>"
#endif
/* Common Message header (table 18, page 124) -- was "MsgHeader */
struct
ptp_header
{
/* 0 */
unsigned
int
messageType
:
4
;
unsigned
int
transportSpecific
:
4
;
/* 1 */
unsigned
int
versionPTP
:
4
;
unsigned
int
reserved1
:
4
;
/* 2 */
uint16_t
messageLength
;
/* 4 */
uint8_t
domainNumber
;
uint8_t
reserved5
;
uint16_t
flagField
;
/* 8 */
uint64_t
correctionField
;
/* 16 */
uint32_t
reserved16
;
uint8_t
sourcePortIdentity
[
10
];
/* 30 */
uint16_t
sequenceId
;
uint8_t
controlField
;
uint8_t
logMessageInterval
;
}
__attribute__
((
packed
));
/* Fucking fucking ieee specification! */
struct
int48
{
uint16_t
msb
;
/* big endian in packet! */
uint32_t
lsb
;
}
__attribute__
((
packed
));
struct
stamp
{
struct
int48
sec
;
uint32_t
nsec
;
}
__attribute__
((
packed
));
/*
* What follows is structures for the individual message types
*/
struct
ptp_announce
{
/* page 129 (149 of pdf) */
struct
stamp
originTimestamp
;
/* 34 */
Integer16
currentUtcOffset
;
/* 44 */
uint8_t
reserved46
;
UInteger8
grandmasterPriority1
;
/* 47 */
ClockQuality
grandmasterClockQuality
;
/* 48 */
UInteger8
grandmasterPriority2
;
/* 52 */
ClockIdentity
grandmasterIdentity
;
/* 53 */
UInteger16
stepsRemoved
;
/* 61 */
Enumeration8
timeSource
;
/* 63 */
}
__attribute__
((
packed
));
struct
ptp_sync_etc
{
/* page 130 (150 of pdf) */
/* doc uses different names in different packets: use simple names */
struct
stamp
stamp
;
/* 34 */
uint8_t
port
[
10
];
/* 44: only for delay_resp etc */
};
tools/ptpdump.c
0 → 100644
View file @
ef9aa57f
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <linux/if_ether.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <ieee1588_types.h>
/* from ../include/pptp */
#include "decent_types.h"
#ifndef ETH_P_1588
#define ETH_P_1588 0x88F7
#endif
int
dumpstruct
(
FILE
*
dest
,
char
*
name
,
void
*
ptr
,
int
size
)
{
int
ret
,
i
;
unsigned
char
*
p
=
ptr
;
ret
=
fprintf
(
dest
,
"DUMP: %s at %p (size %i)
\n
"
,
name
,
ptr
,
size
);
for
(
i
=
0
;
i
<
size
;
)
{
if
((
i
&
0xf
)
==
0
)
ret
+=
fprintf
(
dest
,
"DUMP: "
);
ret
+=
fprintf
(
dest
,
"%02x"
,
p
[
i
]);
i
++
;
ret
+=
fprintf
(
dest
,
i
&
3
?
" "
:
i
&
0xf
?
" "
:
"
\n
"
);
}
if
(
i
&
0xf
)
ret
+=
fprintf
(
dest
,
"
\n
"
);
return
ret
;
}
static
void
dump_eth
(
struct
ethhdr
*
eth
)
{
struct
timeval
tv
;
struct
tm
tm
;
unsigned
char
*
d
=
eth
->
h_dest
;
unsigned
char
*
s
=
eth
->
h_source
;
gettimeofday
(
&
tv
,
NULL
);
localtime_r
(
&
tv
.
tv_sec
,
&
tm
);
printf
(
"TIME: (%li - 0x%lx) %02i:%02i:%02i.%06li
\n
"
,
tv
.
tv_sec
,
tv
.
tv_sec
,
tm
.
tm_hour
,
tm
.
tm_min
,
tm
.
tm_sec
,
(
long
)
tv
.
tv_usec
);
printf
(
"ETH: %04x (%02x:%02x:%02x:%02x:%02x:%02x -> "
"%02x:%02x:%02x:%02x:%02x:%02x)
\n
"
,
ntohs
(
eth
->
h_proto
),
s
[
0
],
s
[
1
],
s
[
2
],
s
[
3
],
s
[
4
],
s
[
5
],
d
[
0
],
d
[
1
],
d
[
2
],
d
[
3
],
d
[
4
],
d
[
5
]);
}
static
void
dump_ip
(
struct
iphdr
*
ip
)
{
uint32_t
s
=
ntohl
(
ip
->
saddr
);
uint32_t
d
=
ntohl
(
ip
->
daddr
);
printf
(
"IP: %i (%i.%i.%i.%i -> %i.%i.%i.%i) len %i
\n
"
,
ip
->
protocol
,
(
s
>>
24
)
&
0xff
,
(
s
>>
16
)
&
0xff
,
(
s
>>
8
)
&
0xff
,
s
&
0xff
,
(
d
>>
24
)
&
0xff
,
(
d
>>
16
)
&
0xff
,
(
d
>>
8
)
&
0xff
,
d
&
0xff
,
ntohs
(
ip
->
tot_len
));
}
static
void
dump_udp
(
struct
udphdr
*
udp
)
{
printf
(
"UDP: (%i -> %i) len %i
\n
"
,
ntohs
(
udp
->
source
),
ntohs
(
udp
->
dest
),
ntohs
(
udp
->
len
));
}
/* Helpers for fucking data structures */
static
void
dump_1stamp
(
char
*
s
,
struct
stamp
*
t
)
{
uint64_t
sec
=
(
uint64_t
)(
ntohs
(
t
->
sec
.
msb
))
<<
32
;
sec
|=
(
uint64_t
)(
ntohl
(
t
->
sec
.
lsb
));
printf
(
"%s%lli.%09i
\n
"
,
s
,
sec
,
ntohl
(
t
->
nsec
));
}
static
void
dump_1quality
(
char
*
s
,
ClockQuality
*
q
)
{
printf
(
"%s%02x-%02x-%04x
\n
"
,
s
,
q
->
clockClass
,
q
->
clockAccuracy
,
q
->
offsetScaledLogVariance
);
}
static
void
dump_1clockid
(
char
*
s
,
ClockIdentity
i
)
{
printf
(
"%s%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x
\n
"
,
s
,
i
[
0
],
i
[
1
],
i
[
2
],
i
[
3
],
i
[
4
],
i
[
5
],
i
[
6
],
i
[
7
]);
}
static
void
dump_1port
(
char
*
s
,
unsigned
char
*
p
)
{
printf
(
"%s%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x
\n
"
,
s
,
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
],
p
[
5
],
p
[
6
],
p
[
7
],
p
[
8
],
p
[
9
]);
}
/* Helpers for each message types */
static
void
dump_msg_announce
(
struct
ptp_announce
*
p
)
{
dump_1stamp
(
"MSG-ANNOUNCE: stamp "
,
&
p
->
originTimestamp
);
dump_1quality
(
"MSG-ANNOUNCE: grandmaster-quality "
,
&
p
->
grandmasterClockQuality
);
printf
(
"MSG-ANNOUNCE: grandmaster-prio %i %i
\n
"
,
p
->
grandmasterPriority1
,
p
->
grandmasterPriority2
);
dump_1clockid
(
"MSG-ANNOUNCE: grandmaster-id "
,
p
->
grandmasterIdentity
);
}
static
void
dump_msg_sync_etc
(
char
*
s
,
struct
ptp_sync_etc
*
p
)
{
dump_1stamp
(
s
,
&
p
->
stamp
);
}
static
void
dump_msg_resp_etc
(
char
*
s
,
struct
ptp_sync_etc
*
p
)
{
dump_1stamp
(
s
,
&
p
->
stamp
);
dump_1port
(
s
,
p
->
port
);
}
/* A big function to dump the ptp information */
static
void
dump_payload
(
void
*
pl
,
int
len
)
{
struct
ptp_header
*
h
=
pl
;
void
*
msg_specific
=
(
void
*
)(
h
+
1
);
if
(
h
->
versionPTP
!=
2
)
{
printf
(
"VERSION: unsupported (%i)
\n
"
,
h
->
versionPTP
);
return
;
}
printf
(
"VERSION: %i (type %i, len %i, domain %i)
\n
"
,
h
->
versionPTP
,
h
->
messageType
,
ntohs
(
h
->
messageLength
),
h
->
domainNumber
);
printf
(
"FLAGS: 0x%04x (correction 0x%08llx)
\n
"
,
h
->
flagField
,
h
->
correctionField
);
dump_1port
(
"PORT: "
,
h
->
sourcePortIdentity
);
printf
(
"REST: seq %i, ctrl %i, log-interval %i
\n
"
,
ntohs
(
h
->
sequenceId
),
h
->
controlField
,
h
->
logMessageInterval
);
#define CASE(t, x) case PPM_ ##x: printf("MESSAGE: (" #t ") " #x "\n")
switch
(
h
->
messageType
)
{
CASE
(
E
,
SYNC
);
dump_msg_sync_etc
(
"MSG-SYNC: "
,
msg_specific
);
break
;
CASE
(
E
,
DELAY_REQ
);
dump_msg_sync_etc
(
"MSG-DELAY_REQ: "
,
msg_specific
);
break
;
CASE
(
E
,
PDELAY_REQ
);
dump_msg_sync_etc
(
"MSG-PDELAY_REQ: "
,
msg_specific
);
break
;
CASE
(
E
,
PDELAY_RESP
);
dump_msg_resp_etc
(
"MSG-PDELAY_RESP: "
,
msg_specific
);
break
;
CASE
(
G
,
FOLLOW_UP
);
dump_msg_sync_etc
(
"MSG-FOLLOW_UP: "
,
msg_specific
);
break
;
CASE
(
G
,
DELAY_RESP
);
dump_msg_resp_etc
(
"MSG-DELAY_RESP: "
,
msg_specific
);
break
;
CASE
(
G
,
PDELAY_RESP_FOLLOW_UP
);
dump_msg_resp_etc
(
"MSG-PDELAY_RESP_FOLLOWUP: "
,
msg_specific
);
break
;
CASE
(
G
,
ANNOUNCE
);
dump_msg_announce
(
msg_specific
);
break
;
CASE
(
G
,
SIGNALING
);
/* FIXME */
break
;
CASE
(
G
,
MANAGEMENT
);
/* FIXME */
break
;
}
/* Finally, binary dump of it all */
dumpstruct
(
stdout
,
"payload"
,
pl
,
len
);
}
static
int
dump_udppkt
(
void
*
buf
,
int
len
)
{
struct
ethhdr
*
eth
=
buf
;
struct
iphdr
*
ip
=
buf
+
ETH_HLEN
;
struct
udphdr
*
udp
=
(
void
*
)(
ip
+
1
);
void
*
payload
=
(
void
*
)(
udp
+
1
);
int
udpdest
=
ntohs
(
udp
->
dest
);
static
unsigned
char
prev
[
256
];
static
int
prevlen
;
if
(
len
<
ETH_HLEN
+
sizeof
(
*
ip
)
+
sizeof
(
*
udp
))
return
-
1
;
/* page 239 and following */
if
(
udpdest
!=
319
&&
udpdest
!=
320
)
return
-
1
;
/* for some reasons, we receive it three times, check dups */
if
(
len
==
prevlen
&&
!
memcmp
(
buf
,
prev
,
len
))
return
-
1
;
memcpy
(
prev
,
buf
,
len
);
prevlen
=
len
;
dump_eth
(
eth
);
dump_ip
(
ip
);
dump_udp
(
udp
);
dump_payload
(
payload
,
len
-
(
payload
-
buf
));
putchar
(
'\n'
);
return
0
;
}
static
int
dump_1588pkt
(
void
*
buf
,
int
len
)
{
struct
ethhdr
*
eth
=
buf
;
void
*
payload
=
(
void
*
)(
eth
+
1
);
dump_eth
(
eth
);
dump_payload
(
payload
,
len
-
(
payload
-
buf
));
putchar
(
'\n'
);
return
0
;
}
int
main
(
int
argc
,
char
**
argv
)
{
int
sock
;
struct
packet_mreq
req
;
struct
ifreq
ifr
;
char
*
ifname
=
"eth0"
;
sock
=
socket
(
PF_PACKET
,
SOCK_RAW
,
htons
(
ETH_P_ALL
));
if
(
sock
<
0
)
{
fprintf
(
stderr
,
"%s: socket(): %s
\n
"
,
argv
[
0
],
strerror
(
errno
));
exit
(
1
);
}
if
(
argc
>
1
)
ifname
=
argv
[
1
];
memset
(
&
ifr
,
0
,
sizeof
(
ifr
));
strcpy
(
ifr
.
ifr_name
,
ifname
);
if
(
ioctl
(
sock
,
SIOCGIFINDEX
,
&
ifr
)
<
0
)
{
fprintf
(
stderr
,
"%s: ioctl(GETIFINDEX(%s)): %s
\n
"
,
argv
[
0
],
ifname
,
strerror
(
errno
));
exit
(
1
);
}
fprintf
(
stderr
,
"Dumping PTP packets from interface
\"
%s
\"\n
"
,
ifname
);
memset
(
&
req
,
0
,
sizeof
(
req
));
req
.
mr_ifindex
=
ifr
.
ifr_ifindex
;
req
.
mr_type
=
PACKET_MR_PROMISC
;
if
(
setsockopt
(
3
,
SOL_PACKET
,
PACKET_ADD_MEMBERSHIP
,
&
req
,
sizeof
(
req
))
<
0
)
{
fprintf
(
stderr
,
"%s: set promiscuous(%s): %s
\n
"
,
argv
[
0
],
ifname
,
strerror
(
errno
));
exit
(
1
);
}
/* Ok, now we are promiscuous. Just read stuff forever */
while
(
1
)
{
struct
ethhdr
*
eth
;
struct
iphdr
*
ip
;
unsigned
char
buf
[
10000
];
struct
sockaddr_in
from
;
socklen_t
fromlen
=
sizeof
(
from
);
int
len
;
len
=
recvfrom
(
sock
,
buf
,
10000
,
MSG_TRUNC
,
(
struct
sockaddr
*
)
&
from
,
&
fromlen
);
/* now only print ptp packets */
if
(
len
<
ETH_HLEN
)
continue
;
eth
=
(
void
*
)
buf
;
ip
=
(
void
*
)(
buf
+
ETH_HLEN
);
switch
(
ntohs
(
eth
->
h_proto
))
{
case
ETH_P_IP
:
if
(
len
<
ETH_HLEN
+
sizeof
(
*
ip
))
continue
;
if
(
ip
->
protocol
!=
IPPROTO_UDP
)
continue
;
dump_udppkt
(
buf
,
len
);
break
;
case
ETH_P_1588
:
dump_1588pkt
(
buf
,
len
);
break
;
default:
continue
;
}
fflush
(
stdout
);
}
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment