static packet_t wpk_clone(packet_t p){ if(packet_type(p) == WPACKET){ wpacket_t _w = (wpacket_t)p; wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w)); //w->writebuf = NULL; //w->len = NULL; packet_begpos(w) = packet_begpos(_w); packet_buf(w) = buffer_acquire(NULL,packet_buf(_w)); //packet_next(w) = NULL; packet_type(w) = WPACKET; packet_datasize(w) = packet_datasize(_w); packet_clone(w) = wpk_clone; packet_makeforwrite(w) = wpk_clone; packet_makeforread(w) = wpk_makeforread; return (packet_t)w; }else return NULL; }
static int LoadSignature(const CString &signatureFilename, signature_packet_t *p_sig) { FILE * pFile = _tfsopen(signatureFilename, _T("rb"), SH_DENYWR); if (pFile) { int size = 65536; std::unique_ptr<unsigned char[]> buffer(new unsigned char[size]); int length = 0; if ((length = (int)fread(buffer.get(), sizeof(char), size, pFile)) >= 8) { fclose(pFile); // is unpacking needed? if ((uint8_t)buffer[0] < 0x80) { std::unique_ptr<unsigned char[]> unpacked(new unsigned char[size]); size = pgp_unarmor((char *)buffer.get(), length, unpacked.get(), length); if (size < 2) return -1; buffer.swap(unpacked); } else size = length; if (packet_type(buffer[0]) != SIGNATURE_PACKET) return -1; DWORD i_header_len = packet_header_len(buffer[0]); if ((i_header_len != 1 && i_header_len != 2 && i_header_len != 4) || i_header_len + 1 > (DWORD)size) return -1; DWORD i_len = scalar_number((uint8_t *)(buffer.get() + 1), i_header_len); if (i_len + i_header_len + 1 != (DWORD)size) return -1; if (parse_signature_packet(p_sig, (uint8_t *)(buffer.get() + 1 + i_header_len), i_len)) return -1; if (p_sig->type != BINARY_SIGNATURE && p_sig->type != TEXT_SIGNATURE) { if (p_sig->version == 4) { free(p_sig->specific.v4.hashed_data); free(p_sig->specific.v4.unhashed_data); } return -1; } return 0; } else fclose(pFile); } return -1; }
packet_t rpk_makeforwrite(packet_t p){ if(packet_type(p) == RPACKET){ rpacket_t r = (rpacket_t)p; wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w)); //w->writebuf = NULL; //w->len = NULL;//触发拷贝之前len没有作用 //w->wpos = 0; //packet_next(w) = NULL; packet_type(w) = WPACKET; packet_begpos(w) = packet_begpos(r); packet_buf(w) = buffer_acquire(NULL,packet_buf(r)); packet_datasize(w) = kn_ntoh32(r->len) + sizeof(r->len); packet_clone(w) = wpk_clone; packet_makeforwrite(w) = wpk_clone; packet_makeforread(w) = wpk_makeforread; return (packet_t)w; }else return NULL; }
wpacket_t wpk_create(uint32_t size) { size = size_of_pow2(size); if(size < 64) size = 64; wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w)); packet_buf(w) = buffer_create(size); w->writebuf = packet_buf(w);//buffer_acquire(NULL,packet_buf(w)); //packet_begpos(w)= 0; //packet_next(w) = NULL; packet_type(w) = WPACKET; w->wpos = sizeof(*(w->len)); w->len = (uint32_t*)packet_buf(w)->buf; *(w->len) = 0; packet_buf(w)->size = sizeof(*(w->len)); packet_datasize(w) = sizeof(*(w->len)); packet_clone(w) = wpk_clone; packet_makeforwrite(w) = wpk_clone; packet_makeforread(w) = wpk_makeforread; return w; }
wpacket_t wpk_create_by_bin(int8_t *addr,uint32_t size) { uint32_t datasize = size; size = size_of_pow2(size); if(size < 64) size = 64; wpacket_t w = (wpacket_t)CALLOC(g_wpk_allocator,1,sizeof(*w));//calloc(1,sizeof(*w)); packet_buf(w) = buffer_create(size); w->writebuf = packet_buf(w);//buffer_acquire(NULL,packet_buf(w)); //packet_begpos(w)= 0; //packet_next(w) = NULL; packet_type(w) = WPACKET; memcpy(&w->writebuf->buf[0],addr,datasize); w->len = (uint32_t*)packet_buf(w)->buf; w->wpos = datasize; packet_buf(w)->size = datasize; packet_datasize(w) = datasize; packet_clone(w) = wpk_clone; packet_makeforwrite(w) = wpk_clone; packet_makeforread(w) = wpk_makeforread; return w; }
int main(){ int sock,size,flags; char buf[1024]; struct sockaddr_ll addr; struct ifreq ifr; unsigned char hwaddr[6]; PACKET pk_start; if((sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_PAE)))<0){ printf("create raw socket error\n"); return -1; } /*flags=fcntl(sock,F_GETFL,0); printf("%d\n",flags); if(fcntl(sock,F_SETFL,flags|O_NONBLOCK)<0) { printf("set nonblock error\n"); return -1; }*/ strcpy(ifr.ifr_name,"eth0"); if(ioctl(sock,SIOCGIFINDEX,&ifr)<0) { printf("get ifindex error\n"); return -1; } printf("%d\n",ifr.ifr_ifindex); bzero(&addr,sizeof(struct sockaddr_ll)); addr.sll_family=PF_PACKET; addr.sll_protocol=htons(ETH_P_PAE); addr.sll_ifindex=ifr.ifr_ifindex; if(bind(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_ll))<0) { printf("bind error\n"); return -1; } if(gethwaddr(hwaddr)<0) { printf("get hwaddr error\n"); return -1; } printf("mac %02x:%02x:%02x:%02x:%02x:%02x\n",hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]); get_start_packet(&pk_start,hwaddr); if(sendto(sock,&pk_start,sizeof(pk_start),0,(struct sockaddr *)&addr,sizeof(struct sockaddr_ll))<0) { printf("send packet error"); return -1; } PACKET pkt_recv; printf("recv message\n"); //block until receive message size=recvfrom(sock,(void *)&pkt_recv,sizeof(pkt_recv),0,NULL,NULL); int type = packet_type(&pkt_recv); int id = pkt_recv.body.test.id; printf("id is %d\n",id); if(type!=1) { printf("warning:identity packet type is 1\n"); return -1; } PACKET pkt_id; get_identity_packet(&pkt_id,id,hwaddr); if(sendto(sock,&pkt_id,sizeof(pk_start),0,(struct sockaddr *)&addr,sizeof(struct sockaddr_ll))<0) { printf("send packet error"); return -1; } bzero(&pkt_recv,sizeof(pkt_recv)); size=recvfrom(sock,(void *)&pkt_recv,sizeof(pkt_recv),0,NULL,NULL); printf("%d\n",size); return 0; }
/* * fill a public_key_t with public key data, including: * * public key packet * * signature packet issued by key which long id is p_sig_issuer * * user id packet */ int parse_public_key( const uint8_t *p_key_data, size_t i_key_len, public_key_t *p_key, const uint8_t *p_sig_issuer ) { const uint8_t *pos = p_key_data; const uint8_t *max_pos = pos + i_key_len; int i_status = 0; #define PUBLIC_KEY_FOUND 0x01 #define USER_ID_FOUND 0x02 #define SIGNATURE_FOUND 0X04 uint8_t *p_key_unarmored = NULL; p_key->psz_username = NULL; p_key->sig.specific.v4.hashed_data = NULL; p_key->sig.specific.v4.unhashed_data = NULL; if( !( *pos & 0x80 ) ) { /* first byte is ASCII, unarmoring */ p_key_unarmored = (uint8_t*)malloc( i_key_len ); if( !p_key_unarmored ) return VLC_ENOMEM; int i_len = pgp_unarmor( (char*)p_key_data, i_key_len, p_key_unarmored, i_key_len ); if( i_len == 0 ) goto error; pos = p_key_unarmored; max_pos = pos + i_len; } while( pos < max_pos ) { if( !(*pos & 0x80) || *pos & 0x40 ) goto error; int i_type = packet_type( *pos ); int i_header_len = packet_header_len( *pos++ ); if( pos + i_header_len > max_pos || ( i_header_len != 1 && i_header_len != 2 && i_header_len != 4 ) ) goto error; int i_packet_len = scalar_number( pos, i_header_len ); pos += i_header_len; if( pos + i_packet_len > max_pos ) goto error; switch( i_type ) { case PUBLIC_KEY_PACKET: i_status |= PUBLIC_KEY_FOUND; if( parse_public_key_packet( &p_key->key, pos, i_packet_len ) != VLC_SUCCESS ) goto error; break; case SIGNATURE_PACKET: /* we accept only v4 signatures here */ if( i_status & SIGNATURE_FOUND || !p_sig_issuer ) break; int i_ret = parse_signature_packet( &p_key->sig, pos, i_packet_len ); if( i_ret == VLC_SUCCESS ) { if( p_key->sig.version != 4 ) break; if( memcmp( p_key->sig.issuer_longid, p_sig_issuer, 8 ) ) { free( p_key->sig.specific.v4.hashed_data ); free( p_key->sig.specific.v4.unhashed_data ); p_key->sig.specific.v4.hashed_data = NULL; p_key->sig.specific.v4.unhashed_data = NULL; break; } i_status |= SIGNATURE_FOUND; } break; case USER_ID_PACKET: if( p_key->psz_username ) /* save only the first User ID */ break; i_status |= USER_ID_FOUND; p_key->psz_username = (uint8_t*)malloc( i_packet_len + 1); if( !p_key->psz_username ) goto error; memcpy( p_key->psz_username, pos, i_packet_len ); p_key->psz_username[i_packet_len] = '\0'; break; default: break; } pos += i_packet_len; } free( p_key_unarmored ); if( !( i_status & ( PUBLIC_KEY_FOUND | USER_ID_FOUND ) ) ) return VLC_EGENERIC; if( p_sig_issuer && !( i_status & SIGNATURE_FOUND ) ) return VLC_EGENERIC; return VLC_SUCCESS; error: if( p_key->sig.version == 4 ) { free( p_key->sig.specific.v4.hashed_data ); free( p_key->sig.specific.v4.unhashed_data ); } free( p_key->psz_username ); free( p_key_unarmored ); return VLC_EGENERIC; }
/****************************************************************************** Start obsluhy klienta Inspirace (vytvoreni socketu, bind): http://beej.us/guide/bgnet/output/html/multipage/clientserver.html#datagram *******************************************************************************/ int Client::start(Opt *options, struct sockaddr_storage client_addr, int index, char *buf, int numbytes, int mtu) { // Generovani nahodneho cisla pro port, na kterem bude klient obsluhovan srand (getpid()); int port = rand() % MAX_PORT + MIN_PORT; client_port = to_string(port); service_ip = options->address_at(index); int sockfd; struct addrinfo hints, *servinfo, *p; int rv; socklen_t addr_len; char s[INET6_ADDRSTRLEN]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; signal(SIGINT, client_signal_reaction); // Registrace funkce pro odchyt signalu if ((rv = getaddrinfo(service_ip.c_str(), client_port.c_str(), &hints, &servinfo)) != 0) { cerr << "Error - Service " << service_ip << ", " << client_port << gai_strerror(rv) << endl; return EXIT_FAILURE; } for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { continue; } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); continue; } break; } if (p == NULL) { cerr << "Error - Service " << service_ip << ", " << client_port << " - failed to bind socket" << endl; return EXIT_FAILURE; } freeaddrinfo(servinfo); client_socket = sockfd; // Ulozim si deskr. socketu // Nastavi se vychozi timeout socketu if((set_socket_timeout(options, IMPLICIT_TIMEOUT)) == SET_FAILED) return EXIT_FAILURE; // ulozim si klientovu IP pro potreby vypisu informacnich hlasek string client_ip = inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s); mtu_size = mtu; // Ulozim si MTU // Cinnost obsluhy serveru string err_msg; unsigned int data_counter = 0; // Pocitadlo dat unsigned int block_counter = 0; // Pocitadlo bloku int data_len; // Pocet odeslanych B int mode; // Mod prenosu int tryouts = 0; // Pocet pokusu o znovu navazani komunikace bool reading_data = false; // Flag cteni dat bool writing_data = false; // Flag zapisu dat int ack; // Cislo potvrzeneho bloku int type; // Typ paketu int file_status; // Info o uspesnosti operace se souborem int bytes_write; // Pocet zapsanych bajtu int block_num; // Cislo bloku int recv_status; // Pocet prijatych B pri volani funkce recvfrom() char *file_buf; // Buffer pro nacitani dat ze souboru int file_buf_size;// Velikost bufferu File *f = new File(); // Nova instance objektu pro praci se soubory while(1) {// Smycka obsluhy klienta if(writing_data == true) type = packet_type(file_buf); // buffer na heapu else type = packet_type(buf); // buffer na zasobniku switch(type) {// Podle typu paketu se provadi dana operace case RRQ: {// Zadost o cteni get_filename(buf); // ukladani jmena souboru // Zjisti se mod prenosu mode = transfer_mode(buf); if(mode == UNKNOWN_MODE) {// neznamy mod err_msg = "Unknown mode"; send_error(sockfd, client_addr, err_msg, ERROR_IL); cout << current_time() << client_ip << " Unknown mode, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else if(mode == NETASCII) { cout << current_time() + client_ip + " Requested READ of " << filename << " [netascii]"<< endl; } else if(mode == OCTET) { cout << current_time() + client_ip + " Requested READ of " << filename << " [octet]"<< endl; } // Otevre se soubor pro cteni file_status = f->open(filename, options->working_path(), FILE_IN, mode_tr); if(file_status == NOT_FOUND) {// Soubor nebyl nalezen err_msg = "File not found"; send_error(sockfd, client_addr, err_msg, ERROR_NF); cout << current_time() + client_ip + " File " << filename << " not found, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else if(file_status == PERM_DEN) {// Nedostatecne opravneni err_msg = "Permission denided"; send_error(sockfd, client_addr, err_msg, ERROR_AV); cout << current_time() << client_ip << " Permission denided, operation aborted" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } // Zjisti se pritomnost rozsireni if(opt_extension(buf, numbytes, options, f) == EXTENSION) {// request obsahuje options send_oack(sockfd, client_addr); reading_data = true; // Alokace bufferu pro nacitani souboru if(block_size.used == true) {// byla specifikovana velikost bloku file_buf = new char[block_size.value + 1]; file_buf_size = block_size.value + 1; if(f->get_file_size() > MAX_BLOCK_COUNT * block_size.value) {// Soubor je prilis velky na prenos pres tftp err_msg = "File is too large to send"; send_error(sockfd, client_addr, err_msg, ERROR_DF); cout << current_time() + client_ip + " File is too large to send. Operation aborted\n"; clean_sources(f, sockfd); return EXIT_FAILURE; } } else {// mezi parametry nebyla velikost bloku, uvazuje se standardni file_buf = new char[STANDARD_BLOCK + 1]; file_buf_size = STANDARD_BLOCK + 1; } } else {// bez parametru, posilani prvnich dat if(f->get_file_size() > MAX_BLOCK_COUNT * STANDARD_BLOCK) {// Soubor je prilis velky na prenos pres tftp err_msg = "File is too large to send"; send_error(sockfd, client_addr, err_msg, ERROR_IL); cout << current_time() + client_ip + " File is too large to send. Operation aborted\n"; clean_sources(f, sockfd); return 1; } // Alokace bufferu pro nacitani souboru - standardni velikost file_buf = new char[STANDARD_BLOCK + 1]; reading_data = true; cout << current_time() + client_ip + " Sending DATA\n"; // poslou se prvni data data_len = send_data(sockfd, client_addr, 1, STANDARD_BLOCK, f, file_buf); data_counter += data_len; if(data_len < STANDARD_BLOCK) {// Prvni blok je zaroven i posledni, tim konci cinnost reading_data = false; } } break; } case WRQ: {// Zadost o zapis get_filename(buf); // ulozim jmeno souboru // Zjistim mod prenosu mode = transfer_mode(buf); if(mode == UNKNOWN_MODE) {// neznamy mod err_msg = "Unknown transfer mode"; send_error(sockfd, client_addr, err_msg, ERROR_IL); break; } else if(mode == NETASCII) { cout << current_time() << client_ip << " Requested WRITE of " << filename << " [netascii]" << endl; } else if(mode == OCTET) { cout << current_time() << client_ip << " Requested WRITE of " << filename << " [octet]" << endl; } // Otevre se soubor pro zapis if(mode == OCTET) { file_status = f->open(filename, options->working_path(), FILE_OUT, OCTET); } else if(mode == NETASCII) { file_status = f->open(filename, options->working_path(), FILE_OUT, NETASCII); } if(file_status == FILE_EXISTS) {// Soubor j*z existuje err_msg = "File already exists"; send_error(sockfd, client_addr, err_msg, ERROR_AE); cout << current_time() << client_ip << " File " << filename << " already exists, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else if(file_status == CANNOT_OPEN) {// Nelze otevrit err_msg = "Cannot open file for writing"; send_error(sockfd, client_addr, err_msg, ERROR_IL); cout << current_time() << client_ip << " Cannot opet file " << filename << " for writing, operation aborted" << endl; clean_sources(f, sockfd); return 1; } // Zjisti se rozsireni if(opt_extension(buf, numbytes, options, f) == EXTENSION) {// request obsahuje options send_oack(sockfd, client_addr); // Alokace bufferu pro nacitani souboru if(block_size.used == true) {// byla specifikovana velikost bloku file_buf = new char[block_size.value + 10]; file_buf_size = block_size.value + 10; } else {// mezi parametry nebyla velikost bloku, uvazuje se standardni file_buf = new char[STANDARD_BLOCK + 10]; file_buf_size = STANDARD_BLOCK + 10; } writing_data = true; cout << current_time() + client_ip + " Receiving DATA\n"; } else {// Bez rozsireni, zasle se ack 0 send_ack(sockfd, client_addr, 0); // Alokace bufferu pro zapis souboru - standardni velikost file_buf = new char[STANDARD_BLOCK + 10]; file_buf_size = STANDARD_BLOCK + 10; writing_data = true; cout << current_time() + client_ip + " Receiving DATA\n"; } break; } case DATA: {// Datovy paket od klienta if(writing_data == true) {// Probiha prenos block_num = ack_number(file_buf); // zjisti se cislo bloku if((block_counter + 1) != block_num) {// Prisel blok, ktery nenavazuje na predchozi err_msg = "Error while file transfer"; send_error(sockfd, client_addr, err_msg, ERROR_IL); break; } int actual_block; if(block_size.used == true) {// Pouziva se nestandardni velikost bloku actual_block = block_size.value; bytes_write = recv_data(file_buf, numbytes, actual_block, f); // zapisou se data } else {// Standardni velikost bloku actual_block = STANDARD_BLOCK; bytes_write = recv_data(file_buf, numbytes, actual_block, f); // zapisou se data } if(bytes_write >= 0) {// Zapis byl uspesny, potvrdi se klientovi send_ack(sockfd, client_addr, block_num); block_counter++; // zvetsi se pocitadlo ulozenych bloku data_counter += bytes_write; // pricte se pocet ulozenych dat k pocitadlu if((numbytes - 4) < actual_block) {// dat bylo min nez je velikost bloku writing_data = false; f->close_file(FILE_OUT); // uzavre se soubor pro zapis cout << current_time() << client_ip << " File " << filename << " has been stored [" << data_counter << " B, " << block_counter << " blocks]" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } } else if(bytes_write == READ_ERR) {// Zapis nebyl uspesny err_msg = "Error while writing to file"; send_error(sockfd, client_addr, err_msg, ERROR_IL); clean_sources(f, sockfd); return EXIT_FAILURE; } } break; } case ACK: {// Potvrzeni od klienta, ze obdrzel konkretni datovy paket ack = ack_number(buf); if(ack == 0) cout << current_time() + client_ip + " Sending DATA\n"; if(reading_data == true) {// prenos jeste nebyl dokoncen if(block_size.used == true) {// Pouziva se nestandardni velikost bloku data_len = send_data(sockfd, client_addr, ack + 1, block_size.value, f, file_buf); if(data_len == SEND_FAIL) {// Chyba pri odesilani cerr << current_time() << client_ip << " Error in sendto, operation aborted" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } else if(data_len < block_size.value) reading_data = false; } else {// Standardni velikost bloku data_len = send_data(sockfd, client_addr, ack + 1, STANDARD_BLOCK, f, file_buf); if(data_len == SEND_FAIL) {// Chyba pri odesilani cerr << current_time() << client_ip << " Error in sendto, operation aborted" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } else if(data_len < STANDARD_BLOCK) reading_data = false; } data_counter += data_len; } else {// Prenos byl dokoncen cout << current_time() << client_ip << " File " << filename << " has been sent [" << data_counter << " B, " << ack << " blocks]\n"; clean_sources(f, sockfd); return EXIT_SUCCESS; } break; } case ERR: {// Error paket int err; if(reading_data == true) {// Klient poslal error pri cteni dat err = recv_error(buf); switch(err) { case ERROR_UN: {// Unknown transfer ID f->close_file(FILE_IN); cout << current_time() << client_ip << " Client aborted file read (transport error)" << endl; return EXIT_FAILURE; } case ERROR_DF: {// Disk full f->close_file(FILE_IN); cout << current_time() << client_ip << " Client aborted file read (too large)" << endl; return EXIT_FAILURE; } case ERROR_ND: {// Nedefinovana chyba f->close_file(FILE_IN); cout << current_time() << client_ip << " Client aborted file read (undefined error)" << endl; return EXIT_FAILURE; } } } else if(writing_data == true) {// Klient poslal error pri zapisu dat err = recv_error(buf); switch(err) { case ERROR_UN: {// Unknown transfer ID f->close_file(FILE_OUT); cout << current_time() << client_ip << " Client aborted file write" << endl; return EXIT_FAILURE; } case ERROR_ND: {// Nedefinovana chyba f->close_file(FILE_OUT); cout << current_time() << client_ip << " Client aborted file read (undefined error)" << endl; return EXIT_FAILURE; } } } break; } case UNKNOWN_OPCODE: {// Neznamy opcode err_msg = "Unknown request"; send_error(sockfd, client_addr, err_msg, ERROR_IL); clean_sources(f, sockfd); return EXIT_FAILURE; } }// konec switch(type) if(writing_data == true) {// Pokud probiha zapis, pouziva se vetsi buffer alokovany na halde recv_status = recv_packet(sockfd, client_addr, file_buf, file_buf_size); } else {// Pri cteni staci mensi velikost na zasobniku recv_status = recv_packet(sockfd, client_addr, buf, BUFSIZE); } if(recv_status == TIMEOUT_ELAPSED) {// Vyprsel cas cekani, probehne 3x pokus o znovu navazani komunikace tryouts++; if(tryouts == 3) {// Probehly tri pokusy o znovu navazani komunikace cout << current_time() << client_ip << " Timeout elapsed, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else {// Probehne pokus cout << current_time() << client_ip << " Timeout elapsed, retrying..." << endl; } } else {// Byl normalne prijat paket numbytes = recv_status; tryouts = 0; // Vynuluje se pocitadlo neuspesnych pokusu } } }