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_FILE_MOVE",
32     "FCE_DIR_MOVE",
33     "FCE_LOGIN",
34     "FCE_LOGOUT"
35 };
36 
unpack_fce_packet(unsigned char * buf,struct fce_packet * packet)37 static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet)
38 {
39     unsigned char *p = buf;
40     uint16_t uint16;
41     uint32_t uint32;
42     uint64_t uint64;
43 
44     memcpy(&packet->fcep_magic[0], p, sizeof(packet->fcep_magic));
45     p += sizeof(packet->fcep_magic);
46 
47     packet->fcep_version = *p++;
48 
49     if (packet->fcep_version > 1)
50         packet->fcep_options = *p++;
51 
52     packet->fcep_event = *p++;
53 
54     if (packet->fcep_version > 1)
55         /* padding */
56         p++;
57 
58     if (packet->fcep_version > 1)
59         /* reserved */
60         p += 8;
61 
62     memcpy(&packet->fcep_event_id, p, sizeof(packet->fcep_event_id));
63     p += sizeof(packet->fcep_event_id);
64     packet->fcep_event_id = ntohl(packet->fcep_event_id);
65 
66     if (packet->fcep_options & FCE_EV_INFO_PID) {
67         memcpy(&packet->fcep_pid, p, sizeof(packet->fcep_pid));
68         packet->fcep_pid = hton64(packet->fcep_pid);
69         p += sizeof(packet->fcep_pid);
70     }
71 
72     if (packet->fcep_options & FCE_EV_INFO_USER) {
73         memcpy(&packet->fcep_userlen, p, sizeof(packet->fcep_userlen));
74         packet->fcep_userlen = ntohs(packet->fcep_userlen);
75         p += sizeof(packet->fcep_userlen);
76 
77         memcpy(&packet->fcep_user[0], p, packet->fcep_userlen);
78         packet->fcep_user[packet->fcep_userlen] = 0; /* 0 terminate strings */
79         p += packet->fcep_userlen;
80     }
81 
82     /* path */
83     memcpy(&packet->fcep_pathlen1, p, sizeof(packet->fcep_pathlen1));
84     p += sizeof(packet->fcep_pathlen1);
85     packet->fcep_pathlen1 = ntohs(packet->fcep_pathlen1);
86 
87     memcpy(&packet->fcep_path1[0], p, packet->fcep_pathlen1);
88     packet->fcep_path1[packet->fcep_pathlen1] = 0; /* 0 terminate strings */
89     p += packet->fcep_pathlen1;
90 
91     if (packet->fcep_options & FCE_EV_INFO_SRCPATH) {
92         memcpy(&packet->fcep_pathlen2, p, sizeof(packet->fcep_pathlen2));
93         p += sizeof(packet->fcep_pathlen2);
94         packet->fcep_pathlen2 = ntohs(packet->fcep_pathlen2);
95         memcpy(&packet->fcep_path2[0], p, packet->fcep_pathlen2);
96         packet->fcep_path2[packet->fcep_pathlen2] = 0; /* 0 terminate strings */
97         p += packet->fcep_pathlen2;
98     }
99 
100     return 0;
101 }
102 
main(int argc,char ** argv)103 int main(int argc, char **argv)
104 {
105     int sockfd, rv, c;
106     struct addrinfo hints, *servinfo, *p;
107     int numbytes;
108     struct sockaddr_storage their_addr;
109     char buf[MAXBUFLEN];
110     socklen_t addr_len;
111     char s[INET6_ADDRSTRLEN];
112     char *host = "localhost";
113 
114     while ((c = getopt(argc, argv, "h:")) != -1) {
115         switch(c) {
116         case 'h':
117             host = strdup(optarg);
118             break;
119         }
120     }
121 
122     memset(&hints, 0, sizeof hints);
123     hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
124     hints.ai_socktype = SOCK_DGRAM;
125 
126     if ((rv = getaddrinfo(host, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) {
127         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
128         return 1;
129     }
130 
131     // loop through all the results and bind to the first we can
132     for(p = servinfo; p != NULL; p = p->ai_next) {
133         if ((sockfd = socket(p->ai_family, p->ai_socktype,
134                              p->ai_protocol)) == -1) {
135             perror("listener: socket");
136             continue;
137         }
138 
139         if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
140             close(sockfd);
141             perror("listener: bind");
142             continue;
143         }
144 
145         break;
146     }
147 
148     if (p == NULL) {
149         fprintf(stderr, "listener: failed to bind socket\n");
150         return 2;
151     }
152 
153     freeaddrinfo(servinfo);
154 
155     printf("listener: waiting to recvfrom...\n");
156 
157     addr_len = sizeof their_addr;
158 
159     struct fce_packet packet;
160     while (1) {
161         if ((numbytes = recvfrom(sockfd,
162                                  buf,
163                                  MAXBUFLEN - 1,
164                                  0,
165                                  (struct sockaddr *)&their_addr,
166                                  &addr_len)) == -1) {
167             perror("recvfrom");
168             exit(1);
169         }
170 
171         unpack_fce_packet((unsigned char *)buf, &packet);
172 
173         if (memcmp(packet.fcep_magic, FCE_PACKET_MAGIC, sizeof(packet.fcep_magic)) == 0) {
174 
175             switch (packet.fcep_event) {
176             case FCE_CONN_START:
177                 printf("FCE Start\n");
178                 break;
179 
180             case FCE_CONN_BROKEN:
181                 printf("Broken FCE connection\n");
182                 break;
183 
184             default:
185                 printf("ID: %" PRIu32 ", Event: %s", packet.fcep_event_id, fce_ev_names[packet.fcep_event]);
186                 if (packet.fcep_options & FCE_EV_INFO_PID)
187                     printf(", pid: %" PRId64, packet.fcep_pid);
188                 if (packet.fcep_options & FCE_EV_INFO_USER)
189                     printf(", user: %s", packet.fcep_user);
190 
191                 if (packet.fcep_options & FCE_EV_INFO_SRCPATH)
192                     printf(", source: %s", packet.fcep_path2);
193 
194                 printf(", Path: %s\n", packet.fcep_path1);
195                 break;
196             }
197         }
198     }
199 
200     close(sockfd);
201     return 0;
202 }
203