/** * Initialization based on command line args */ void initialize() { char tempf1[MAXPATHNAME], hostname[256]; struct hostent *hp; struct in_addr *addr; int fd, i; parent = 0; // Load list of multicast interfaces if (interface_count == 0) { for (i = 0; i < ifl_len; i++) { if (!ifl[i].isloopback) { m_interface[interface_count++] = ifl[i]; } } } // No non-loopback interfaces, so just use the hostname's interface if (interface_count == 0) { gethostname(hostname, sizeof(hostname)); if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Can't get host name\n"); exit(1); } else { addr = (struct in_addr *)hp->h_addr_list[0]; m_interface[interface_count].addr = *addr; m_interface[interface_count].ismulti = 1; m_interface[interface_count++].isloopback = 0; } } if (uid) { m_interface[interface_count].addr.s_addr = uid; m_interface[interface_count].ismulti = 0; m_interface[interface_count++].isloopback = 0; } // Check validity of dest, backup, and temp directories for (i = 0; i < destdircnt; i++) { if (!isfullpath(destdir[i])) { fprintf(stderr, "ERROR: must specify absolute pathname " "for dest directory\n"); exit(1); } snprintf(tempf1, sizeof(tempf1)-1, "%s%c_uftptmp1",destdir[i],PATH_SEP); tempf1[sizeof(tempf1)-1] = '\x0'; if ((fd = open(tempf1, O_WRONLY | O_CREAT, 0644)) < 0) { perror("couldn't write to dest directory"); exit(1); } close(fd); unlink(tempf1); if (backupcnt > 0) { // backupcnt and destdircnt are always equal if (!strcmp(backupdir[i], destdir[i])) { fprintf(stderr, "ERROR: corresponding backup dir and dest dir " "must be different\n"); exit(1); } if (!isfullpath(backupdir[i])) { fprintf(stderr, "ERROR: must specify absolute pathname " "for backup directory\n"); exit(1); } if (!dirs_movable(destdir[i], backupdir[i])) { exit(1); } } } if (strcmp(tempdir, "")) { if (destdircnt > 1) { fprintf(stderr, "ERROR: Cannot use a temp directory " "with multiple dest directories\n"); exit(1); } if (backupcnt > 0) { fprintf(stderr, "ERROR: Cannot use a temp directory " "with a backup directory\n"); exit(1); } if (!strcmp(tempdir, destdir[0])) { fprintf(stderr, "ERROR: temp dir and dest dir must be different\n"); exit(1); } if (!isfullpath(tempdir)) { fprintf(stderr, "ERROR: must specify absolute pathname " "for temp directory\n"); exit(1); } if (!dirs_movable(tempdir, destdir[0])) { exit(1); } } if (!pub_multi_count) { pub_multi[0].s_addr = inet_addr(DEF_PUB_MULTI); pub_multi_count = 1; } for (i = 0; i < MAXLIST; i++) { group_list[i].group_id = 0; } next_hb_time.tv_sec = 0; next_hb_time.tv_usec = 0; next_keyreq_time.tv_sec = 0; next_keyreq_time.tv_usec = 0; atexit(cleanup); key_init(); create_sockets(); daemonize(); showtime = 1; }
/** * Validate and establish the destination name of an incoming file. * Returns 0 if the file was rejected for some reason, 1 otherwise. */ int setup_dest_file(struct group_list_t *group) { int found_dest_dir, len, i; int (*cmp)(const char *, const char *); int (*ncmp)(const char *, const char *, size_t); #if PATH_SEP != '/' // First translate any '/' in the sent file name to PATH_SEP { char *p; while ((p = strchr(group->fileinfo.name, '/')) != NULL) { *p = PATH_SEP; } } #endif #ifdef WINDOWS cmp = stricmp; ncmp = strnicmp; #else cmp = strcmp; ncmp = strncmp; #endif if (isfullpath(group->fileinfo.name)) { if (strcmp(tempdir, "")) { glog1(group, "Rejecting file with absolute pathname: " "temp directory is in use"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } for (found_dest_dir = 0, i = 0; i < destdircnt; i++) { if (!ncmp(group->fileinfo.name, destdir[i], strlen(destdir[i]))) { if (!cmp(group->fileinfo.name, destdir[i])) { glog1(group, "Rejecting file with absolute pathname: " "can't have the same name as a dest directory"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } else { found_dest_dir = 1; break; } } } if (!found_dest_dir) { glog1(group, "Rejecting file with absolute pathname: " "doesn't match any dest directory"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } group->fileinfo.destdiridx = i; snprintf(group->fileinfo.filepath, sizeof(group->fileinfo.filepath), "%s", group->fileinfo.name); } else { if (!strcmp(tempdir, "")) { len = snprintf(group->fileinfo.filepath, sizeof(group->fileinfo.filepath), "%s%c%s", destdir[0], PATH_SEP, group->fileinfo.name); } else { len = snprintf(group->fileinfo.filepath, sizeof(group->fileinfo.filepath), "%s%c_group_%08X%c%s", tempdir, PATH_SEP, group->group_id, PATH_SEP, group->fileinfo.name); } if (len >= sizeof(group->fileinfo.filepath)) { glog1(group, "Rejecting file: max pathname length exceeded"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } } len = snprintf(group->fileinfo.temppath, sizeof(group->fileinfo.temppath), "%s.~uftp-%08X-%04X", group->fileinfo.filepath, group->group_id, group->file_id); if (len >= sizeof(group->fileinfo.temppath)) { glog1(group, "Rejecting file: max pathname length exceeded"); early_complete(group, COMP_STAT_REJECTED, 0); return 0; } return 1; }
/** * Initialization based on command line args */ void initialize(void) { char tempf1[MAXPATHNAME], hostname[256]; struct addrinfo ai_hints, *ai_rval; int rval, fd, i; parent = 0; srand((unsigned int)time(NULL) ^ getpid()); // Load list of multicast interfaces if (interface_count == 0) { for (i = 0; i < ifl_len; i++) { if (!ifl[i].isloopback) { m_interface[interface_count++] = ifl[i]; } } } // No non-loopback interfaces, so just use the hostname's interface if (interface_count == 0) { gethostname(hostname, sizeof(hostname)); memset(&ai_hints, 0, sizeof(ai_hints)); ai_hints.ai_family = AF_UNSPEC; ai_hints.ai_socktype = SOCK_DGRAM; ai_hints.ai_protocol = 0; ai_hints.ai_flags = 0; if ((rval = getaddrinfo(hostname, NULL, &ai_hints, &ai_rval)) != 0) { fprintf(stderr, "Can't get address of hostname %s: %s\n", hostname, gai_strerror(rval)); exit(ERR_PARAM); } memcpy(&m_interface[interface_count].su, ai_rval->ai_addr, ai_rval->ai_addrlen); m_interface[interface_count].ismulti = 1; m_interface[interface_count++].isloopback = 0; freeaddrinfo(ai_rval); } if (!uid) { if (m_interface[0].su.ss.ss_family == AF_INET6) { uid = m_interface[0].su.sin6.sin6_addr.s6_addr[12] << 24; uid |= m_interface[0].su.sin6.sin6_addr.s6_addr[13] << 16; uid |= m_interface[0].su.sin6.sin6_addr.s6_addr[14] << 8; uid |= m_interface[0].su.sin6.sin6_addr.s6_addr[15]; } else { uid = m_interface[0].su.sin.sin_addr.s_addr; } } // Check validity of dest, backup, and temp directories for (i = 0; i < destdircnt; i++) { if (!isfullpath(destdir[i])) { fprintf(stderr, "ERROR: must specify absolute pathname " "for dest directory\n"); exit(ERR_PARAM); } snprintf(tempf1, sizeof(tempf1)-1, "%s%c_uftptmp1",destdir[i],PATH_SEP); tempf1[sizeof(tempf1)-1] = '\x0'; if ((fd = open(tempf1, O_WRONLY | O_CREAT, 0644)) < 0) { perror("couldn't write to dest directory"); exit(ERR_PARAM); } close(fd); unlink(tempf1); if (backupcnt > 0) { // backupcnt and destdircnt are always equal if (!strcmp(backupdir[i], destdir[i])) { fprintf(stderr, "ERROR: corresponding backup dir and dest dir " "must be different\n"); exit(ERR_PARAM); } if (!isfullpath(backupdir[i])) { fprintf(stderr, "ERROR: must specify absolute pathname " "for backup directory\n"); exit(ERR_PARAM); } if (!dirs_movable(destdir[i], backupdir[i])) { exit(ERR_PARAM); } } } if (strcmp(tempdir, "")) { if (destdircnt > 1) { fprintf(stderr, "ERROR: Cannot use a temp directory " "with multiple dest directories\n"); exit(ERR_PARAM); } if (backupcnt > 0) { fprintf(stderr, "ERROR: Cannot use a temp directory " "with a backup directory\n"); exit(ERR_PARAM); } if (!strcmp(tempdir, destdir[0])) { fprintf(stderr, "ERROR: temp dir and dest dir must be different\n"); exit(ERR_PARAM); } if (!isfullpath(tempdir)) { fprintf(stderr, "ERROR: must specify absolute pathname " "for temp directory\n"); exit(ERR_PARAM); } if (!dirs_movable(tempdir, destdir[0])) { exit(ERR_PARAM); } } if (strcmp(postreceive, "")) { if (!isfullpath(postreceive)) { fprintf(stderr, "ERROR: must specify absolute pathname " "for postreceive script\n"); exit(ERR_PARAM); } } if (!pub_multi_count) { memset(&ai_hints, 0, sizeof(ai_hints)); ai_hints.ai_family = AF_UNSPEC; ai_hints.ai_socktype = SOCK_DGRAM; ai_hints.ai_protocol = 0; ai_hints.ai_flags = AI_NUMERICHOST; if ((rval = getaddrinfo(DEF_PUB_MULTI, NULL, &ai_hints, &ai_rval)) != 0) { fprintf(stderr, "Can't get address of default public address: %s\n", gai_strerror(rval)); exit(ERR_PARAM); } memcpy(&pub_multi[0], ai_rval->ai_addr, ai_rval->ai_addrlen); freeaddrinfo(ai_rval); pub_multi_count = 1; } for (i = 0; i < MAXLIST; i++) { memset(&group_list[i], 0, sizeof(struct group_list_t)); } next_hb_time.tv_sec = 0; next_hb_time.tv_usec = 0; next_keyreq_time.tv_sec = 0; next_keyreq_time.tv_usec = 0; atexit(cleanup); key_init(); create_sockets(); daemonize(); showtime = 1; if (!strcmp(statusfilename, "@LOG")) { status_file = applog; } else if (strcmp(statusfilename, "")) { if ((status_file = fopen(statusfilename, "at")) == NULL) { perror("Can't open status file"); exit(ERR_PARAM); } } }