/* This is called when we want send our certificate */ int _gnutls_send_server_certificate(gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; if (session->internals.auth_struct-> gnutls_generate_server_certificate == NULL) return 0; _gnutls_buffer_init(&data); if (again == 0) { ret = session->internals.auth_struct-> gnutls_generate_server_certificate(session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = send_handshake(session, data.data, data.length, GNUTLS_HANDSHAKE_CERTIFICATE_PKT); if (ret < 0) { gnutls_assert(); } cleanup: _gnutls_buffer_clear(&data); return ret; }
int Peer::Init(network::Socket & sock, const TorrentInterfaceInternalPtr & torrent, PEER_ADD peer_add) { m_nm->Socket_set_assoc(sock, shared_from_this()); memset(&m_buf, 0, sizeof(network::buffer)); m_torrent = torrent; m_nm = torrent->get_nm(); m_g_cfg = torrent->get_cfg(); m_bitfield = new unsigned char[m_torrent->get_bitfield_length()]; memset(m_bitfield, 0, m_torrent->get_bitfield_length()); m_sleep_time = 0; m_peer_choking= true; m_peer_interested = false; m_am_choking = false;// m_am_interested = false;// m_downloaded = 0; m_uploaded = 0; m_sock = sock; memcpy(&m_addr, &m_sock->m_peer, sizeof(sockaddr_in)); get_peer_key(m_sock->m_peer, m_ip);//inet_ntoa(m_sock->m_peer.sin_addr); switch(peer_add) { case PEER_ADD_TRACKER: m_state = PEER_STATE_SEND_HANDSHAKE; break; case PEER_ADD_INCOMING: if (send_handshake() != ERR_NO_ERROR) goto_sleep(); if (send_bitfield() != ERR_NO_ERROR) goto_sleep(); m_state = PEER_STATE_GENERAL_READY; break; } return ERR_NO_ERROR; }
/* This is the function for the client to send the key * exchange message */ int _gnutls_send_client_kx_message (gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; if (session->internals.auth_struct->gnutls_generate_client_kx == NULL) return 0; _gnutls_buffer_init( &data); if (again == 0) { ret = session->internals.auth_struct->gnutls_generate_client_kx (session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = send_handshake (session, data.data, data.length, GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE); if (ret < 0) { gnutls_assert (); } cleanup: _gnutls_buffer_clear (&data); return ret; }
/* This is called when we want send our certificate */ int _gnutls_send_client_certificate (gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; if (session->key->certificate_requested == 0) return 0; if (session->internals.auth_struct->gnutls_generate_client_certificate == NULL) return 0; _gnutls_buffer_init( &data); if (again == 0) { if (gnutls_protocol_get_version (session) != GNUTLS_SSL3 || session->internals.selected_cert_list_length > 0) { /* TLS 1.0 or SSL 3.0 with a valid certificate */ ret = session->internals. auth_struct->gnutls_generate_client_certificate (session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } } /* In the SSL 3.0 protocol we need to send a * no certificate alert instead of an * empty certificate. */ if (gnutls_protocol_get_version (session) == GNUTLS_SSL3 && session->internals.selected_cert_list_length == 0) { ret = gnutls_alert_send (session, GNUTLS_AL_WARNING, GNUTLS_A_SSL3_NO_CERTIFICATE); } else { /* TLS 1.0 or SSL 3.0 with a valid certificate */ ret = send_handshake (session, data.data, data.length, GNUTLS_HANDSHAKE_CERTIFICATE_PKT); } cleanup: _gnutls_buffer_clear (&data); return ret; }
/* This is the function for the client to send the certificate * verify message */ int _gnutls_send_client_certificate_verify (gnutls_session_t session, int again) { gnutls_buffer_st data; int ret = 0; /* This is a packet that is only sent by the client */ if (session->security_parameters.entity == GNUTLS_SERVER) return 0; /* if certificate verify is not needed just exit */ if (session->key->certificate_requested == 0) return 0; if (session->internals.auth_struct->gnutls_generate_client_cert_vrfy == NULL) { gnutls_assert (); return 0; /* this algorithm does not support cli_cert_vrfy */ } _gnutls_buffer_init( &data); if (again == 0) { ret = session->internals. auth_struct->gnutls_generate_client_cert_vrfy (session, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } if (ret == 0) goto cleanup; } ret = send_handshake (session, data.data, data.length, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY); if (ret < 0) { gnutls_assert (); } cleanup: _gnutls_buffer_clear (&data); return ret; }
static void * block_tx_client_thread (void *vdata) { BlockTxClient *client = vdata; BlockTxInfo *info = client->info; BlockTxClientDoneCB cb = client->cb; evutil_socket_t data_fd; gboolean restart; retry: data_fd = connect_chunk_server (info->cs); if (data_fd < 0) { info->result = BLOCK_CLIENT_NET_ERROR; if (!info->transfer_once) { pipewrite (info->done_pipe[1], &info->result, sizeof(info->result)); /* Transfer manager always expects an ENDED response. */ int rsp = BLOCK_CLIENT_ENDED; pipewrite (info->done_pipe[1], &rsp, sizeof(rsp)); } return vdata; } client->data_fd = data_fd; if (send_handshake (data_fd, info) < 0) { if (!info->transfer_once) { pipewrite (info->done_pipe[1], &info->result, sizeof(info->result)); int rsp = BLOCK_CLIENT_ENDED; pipewrite (info->done_pipe[1], &rsp, sizeof(rsp)); } evutil_closesocket (client->data_fd); return vdata; } client->recv_buf = evbuffer_new (); restart = client_thread_loop (client); if (restart) { seaf_message ("Restarting block tx client.\n"); memset (client, 0, sizeof(BlockTxClient)); client->info = info; client->cb = cb; client->info->result = BLOCK_CLIENT_UNKNOWN; goto retry; } return vdata; }
/* Renvoie 1 en cas de succés, 0 en cas d'échec. */ int init_peer_connection(struct proto_peer *peer, const struct proto_client_handshake *hs) { int fd ; struct hostent *sp; struct sockaddr_in sins; pthread_mutex_lock(&peer->lock) ; sp = gethostbyaddr(&(peer->ipaddr), sizeof(peer->ipaddr), AF_INET); if (sp == NULL) { perror("gethostbyaddr"); exit(errno); } fd = socket(PF_INET, SOCK_STREAM, 0); if (fd == -1) { perror ("socket"); exit(errno); } sins.sin_family = AF_INET; memcpy (&sins.sin_addr, sp->h_addr_list[0], (size_t)sp->h_length); sins.sin_port = htons(peer->port); if (connect (fd, (struct sockaddr *)&sins, sizeof(sins)) == -1) { switch(errno) { case ECONNREFUSED : printf("Connection to peer %d failed. Peer removed from list.\n",peer->peerId); return 0 ; break ; default : perror ("connect"); } exit (errno); } peer->sockfd = fd ; pthread_mutex_unlock(&peer->lock) ; send_handshake(peer,hs) ; receive_handshake(peer,hs) ; return 1 ; }
int main(int argc, const char * argv[]) { struct { int verbose, _1_, keepalive, _2_, timeout, _3_; char * hostname, * port, * source_type, * source_name; } cfg; struct config_var vars[] = { // {"name", {0, f, r, n}, '-', "ENV_NAME", DEFAULT_VALUE, &my_variable}, {"verbose", {0, 1, 0, 0}, 'v', NULL, (void *)1, &cfg.verbose}, {"quiet", {0, 1, 0, 0}, 'q', NULL, (void *)-1, &cfg.verbose}, {"hostname", {0, 0, 1, 0}, 'h', "HOSTNAME", "localhost", &cfg.hostname}, {"port", {0, 0, 1, 0}, 'p', "PORT", SERVER_PORT, &cfg.port}, {"source-type", {0, 0, 1, 0}, 't', "SOURCE_TYPE", "file", &cfg.source_type}, {"source-name", {0, 0, 1, 0}, 's', "SOURCE_NAME", NULL, &cfg.source_name}, {"keepalive-int", {0, 0, 1, 1}, 'k', "KEEPALIVE_INTERVAL", (void *)300, &cfg.keepalive}, {"packet-timeout", {0, 0, 1, 1}, 't', "PACKET_TIMEOUT", (void *)DEFAULT_TIMEOUT, &cfg.timeout} }; int sockfd = 0; ssize_t retv = 0; char buf[256]; pk_keepalive_t * pk = (pk_keepalive_t *)buf; pk_advertize_t * ad; pid_t keepalive_pid = 0; struct keepalive_param kp = {&sockfd, &cfg.keepalive}; config(argc, argv, sizeof(vars)/sizeof(struct config_var), vars); ad = (pk_advertize_t *)alloc_packet(PACKET_SIZE_MAX); if ((retv = !ad)) goto exit; printf("Connecting to %s:%s\n", cfg.hostname, cfg.port); if ((retv = connect_socket(cfg.hostname, cfg.port, &sockfd))) { fprintf(stderr, "Connection failed\n"); goto free; } if ((retv = send_handshake(sockfd, cfg.timeout))) { fprintf(stderr, "Bad handshake\n"); goto free; } _fork(&keepalive_pid, &do_keepalive, &kp); if (!strcasecmp("file", cfg.source_type)) { FILE * file = fopen(cfg.source_name, "r"); if ((retv = !file)) { perror("fopen"); goto free; } // states: // 0 - whitespace before name // 1 - name // 2 - whitespace between name and port // 3 - port // 4 - whitespace after port char state = 0, name[220], port[7]; for (int c = 0, i = 0, j = 0; (c = fgetc(file)) > 0;) switch (state) { case 0: // whitespace before name if (c == '#') { state = 4; break; } else if (c <= 0x20 || 0x7F <= c) break; state = 1; i = 0; case 1: // name if ((retv = i >= sizeof(name))) { fprintf(stderr, "Names cannot be more than %lu characters\n", sizeof(name) - 1); goto fclose; } else if (j == 0 && 0x30 <= c && c <= 0x39) { // if the first character is a number, interpret it as a port port[j++] = c; state = 3; break; } if (0x20 < c && c < 0x7F) { name[i++] = c; break; } state = 2; case 2: // whitespace between name and port if (c <= 0x20 || 0x7F <= c) break; state = 3; j = 0; case 3: // port if ((retv = j >= sizeof(port))) { fprintf(stderr, "Port number cannot be greater than 65535\n"); goto fclose; } else if (0x30 <= c && c <= 0x39) { port[j++] = c; state = 3; break; } else if (0x20 < c && c < 0x7F && c != '#') { fprintf(stderr, "Port numbers must be numeric\n"); goto fclose; } state = 4; case 4: // whitespace after port if (c == '\n' || c == '\r') { name[i] = 0; port[j] = 0; if (i == 0 && j == 0) { state = 0; break; } int portnum = atoi(port); if ((retv = portnum > USHRT_MAX)) { fprintf(stderr, "Port number cannot be greater than 65535\n"); goto fclose; } init_pk_advertize(ad, portnum, name); if (!*name) ad->name.data[0] = '+'; retv = pk_send(sockfd, (pk_keepalive_t *)ad, 0); if ((retv = retv < 0)) goto free; state = 0; } break; default: fprintf(stderr, "Internal error\n"); retv = 1; goto fclose; break; } fclose: fclose(file); } else if (!strcasecmp("sqlite", cfg.source_type)) { fprintf(stderr, "Using SQLite as a source is currently unsupported\n"); retv = 1; goto free; } else { fprintf(stderr, "Bad source type %s\n", cfg.source_type); retv = 1; goto free; } free: free_packet((pk_keepalive_t *)ad); while (!retv) { retv = pk_recv(sockfd, buf, cfg.timeout, 0); if (retv <= 0) break; retv = check_version(pk); } //close: if (sockfd) close(sockfd); kill(keepalive_pid, SIGTERM); exit: return (int)retv; }
int Peer::clock() { if (m_state == PEER_STATE_SEND_HANDSHAKE) { if (m_sock == NULL) { try { m_nm->Socket_add(m_addr, shared_from_this(), m_sock); } catch (...) { goto_sleep(); return ERR_INTERNAL; } } if (send_handshake() != ERR_NO_ERROR) goto_sleep(); if (send_bitfield() != ERR_NO_ERROR) goto_sleep(); m_state = PEER_STATE_WAIT_HANDSHAKE; } if (!m_peer_choking) { if (m_state == PEER_STATE_GENERAL_READY ) m_state = PEER_STATE_REQUEST_READY; } else if (m_state == PEER_STATE_GENERAL_READY || m_state == PEER_STATE_REQUEST_READY) { send_interested(); m_state = PEER_STATE_WAIT_UNCHOKE; } //если находимся в нужном состоянии и очередь не пуста if ((m_state == PEER_STATE_GENERAL_READY || m_state == PEER_STATE_REQUEST_READY || m_state == PEER_STATE_WAIT_UNCHOKE) && !m_requests_queue.empty()) { char block[BLOCK_LENGTH]; uint32_t block_length; PIECE_INDEX piece_index; BLOCK_INDEX block_index; std::set<BLOCK_ID>::iterator iter = m_requests_queue.begin(); get_piece_block_from_block_id(*iter, piece_index, block_index); //если удалось прочитать блок и отправить, удаляем индекс блока из очереди if (m_torrent->read_block(piece_index, block_index, block, block_length) == ERR_NO_ERROR && send_piece(piece_index, BLOCK_LENGTH * block_index, block_length, block) == ERR_NO_ERROR) { m_requests_queue.erase(iter); m_torrent->inc_uploaded(block_length); m_uploaded += block_length; //logger::LOGGER() << "rx=%f tx=%f\n", get_rx_speed(), get_tx_speed()); } } if (m_state == PEER_STATE_REQUEST_READY && m_requested_blocks.size() <= PEER_MAX_REQUEST_NUMBER && !m_blocks2request.empty()) { std::set<BLOCK_ID>::iterator iter = m_blocks2request.begin(); PIECE_INDEX piece; BLOCK_INDEX block; uint32_t length; get_piece_block_from_block_id(*iter, piece, block); m_torrent->get_block_length_by_index(piece, block, length); if (send_request(piece, block, length) == ERR_NO_ERROR) { m_requested_blocks.insert(*iter); m_blocks2request.erase(iter); } } return ERR_NO_ERROR; }
void listen_from_peers() { struct peer_state* peer = peers; unsigned int msglen = 0; while(missing_blocks() > 0) { fd_set fdrset_clone; fd_set fdwset_clone; FD_COPY(&fdrset,&fdrset_clone); FD_COPY(&fdwset,&fdwset_clone); int rdy = select(FD_SETSIZE,&fdrset_clone,&fdwset_clone,0, 0); if(rdy <= 0) { continue; } peer = peers; if(active_peers() == 0){ break; } while(peer){ if(FD_ISSET(peer->socket,&fdwset_clone)){ if(peer->connected == 0){ //to send the handshake if it is not connected send_handshake(peer); } else if(peer->send_count > 0) { //to send the have/interested/piece messages to peers send_buffed_msg(peer); } } if(FD_ISSET(peer->socket,&fdrset_clone)) { int newbytes = recv(peer->socket,peer->incoming+peer->count,BUFSIZE-peer->count,0); if(newbytes <= 0){ peer->trying_to_connect = 0; if(newbytes == 0){ piece_status[peer->requested_piece] = PIECE_EMPTY; } disconnet_peer(peer); reconnect_peer(peer); peer = peer->next; continue; } peer->count += newbytes; if(!peer->handshaked){ peer->count -= peer->incoming[0]+49; if(peer->count) { memmove(peer->incoming,peer->incoming + peer->incoming[0]+49,peer->count); } peer->handshaked = 1; } if(memcmp(peer->incoming+peer->incoming[0]+8+20,"-UICCS450-",strlen("-UICCS450-"))==0) { fprintf(stderr,"Caught a CS450 peer, exiting.\n"); disconnet_peer(peer); continue; } while(peer->count >= (ntohl(((int*)peer->incoming)[0])) + 4){ msglen = ntohl(((int*)peer->incoming)[0]); switch(peer->incoming[4]) { // CHOKE case 0: { if(debug) fprintf(stderr,"Choke\n"); peer->choked = 1; piece_status[peer->requested_piece]=PIECE_EMPTY; peer->requested_piece = -1; break; } // UNCHOKE case 1: { if(debug) fprintf(stderr,"Unchoke\n"); peer->choked = 0; peer->requested_piece = next_piece(-1,peer); request_block(peer,peer->requested_piece,0); break; } //Interested case 2: { //dev_notifier(); send_choke_unchoke_msg(peer,0); //ischoked = 0 peer->not_interested = 0; break; } //Not interested case 3: { //dev_notifier(); peer->not_interested = 1; break; } // HAVE -- update the bitfield for this peer case 4: { int piece = ntohl(*((int*)&peer->incoming[5])); int bitfield_byte = piece/8; int bitfield_bit = piece%8; if(debug) fprintf(stderr,"Have %d\n",piece); peer->bitfield[bitfield_byte] |= 1 << (7 - bitfield_bit); piece_occurence_value[piece]++; send_interested(peer); break; } // BITFIELD -- set the bitfield for this peer case 5: //peer->choked = 0; //commenting it according to prof's note in class if(debug) printf("Bitfield of length %d\n",msglen-1); int fieldlen = msglen - 1; if(fieldlen != (file_length/piece_length/8+1)) { disconnet_peer(peer); if(active_peers() == 0){ break; } peer = peer->next; continue; } memcpy(peer->bitfield,peer->incoming+5,fieldlen); read_bit_maps(peer->bitfield,fieldlen); send_interested(peer); break; //Request piece case 6: { if(peer->i_choked_it == 1) break; decode_request_send_piece_to_peer(peer); } break; // PIECE case 7: { //make the tit for tatter peer->send_recv_balancer++; if(peer->i_choked_it && peer->send_recv_balancer == 0){ peer->i_choked_it = 0; send_choke_unchoke_msg(peer,0); //unchoke peer } int piece = ntohl(*((int*)&peer->incoming[5])); int offset = ntohl(*((int*)&peer->incoming[9])); int datalen = msglen - 9; fprintf(stderr,"Writing piece %d, offset %d, ending at %d\n",piece,offset,piece*piece_length+offset+datalen); write_block(peer->incoming+13,piece,offset,datalen,1); draw_state(); offset+=datalen; if(offset==piece_length || (piece*piece_length+offset == file_length) ) { broadcast_have_msg(piece); draw_state(); if(debug) fprintf(stderr,"Reached end of piece %d at offset %d\n",piece,offset); peer->requested_piece=next_piece(piece,peer); offset = 0; } request_block(peer,peer->requested_piece,offset); break; } } drop_message(peer); } } peer = peer->next; } } return; }
// main check password function which do real job of authentication against dovecot static authn_status check_password(request_rec * r, const char *user, const char *password) { authn_dovecot_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_dovecot_module); apr_pool_t *p; // sub pool of r->pool int i, auths, readsocks, result, opts, fdmax, cnt, auth_in_progress, retval; struct sockaddr_un address; struct timeval tv; struct connection_state cs; apr_pool_create(&p, r->pool); // create subpool for local functions, variables... // setting default values for connection state cs.version_ok = 0; cs.mech_available = 0; cs.hshake_done = 0; cs.authenticated = 0; // by default user is NOT authenticated :) cs.handshake_sent = 0; cs.user = NULL; fd_set socks_r; fd_set socks_w; fd_set error_fd; char * const line = apr_pcalloc(p, sizeof(char) * (BUFFMAX + 1)); ap_assert(line != NULL); auths = socket(AF_UNIX, SOCK_STREAM, 0); opts = fcntl(auths, F_GETFL); opts = (opts | O_NONBLOCK); if (fcntl(auths, F_SETFL, opts) < 0) { perror("fcntl(F_SETFL)"); } address.sun_family = AF_UNIX; strncpy(address.sun_path,conf->dovecotauthsocket, strlen(conf->dovecotauthsocket)); result = connect(auths, (struct sockaddr *)&address, sizeof address); if (result) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: could not connect to dovecot socket"); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } cnt = 0; auth_in_progress = 0; // loop trough sockets for writability and for data on socket to read, // wait untill authenticated or if timeoout occurs error out with AUTH_USER_NOT_FOUND and log it while (cnt < conf->dovecotauthtimeout) { fdmax = auths; // simply this is only one really used socket so ... tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&socks_r); FD_SET(auths, &socks_r); FD_ZERO(&error_fd); FD_SET(auths, &error_fd); if (cs.handshake_sent == 0) { FD_ZERO(&socks_w); FD_SET(auths, &socks_w); } else { FD_ZERO(&socks_w); } readsocks = select(fdmax + 1, &socks_r, &socks_w, NULL, &tv); if (readsocks < 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: socket select"); return DECLINED; } if (readsocks == 0) { cnt++; // wait for timeout and count to conf->dovecotauthtimeout // only add to counter in case of timeout! //fprintf(stderr, "%i ", cnt); fflush(stdout); } else { for (i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &socks_w)) { if (cs.handshake_sent == 0) { cs.handshake_sent = send_handshake(p, r, i); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: handshake is sent"); } } if (FD_ISSET(i, &socks_r)) { while ((retval = sock_readline(p, r, i, line)) > 0) { if (!receive_data(p, r, &cs, line)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: problems while receiving data from socket"); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } else { if (cs.hshake_done == 1) { if (!cs.version_ok && !cs.mech_available) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: No authentication possible protocol version wrong or plaintext method not available..."); close(auths); return AUTH_USER_NOT_FOUND; } else { if (auth_in_progress != 1) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: Sending authentication request"); send_auth_request(p, r, i, user, password, #if MODULE_MAGIC_NUMBER_MAJOR >= 20120211 r->connection->client_ip #else r->connection->remote_ip #endif ); auth_in_progress = 1; } } } if (cs.authenticated == 1) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Dovecot Authentication: Authenticated user=\"%s\"", user); close(auths); if (cs.user != NULL) { r->user = cs.user; } return AUTH_GRANTED; } if (cs.authenticated == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: Denied authentication for user=\"%s\"", user); close(auths); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } break; } } if (retval == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: socket reading failed bailing out"); close(auths); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } } } } } } close(auths); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication Timeout"); if (conf->authoritative == 0) { return DECLINED; } else { return AUTH_USER_NOT_FOUND; } }
int leecher_handshake(int sockfd, char *fname, char *id, struct sockaddr_in* sockaddr){ int response; response = get_handshake(sockfd, fname, sockaddr); send_handshake(sockfd, fname, id); return response; }
//perform handshake from the leecher's perspective //Compute the necessary computations, listen for incoming packet, verify it //and then send ours back. int seeder_handshake(int sockfd, char* fname, char *id,struct sockaddr_in sockaddr) { send_handshake(sockfd, fname, id); return get_handshake(sockfd, fname, &sockaddr); }