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