]> arthur.barton.de Git - netatalk.git/blob - bin/misc/fce.c
Merge branch-allea
[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     "FCE_TM_SIZE"
32 };
33
34 // get sockaddr, IPv4 or IPv6:
35 static void *get_in_addr(struct sockaddr *sa)
36 {
37     if (sa->sa_family == AF_INET) {
38         return &(((struct sockaddr_in*)sa)->sin_addr);
39     }
40
41     return &(((struct sockaddr_in6*)sa)->sin6_addr);
42 }
43
44 static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet)
45 {
46     unsigned char *p = buf;
47
48     memcpy(&packet->magic[0], p, sizeof(packet->magic));
49     p += sizeof(packet->magic);
50
51     packet->version = *p;
52     p++;
53
54     packet->mode = *p;
55     p++;
56
57     memcpy(&packet->event_id, p, sizeof(packet->event_id));
58     p += sizeof(packet->event_id);
59     packet->event_id = ntohl(packet->event_id);
60
61     memcpy(&packet->datalen, p, sizeof(packet->datalen));
62     p += sizeof(packet->datalen);
63     packet->datalen = ntohs(packet->datalen);
64
65     memcpy(&packet->data[0], p, packet->datalen);
66     p += packet->datalen;
67
68     return 0;
69 }
70
71 int main(void)
72 {
73     int sockfd;
74     struct addrinfo hints, *servinfo, *p;
75     int rv;
76     int numbytes;
77     struct sockaddr_storage their_addr;
78     char buf[MAXBUFLEN];
79     socklen_t addr_len;
80     char s[INET6_ADDRSTRLEN];
81     uint64_t tmsize;
82
83     memset(&hints, 0, sizeof hints);
84     hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
85     hints.ai_socktype = SOCK_DGRAM;
86
87     if ((rv = getaddrinfo(NULL, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) {
88         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
89         return 1;
90     }
91
92     // loop through all the results and bind to the first we can
93     for(p = servinfo; p != NULL; p = p->ai_next) {
94         if ((sockfd = socket(p->ai_family, p->ai_socktype,
95                              p->ai_protocol)) == -1) {
96             perror("listener: socket");
97             continue;
98         }
99
100         if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
101             close(sockfd);
102             perror("listener: bind");
103             continue;
104         }
105
106         break;
107     }
108
109     if (p == NULL) {
110         fprintf(stderr, "listener: failed to bind socket\n");
111         return 2;
112     }
113
114     freeaddrinfo(servinfo);
115
116     printf("listener: waiting to recvfrom...\n");
117
118     addr_len = sizeof their_addr;
119
120     struct fce_packet packet;
121     while (1) {
122         if ((numbytes = recvfrom(sockfd,
123                                  buf,
124                                  MAXBUFLEN - 1,
125                                  0,
126                                  (struct sockaddr *)&their_addr,
127                                  &addr_len)) == -1) {
128             perror("recvfrom");
129             exit(1);
130         }
131
132         unpack_fce_packet(buf, &packet);
133
134         if (memcmp(packet.magic, FCE_PACKET_MAGIC, sizeof(packet.magic)) == 0) {
135
136             switch (packet.mode) {
137             case FCE_TM_SIZE:
138                 memcpy(&tmsize, packet.data, sizeof(uint64_t));
139                 tmsize = ntoh64(tmsize);
140                 printf("ID: %" PRIu32 ", Event: %s, Volume: %s, TM used size: %" PRIu64 " \n",
141                        packet.event_id, fce_ev_names[packet.mode], packet.data + sizeof(uint64_t), tmsize);
142                 break;
143
144             case FCE_CONN_START:
145                 printf("FCE Start\n");
146                 break;
147
148             case FCE_CONN_BROKEN:
149                 printf("Broken FCE connection\n");
150                 break;
151
152             default:
153                 printf("ID: %" PRIu32 ", Event: %s, Path: %s\n",
154                        packet.event_id, fce_ev_names[packet.mode], packet.data);
155                 break;
156             }
157         }
158     }
159
160     close(sockfd);
161     return 0;
162 }