/** * Lookups up the MAC address for the provided IP in the ARP table * The result (if found) is copied into the mac array * 0 is return if the result was found. * non-zero result if the result was not found. * * We read /proc/net/arp instead of using ioctl/SIOCGARP because the latter * requires that we specify an interface. We don't really care about * interface so we just read the file instead. */ int netcap_arp_lookup ( const char* ip, char* mac, int maclength ) { FILE* file = fopen("/proc/net/arp", "r"); /* should check the result */ char line[256]; char* saveptr; int i; char* tok; int linecount = 0; while (fgets(line, sizeof(line), file)) { linecount++; if ( linecount == 1 ) continue; for ( i=0, tok=strtok_r(line," \t",&saveptr); tok ; i++, tok=strtok_r(NULL," \t",&saveptr) ) { //errlog( ERR_WARNING, "TOKEN[%i]: %s\n", i, tok); if ( i == 0 ) { if ( strcmp( tok, ip) != 0 ) break; } if ( i == 3 ) { strncpy( mac, tok, maclength ); if ( fclose(file) < 0 ) perrlog( "fclose"); return 0; } } } if ( fclose(file) < 0 ) perrlog( "fclose"); return -1; }
/* Run on every file of the shared dir, if a file is not alredy in the shared array * or has different size/mtime the new_list array is enlarged and a new * fileinfo struct is allocated */ static int file_walk_callback(const char *path, const struct stat *sptr, int type) { uint32_t i; int32_t n = -1; if (type == FTW_DNR) ywarn("Directory %s cannot be traversed.\n", path); if (type == FTW_F) { for(i=0;i<shr_list_len;i++) { if((strcmp(path, shr_list[i]->file) == 0) &&\ (sptr->st_mtime == shr_list[i]->mtime) &&\ (sptr->st_size == shr_list[i]->length)) { n = i; break; } } if(n == -1) { new_list = realloc(new_list, sizeof(FileNode *) * (new_list_len + 1)); if(new_list == NULL) { perrlog("realloc"); return -1; } new_list[new_list_len] = malloc(sizeof(FileNode)); if(new_list[new_list_len] == NULL) { perrlog("malloc"); return -1; } new_list[new_list_len]->file = strdup(path); new_list[new_list_len]->BLAKE2b = NULL; new_list[new_list_len]->mtime = sptr->st_mtime; new_list[new_list_len]->length = sptr->st_size; new_list[new_list_len]->exists = true; new_list_len++; } } return 0; }
/* tox_hash() is sha256. * */ static int file_checksumcalc_noblock(uint8_t *BLAKE2b, char *filename) { static FILE *f = NULL; uint32_t i; int rc; uint8_t buf[HASHING_BUFSIZE]; static crypto_generichash_state state; if(!f) { if(!(f = fopen(filename, "rb"))) { perrlog("fopen"); return(-1); } // state = sodium_malloc(crypto_generichash_statebytes()); // buf = malloc(HASHING_BUFSIZE); crypto_generichash_init(&state, NULL, 0, TOX_FILE_ID_LENGTH); } if((i = fread(buf, 1, HASHING_BUFSIZE, f)) > 0) { crypto_generichash_update(&state, buf, HASHING_BUFSIZE); rc = i; } else { crypto_generichash_final(&state, BLAKE2b, TOX_FILE_ID_LENGTH); if(fclose(f) != 0) perrlog("fclose"); f = NULL; rc = 0; } /* rc > 0: still hashing * rc == 0: complete * rc < 0: error*/ return(rc); }
int file_walk_shared(const char *shrdir) { char *abspath = NULL; int rc; abspath = canonicalize_file_name(shrdir); if(!abspath) { perrlog("canonicalize_file_name"); return -1; } rc = ftw(abspath, file_walk_callback, SHRDIR_MAX_DESCRIPTORS); free(abspath); /* no new files found */ if(new_list_len == 0) file_recheck = false; return rc; }
/* If the recheck flag is set and there is no hashing operations running * walks the directory. * * If there are new files and nothing is currently hashing pick the latest * file from the new_list and check if it's alredy in shr_list: * - if totally new, reallocate the shared list to accomodate the new * - if preexisting in shr_list, free the old and point it to the data of the new * then shrink the new_list, removing the last element (frees it when it's empty), * finally allocate a FileHash struct for the new element in shr_list and set a flag for hashing * * If the hashing flag was set, take it's number and start the hashing, * when the entire file has been read or an error occurs clear the hashing flag.*/ int file_do(const char *shrdir) { uint32_t i, t; int32_t rc, n = -1; static int hashing = -1; static int last; if(file_recheck && new_list_len == 0 && hashing == -1) { file_exists_shared(); file_walk_shared(shrdir); } i = new_list_len - 1; /* Starts from last element */ if(new_list_len > 0 && hashing == -1) { for(t=0;t<shr_list_len;t++) { if(strcmp(new_list[i]->file, shr_list[t]->file) == 0) { n = i; break; } } if(n == -1) { shr_list = realloc(shr_list, sizeof(FileNode *) * (shr_list_len + 1)); if(shr_list == NULL) { perrlog("realloc"); return -1; } shr_list[shr_list_len] = new_list[i]; last = shr_list_len; shr_list_len++; } else { free(shr_list[t]->file); free(shr_list[t]->BLAKE2b); free(shr_list[t]); shr_list[t] = new_list[n]; last = t; } new_list = realloc(new_list, sizeof(FileNode *) * (new_list_len - 1)); new_list_len--; if(new_list == NULL && new_list_len != 0) { perrlog("realloc"); return -1; } shr_list[last]->BLAKE2b = malloc(TOX_FILE_ID_LENGTH); if(shr_list[last]->BLAKE2b == NULL) { perrlog("malloc"); return -1; } hashing = last; } if(hashing >= 0) { rc = file_checksumcalc_noblock(shr_list[last]->BLAKE2b, shr_list[last]->file); if(rc <= 0) { hashing = -1; if(new_list_len == 0) file_recheck = false; /* execute callback for new file*/ if(file_new_c != NULL) file_new_c(shr_list[last], last); yinfo("Hash: %i - %s", last, shr_list[last]->file); /* write filenode to cache */ // char cachepath[PATH_MAX + 20]; // snprintf(cachepath, sizeof(cachepath), "%s/%i", cachedir, last); // filenode_dump(shr_list[last], cachepath); // TODO } if(rc < 0) return -1; } return 0; }