From 094d73aeaf066d5866b0b7703d0e6cb881e67357 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Tue, 31 May 2011 13:41:18 +0200 Subject: [PATCH] Various fixes --- bin/misc/fce.c | 105 +++++++++++++++++++++++++++----- etc/afpd/fce_api.c | 117 ++++++++++++++++++++++++------------ etc/afpd/fce_api_internal.h | 1 + include/atalk/fce_api.h | 7 ++- include/atalk/util.h | 4 +- 5 files changed, 173 insertions(+), 61 deletions(-) diff --git a/bin/misc/fce.c b/bin/misc/fce.c index 863665b4..76ca0a8e 100644 --- a/bin/misc/fce.c +++ b/bin/misc/fce.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + #include #include #include @@ -8,13 +12,29 @@ #include #include #include +#include +#include + +#include +#include #include +#include + +#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", + "FCE_TM_SIZE" +}; // get sockaddr, IPv4 or IPv6: -void *get_in_addr(struct sockaddr *sa) +static void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); @@ -23,6 +43,33 @@ void *get_in_addr(struct sockaddr *sa) return &(((struct sockaddr_in6*)sa)->sin6_addr); } +static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet) +{ + unsigned char *p = buf; + + memcpy(&packet->magic[0], p, sizeof(packet->magic)); + p += sizeof(packet->magic); + + packet->version = *p; + p++; + + 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); + p += packet->datalen; + + return 0; +} + int main(void) { int sockfd; @@ -33,11 +80,11 @@ int main(void) char buf[MAXBUFLEN]; socklen_t addr_len; char s[INET6_ADDRSTRLEN]; + uint64_t tmsize; 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)); @@ -71,21 +118,47 @@ int main(void) 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(buf, &packet); + + if (memcmp(packet.magic, FCE_PACKET_MAGIC, sizeof(packet.magic)) == 0) { + + switch (packet.mode) { + case FCE_TM_SIZE: + memcpy(&tmsize, packet.data, sizeof(uint64_t)); + tmsize = ntoh64(tmsize); + printf("ID: %" PRIu32 ", Event: %s, Volume: %s, TM used size: %" PRIu64 " \n", + packet.event_id, fce_ev_names[packet.mode], packet.data + sizeof(uint64_t), tmsize); + break; + 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; } diff --git a/etc/afpd/fce_api.c b/etc/afpd/fce_api.c index 6c6bf4ed..012dedde 100755 --- a/etc/afpd/fce_api.c +++ b/etc/afpd/fce_api.c @@ -65,8 +65,16 @@ static struct udp_entry udp_socket_list[FCE_MAX_UDP_SOCKS]; static int udp_sockets = 0; static int udp_initialized = FCE_FALSE; -static unsigned long fce_ev_enabled = 0; +static unsigned long fce_ev_enabled = + (1 << FCE_FILE_MODIFY) | + (1 << FCE_FILE_DELETE) | + (1 << FCE_DIR_DELETE) | + (1 << FCE_FILE_CREATE) | + (1 << FCE_DIR_CREATE); + static uint64_t tm_used; /* used for passing to event handler */ +#define MAXIOBUF 1024 +static char iobuf[MAXIOBUF]; static const char *skip_files[] = { ".DS_Store", @@ -118,7 +126,9 @@ void fce_init_udp() LOG(log_error, logtype_afpd, "fce_init_udp: no socket for %s:%s", udp_entry->addr, udp_entry->port); } + udp_entry->addrinfo = *p; memcpy(&udp_entry->addrinfo, p, sizeof(struct addrinfo)); + memcpy(&udp_entry->sockaddr, p->ai_addr, sizeof(struct sockaddr_storage)); freeaddrinfo(servinfo); } @@ -156,7 +166,7 @@ static ssize_t build_fce_packet( struct fce_packet *packet, char *path, int mode strncpy(packet->magic, FCE_PACKET_MAGIC, sizeof(packet->magic) ); packet->version = FCE_PACKET_VERSION; packet->mode = mode; - packet->event_id = htonl( event_id ); + packet->event_id = event_id; pathlen = strlen(path) + 1; /* include string terminator */ @@ -166,20 +176,20 @@ static ssize_t build_fce_packet( struct fce_packet *packet, char *path, int mode /* This is the payload len. Means: the stream has len bytes more until packet is finished */ /* A server should read the first 16 byte, decode them and then fetch the rest */ + data_len = FCE_PACKET_HEADER_SIZE + pathlen; + packet->datalen = pathlen; switch (mode) { case FCE_TM_SIZE: - packet->len = htons(pathlen) + sizeof(tm_used); tm_used = hton64(tm_used); memcpy(packet->data, &tm_used, sizeof(tm_used)); - strncpy(packet->data + sizeof(tm_used), path, pathlen); - data_len = sizeof(struct fce_packet) + pathlen + sizeof(tm_used); + + packet->datalen += sizeof(tm_used); + data_len += sizeof(tm_used); break; default: - packet->len = htons(pathlen); strncpy(packet->data, path, pathlen); - data_len = sizeof(struct fce_packet) + pathlen; break; } @@ -187,6 +197,33 @@ static ssize_t build_fce_packet( struct fce_packet *packet, char *path, int mode return data_len; } +static int pack_fce_packet(struct fce_packet *packet, unsigned char *buf) +{ + unsigned char *p = buf; + + memcpy(p, &packet->magic[0], sizeof(packet->magic)); + p += sizeof(packet->magic); + + *p = packet->version; + p++; + + *p = packet->mode; + p++; + + uint32_t id = htonl(packet->event_id); + memcpy(p, &id, sizeof(id)); + p += sizeof(packet->event_id); + + uint16_t l = htons(packet->datalen); + memcpy(p, &l, sizeof(l)); + p += sizeof(l); + + memcpy(p, &packet->data[0], packet->datalen); + p += packet->datalen; + + return 0; +} + /* * Send the fce information to all (connected) listeners * We dont give return code because all errors are handled internally (I hope..) @@ -197,11 +234,13 @@ static void send_fce_event( char *path, int mode ) void *data = &packet; static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */ + LOG(log_note, logtype_afpd, "send_fce_event: start"); + time_t now = time(NULL); /* build our data packet */ ssize_t data_len = build_fce_packet( &packet, path, mode, ++event_id ); - + pack_fce_packet(&packet, iobuf); for (int i = 0; i < udp_sockets; i++) { @@ -232,31 +271,33 @@ static void send_fce_event( char *path, int mode ) /* Okay, we have a running socket again, send server that we had a problem on our side*/ data_len = build_fce_packet( &packet, "", FCE_CONN_BROKEN, 0 ); + pack_fce_packet(&packet, iobuf); sendto(udp_entry->sock, - data, + iobuf, data_len, 0, - udp_entry->addrinfo.ai_addr, + (struct sockaddr *)&udp_entry->sockaddr, udp_entry->addrinfo.ai_addrlen); /* Rebuild our original data packet */ data_len = build_fce_packet( &packet, path, mode, event_id ); + pack_fce_packet(&packet, iobuf); } + LOG(log_note, logtype_afpd, "send_fce_event: sending..."); sent_data = sendto(udp_entry->sock, - data, + iobuf, data_len, 0, - udp_entry->addrinfo.ai_addr, + (struct sockaddr *)&udp_entry->sockaddr, udp_entry->addrinfo.ai_addrlen); /* Problems ? */ - if (sent_data != data_len) - { + if (sent_data != data_len) { /* Argh, socket broke, we close and retry later */ - LOG(log_error, logtype_afpd, "Error while sending packet to %s for fce UDP connection: transfered: %d of %d errno %d", - udp_entry->port, sent_data, data_len, errno ); + LOG(log_error, logtype_afpd, "send_fce_event: error sending packet to %s:%s, transfered %d of %d: %s", + udp_entry->addr, udp_entry->port, sent_data, data_len, strerror(errno)); close( udp_entry->sock ); udp_entry->sock = -1; @@ -278,7 +319,8 @@ static int add_udp_socket(const char *target_ip, const char *target_port ) udp_socket_list[udp_sockets].addr = strdup(target_ip); udp_socket_list[udp_sockets].port = strdup(target_port); udp_socket_list[udp_sockets].sock = -1; - memset( &udp_socket_list[udp_sockets].addrinfo, 0, sizeof(struct sockaddr_in) ); + memset(&udp_socket_list[udp_sockets].addrinfo, 0, sizeof(struct addrinfo)); + memset(&udp_socket_list[udp_sockets].sockaddr, 0, sizeof(struct sockaddr_storage)); udp_socket_list[udp_sockets].next_try_on_error = 0; udp_sockets++; @@ -303,18 +345,10 @@ static int register_fce(const char *u_name, int is_dir, int mode) static int first_event = FCE_TRUE; /* do some initialization on the fly the first time */ - if (first_event) - { + if (first_event) { fce_initialize_history(); - fce_ev_enabled = - (1 << FCE_FILE_MODIFY) | - (1 << FCE_FILE_DELETE) | - (1 << FCE_DIR_DELETE) | - (1 << FCE_FILE_CREATE) | - (1 << FCE_DIR_CREATE); } - /* handle files which should not cause events (.DS_Store atc. ) */ for (int i = 0; skip_files[i] != NULL; i++) { @@ -326,8 +360,8 @@ static int register_fce(const char *u_name, int is_dir, int mode) char full_path_buffer[MAXPATHLEN + 1] = {""}; const char *cwd = getcwdpath(); - if (mode & FCE_TM_SIZE) { - strncpy(full_path_buffer, u_name, MAXPATHLEN); + if (mode == FCE_TM_SIZE) { + strlcpy(full_path_buffer, u_name, MAXPATHLEN); } else if (!is_dir || mode == FCE_DIR_DELETE) { if (strlen( cwd ) + strlen( u_name) + 1 >= MAXPATHLEN) { LOG(log_error, logtype_afpd, "FCE file name too long: %s/%s", cwd, u_name ); @@ -467,6 +501,8 @@ int fce_register_tm_size(const char *vol, size_t used) { int ret = AFP_OK; + LOG(log_note, logtype_afpd, "fce_register_tm_size"); + if (vol == NULL) return AFPERR_PARAM; @@ -509,21 +545,22 @@ int fce_set_events(const char *events) return AFPERR_PARAM; e = strdup(events); + fce_ev_enabled = 0; for (p = strtok(e, ","); p; p = strtok(NULL, ",")) { - if (strcmp(e, "fmod") == 0) { - fce_ev_enabled |= FCE_FILE_MODIFY; - } else if (strcmp(e, "fdel") == 0) { - fce_ev_enabled |= FCE_FILE_DELETE; - } else if (strcmp(e, "ddel") == 0) { - fce_ev_enabled |= FCE_DIR_DELETE; - } else if (strcmp(e, "fcre") == 0) { - fce_ev_enabled |= FCE_FILE_CREATE; - } else if (strcmp(e, "dcre") == 0) { - fce_ev_enabled |= FCE_DIR_CREATE; - } else if (strcmp(e, "tmsz") == 0) { - fce_ev_enabled |= FCE_TM_SIZE; + if (strcmp(p, "fmod") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_MODIFY); + } else if (strcmp(p, "fdel") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_DELETE); + } else if (strcmp(p, "ddel") == 0) { + fce_ev_enabled |= (1 << FCE_DIR_DELETE); + } else if (strcmp(p, "fcre") == 0) { + fce_ev_enabled |= (1 << FCE_FILE_CREATE); + } else if (strcmp(p, "dcre") == 0) { + fce_ev_enabled |= (1 << FCE_DIR_CREATE); + } else if (strcmp(p, "tmsz") == 0) { + fce_ev_enabled |= (1 << FCE_TM_SIZE); } } diff --git a/etc/afpd/fce_api_internal.h b/etc/afpd/fce_api_internal.h index f405cabf..d73b775a 100755 --- a/etc/afpd/fce_api_internal.h +++ b/etc/afpd/fce_api_internal.h @@ -20,6 +20,7 @@ struct udp_entry char *addr; char *port; struct addrinfo addrinfo; + struct sockaddr_storage sockaddr; time_t next_try_on_error; /* In case of error set next timestamp to retry */ }; diff --git a/include/atalk/fce_api.h b/include/atalk/fce_api.h index 2e23a81d..b6111e4c 100755 --- a/include/atalk/fce_api.h +++ b/include/atalk/fce_api.h @@ -28,13 +28,14 @@ * be shure about datastructs and type sizes between platforms. * Format is network byte order. */ +#define FCE_PACKET_HEADER_SIZE 8+1+1+4+2 struct fce_packet { char magic[8]; unsigned char version; unsigned char mode; - uint32_t event_id; /* network byte order */ - uint16_t len; /* network byte order */ + uint32_t event_id; + uint16_t datalen; char data[MAXPATHLEN]; }; @@ -50,7 +51,7 @@ int fce_register_tm_size(const char *vol, size_t used); int fce_add_udp_socket(const char *target ); // IP or IP:Port int fce_set_coalesce( char *coalesce_opt ); // all|delete|create -int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre,tmsz (default is all) */ +int fce_set_events(const char *events); /* fmod,fdel,ddel,fcre,dcre,tmsz (default is all except tmsz) */ #define FCE_DEFAULT_PORT 12250 #define FCE_DEFAULT_PORT_STRING "12250" diff --git a/include/atalk/util.h b/include/atalk/util.h index 79f6db2b..811c0ee6 100644 --- a/include/atalk/util.h +++ b/include/atalk/util.h @@ -52,8 +52,8 @@ #define hton64(x) (x) #define ntoh64(x) (x) #else /* BYTE_ORDER == BIG_ENDIAN */ -#define hton64(x) ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ - (u_int64_t) ((htonl(x) & 0xffffffffLL) << 32)) +#define hton64(x) ((uint64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ + (uint64_t) ((htonl(x) & 0xffffffffLL) << 32)) #define ntoh64(x) (hton64(x)) #endif /* BYTE_ORDER == BIG_ENDIAN */ -- 2.39.2