]> arthur.barton.de Git - netatalk.git/blob - bin/misc/fce.c
dc58602ee8c69ef6abca408f71721cb4293336d8
[netatalk.git] / bin / misc / fce.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif /* HAVE_CONFIG_H */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <netdb.h>
15 #include <inttypes.h>
16 #include <sys/types.h>
17 #include <sys/param.h>
18
19 #include <atalk/fce_api.h>
20 #include <atalk/util.h>
21
22 #define MAXBUFLEN 1024
23
24 static char *fce_ev_names[] = {
25     "",
26     "FCE_FILE_MODIFY",
27     "FCE_FILE_DELETE",
28     "FCE_DIR_DELETE",
29     "FCE_FILE_CREATE",
30     "FCE_DIR_CREATE"
31 };
32
33 // get sockaddr, IPv4 or IPv6:
34 static void *get_in_addr(struct sockaddr *sa)
35 {
36     if (sa->sa_family == AF_INET) {
37         return &(((struct sockaddr_in*)sa)->sin_addr);
38     }
39
40     return &(((struct sockaddr_in6*)sa)->sin6_addr);
41 }
42
43 static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet)
44 {
45     unsigned char *p = buf;
46
47     memcpy(&packet->magic[0], p, sizeof(packet->magic));
48     p += sizeof(packet->magic);
49
50     packet->version = *p;
51     p++;
52
53     packet->mode = *p;
54     p++;
55
56     memcpy(&packet->event_id, p, sizeof(packet->event_id));
57     p += sizeof(packet->event_id);
58     packet->event_id = ntohl(packet->event_id);
59
60     memcpy(&packet->datalen, p, sizeof(packet->datalen));
61     p += sizeof(packet->datalen);
62     packet->datalen = ntohs(packet->datalen);
63
64     memcpy(&packet->data[0], p, packet->datalen);
65     p += packet->datalen;
66
67     return 0;
68 }
69
70 int main(void)
71 {
72     int sockfd;
73     struct addrinfo hints, *servinfo, *p;
74     int rv;
75     int numbytes;
76     struct sockaddr_storage their_addr;
77     char buf[MAXBUFLEN];
78     socklen_t addr_len;
79     char s[INET6_ADDRSTRLEN];
80     uint64_t tmsize;
81
82     memset(&hints, 0, sizeof hints);
83     hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
84     hints.ai_socktype = SOCK_DGRAM;
85
86     if ((rv = getaddrinfo(NULL, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) {
87         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
88         return 1;
89     }
90
91     // loop through all the results and bind to the first we can
92     for(p = servinfo; p != NULL; p = p->ai_next) {
93         if ((sockfd = socket(p->ai_family, p->ai_socktype,
94                              p->ai_protocol)) == -1) {
95             perror("listener: socket");
96             continue;
97         }
98
99         if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
100             close(sockfd);
101             perror("listener: bind");
102             continue;
103         }
104
105         break;
106     }
107
108     if (p == NULL) {
109         fprintf(stderr, "listener: failed to bind socket\n");
110         return 2;
111     }
112
113     freeaddrinfo(servinfo);
114
115     printf("listener: waiting to recvfrom...\n");
116
117     addr_len = sizeof their_addr;
118
119     struct fce_packet packet;
120     while (1) {
121         if ((numbytes = recvfrom(sockfd,
122                                  buf,
123                                  MAXBUFLEN - 1,
124                                  0,
125                                  (struct sockaddr *)&their_addr,
126                                  &addr_len)) == -1) {
127             perror("recvfrom");
128             exit(1);
129         }
130
131         unpack_fce_packet(buf, &packet);
132
133         if (memcmp(packet.magic, FCE_PACKET_MAGIC, sizeof(packet.magic)) == 0) {
134
135             switch (packet.mode) {
136             case FCE_CONN_START:
137                 printf("FCE Start\n");
138                 break;
139
140             case FCE_CONN_BROKEN:
141                 printf("Broken FCE connection\n");
142                 break;
143
144             default:
145                 printf("ID: %" PRIu32 ", Event: %s, Path: %s\n",
146                        packet.event_id, fce_ev_names[packet.mode], packet.data);
147                 break;
148             }
149         }
150     }
151
152     close(sockfd);
153     return 0;
154 }