+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/param.h>
#include <atalk/fce_api.h>
+#include <atalk/util.h>
+
+#define MAXBUFLEN 1024
-#define MAXBUFLEN 100
+static char *fce_ev_names[] = {
+ "",
+ "FCE_FILE_MODIFY",
+ "FCE_FILE_DELETE",
+ "FCE_DIR_DELETE",
+ "FCE_FILE_CREATE",
+ "FCE_DIR_CREATE"
+};
-// get sockaddr, IPv4 or IPv6:
-void *get_in_addr(struct sockaddr *sa)
+static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet)
{
- if (sa->sa_family == AF_INET) {
- return &(((struct sockaddr_in*)sa)->sin_addr);
- }
+ unsigned char *p = buf;
+
+ memcpy(&packet->magic[0], p, sizeof(packet->magic));
+ p += sizeof(packet->magic);
+
+ packet->version = *p;
+ p++;
- return &(((struct sockaddr_in6*)sa)->sin6_addr);
+ packet->mode = *p;
+ p++;
+
+ memcpy(&packet->event_id, p, sizeof(packet->event_id));
+ p += sizeof(packet->event_id);
+ packet->event_id = ntohl(packet->event_id);
+
+ memcpy(&packet->datalen, p, sizeof(packet->datalen));
+ p += sizeof(packet->datalen);
+ packet->datalen = ntohs(packet->datalen);
+
+ memcpy(&packet->data[0], p, packet->datalen);
+ packet->data[packet->datalen] = 0; /* 0 terminate strings */
+ p += packet->datalen;
+
+ return 0;
}
int main(void)
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
- char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
-// hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
printf("listener: waiting to recvfrom...\n");
addr_len = sizeof their_addr;
- if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
- (struct sockaddr *)&their_addr, &addr_len)) == -1) {
- perror("recvfrom");
- exit(1);
- }
- printf("listener: got packet from %s\n",
- inet_ntop(their_addr.ss_family,
- get_in_addr((struct sockaddr *)&their_addr),
- s, sizeof s));
- printf("listener: packet is %d bytes long\n", numbytes);
- buf[numbytes] = '\0';
- printf("listener: packet contains \"%s\"\n", buf);
+ struct fce_packet packet;
+ while (1) {
+ if ((numbytes = recvfrom(sockfd,
+ buf,
+ MAXBUFLEN - 1,
+ 0,
+ (struct sockaddr *)&their_addr,
+ &addr_len)) == -1) {
+ perror("recvfrom");
+ exit(1);
+ }
- close(sockfd);
+ unpack_fce_packet((unsigned char *)buf, &packet);
+
+ if (memcmp(packet.magic, FCE_PACKET_MAGIC, sizeof(packet.magic)) == 0) {
+
+ switch (packet.mode) {
+ case FCE_CONN_START:
+ printf("FCE Start\n");
+ break;
+ case FCE_CONN_BROKEN:
+ printf("Broken FCE connection\n");
+ break;
+
+ default:
+ printf("ID: %" PRIu32 ", Event: %s, Path: %s\n",
+ packet.event_id, fce_ev_names[packet.mode], packet.data);
+ break;
+ }
+ }
+ }
+
+ close(sockfd);
return 0;
}