--- a/libpurple/protocols/gg/lib/dcc7.c Wed Mar 12 22:56:56 2014 +0100 +++ b/libpurple/protocols/gg/lib/dcc7.c Thu Mar 13 00:09:23 2014 +0100 @@ -5,7 +5,7 @@ * Tomasz Chiliński <chilek@chilan.com> * Adam Wysocki <gophi@ekg.chmurka.net> * Bartłomiej Zimoń <uzi18@o2.pl> - * + * * Thanks to Jakub Zawadzki <darkjames@darkjames.ath.cx> * * This program is free software; you can redistribute it and/or modify @@ -167,7 +167,9 @@ } if (dcc->sess->resolver_start(&dcc->fd, &dcc->resolver, GG_RELAY_HOST) == -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() " + "resolving failed (errno=%d, %s)\n", + errno, strerror(errno)); return -1; } @@ -243,7 +245,8 @@ sin.sin_port = htons(port); if (bind(fd, (struct sockaddr*) &sin, sizeof(sin)) == -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to %s:%d\n", inet_ntoa(sin.sin_addr), port); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to" + " bind to %s:%d\n", inet_ntoa(sin.sin_addr), port); goto fail; } @@ -260,7 +263,7 @@ dcc->fd = fd; dcc->local_addr = sin.sin_addr.s_addr; dcc->local_port = ntohs(sin.sin_port); - + dcc->state = GG_STATE_LISTENING; dcc->check = GG_CHECK_READ; dcc->timeout = GG_DCC7_TIMEOUT_FILE_ACK; @@ -292,7 +295,7 @@ if (gg_dcc7_listen(dcc, dcc->sess->client_addr, dcc->sess->client_port) == -1) return -1; - + if (dcc->sess->external_port != 0) external_port = dcc->sess->external_port; else @@ -300,12 +303,14 @@ if (dcc->sess->external_addr != 0) external_addr = dcc->sess->external_addr; - else + else external_addr = dcc->local_addr; addr.s_addr = external_addr; - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() sending IP address %s and port %d\n", inet_ntoa(addr), external_port); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() " + "sending IP address %s and port %d\n", + inet_ntoa(addr), external_port); memset(&pkt, 0, sizeof(pkt)); pkt.uin = gg_fix32(dcc->peer_uin); @@ -372,7 +377,7 @@ errno = EINVAL; return -1; } - + memset(&pkt, 0, sizeof(pkt)); pkt.type = gg_fix32(type); @@ -397,7 +402,9 @@ * * \ingroup dcc7 */ -static struct gg_dcc7 *gg_dcc7_send_file_common(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash, int seek) +static struct gg_dcc7 *gg_dcc7_send_file_common(struct gg_session *sess, + uin_t rcpt, int fd, size_t size, const char *filename1250, + const char *hash, int seek) { struct gg_dcc7 *dcc = NULL; @@ -456,7 +463,8 @@ * * \ingroup dcc7 */ -struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, const char *filename, const char *filename1250, const char *hash) +struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, + const char *filename, const char *filename1250, const char *hash) { struct gg_dcc7 *dcc = NULL; const char *tmp; @@ -464,7 +472,8 @@ struct stat st; int fd = -1; - gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file(%p, %d, \"%s\", %p)\n", sess, rcpt, filename, hash); + gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file(%p, %d," + " \"%s\", %p)\n", sess, rcpt, filename, hash); if (!sess || !rcpt || !filename) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() invalid parameters\n"); @@ -475,8 +484,14 @@ if (!filename1250) filename1250 = filename; - if (stat(filename, &st) == -1) { - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() stat() failed (%s)\n", strerror(errno)); + if ((fd = open(filename, O_RDONLY)) == -1) { + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() open() failed (%s)\n", strerror(errno)); + goto fail; + } + + if (fstat(fd, &st) == -1) { + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() " + "fstat() failed (%s)\n", strerror(errno)); goto fail; } @@ -486,11 +501,6 @@ goto fail; } - if ((fd = open(filename, O_RDONLY)) == -1) { - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() open() failed (%s)\n", strerror(errno)); - goto fail; - } - if (!hash) { if (gg_file_hash_sha1(fd, (uint8_t*) hash_buf) == -1) goto fail; @@ -534,9 +544,12 @@ * * \ingroup dcc7 */ -struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash) +struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, + int fd, size_t size, const char *filename1250, const char *hash) { - gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file_fd(%p, %d, %d, %u, \"%s\", %p)\n", sess, rcpt, fd, size, filename1250, hash); + gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file_fd(%p, " + "%d, %d, %" GG_SIZE_FMT ", \"%s\", %p)\n", + sess, rcpt, fd, size, filename1250, hash); return gg_dcc7_send_file_common(sess, rcpt, fd, size, filename1250, hash, 0); } @@ -629,11 +642,12 @@ gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_id(%p, %p, %p, %d)\n", sess, e, payload, len); for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) { - gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, state %d, type %d\n", tmp, tmp->state, tmp->dcc_type); + gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, " + "state %d, type %d\n", tmp, tmp->state, tmp->dcc_type); if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != (int) gg_fix32(p->type)) continue; - + tmp->cid = p->id; switch (tmp->dcc_type) { @@ -694,9 +708,9 @@ e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; return 0; } - + /* XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT? */ - + dcc->offset = gg_fix32(p->offset); dcc->state = GG_STATE_WAITING_FOR_INFO; @@ -720,13 +734,14 @@ char *tmp; gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_info(%p, %p, %p, %d)\n", sess, e, payload, len); - gg_debug_session(sess, GG_DEBUG_FUNCTION, "// gg_dcc7_handle_info() received address: %s, hash: %s\n", p->info, p->hash); + gg_debug_session(sess, GG_DEBUG_FUNCTION, "// gg_dcc7_handle_info() " + "received address: %s, hash: %s\n", p->info, p->hash); if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown dcc session\n"); return 0; } - + if (dcc->state == GG_STATE_CONNECTED) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() state is already connected\n"); return 0; @@ -750,7 +765,9 @@ } if (dcc->state == GG_STATE_WAITING_FOR_INFO) { - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() waiting for info so send one\n"); + gg_debug_session(sess, GG_DEBUG_MISC, + "// gg_dcc7_handle_info() waiting for info " + "so send one\n"); gg_dcc7_listen_and_send_info(dcc); e->type = GG_EVENT_DCC7_PENDING; e->event.dcc7_pending.dcc7 = dcc; @@ -777,7 +794,10 @@ cid = strtoull(tmp + 2, NULL, 0); # endif - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid)); + gg_debug_session(sess, GG_DEBUG_MISC, + "// gg_dcc7_handle_info() info.str=%s, " + "info.id=%llu, sess.id=%llu\n", tmp + 2, cid, + *((unsigned long long*) &dcc->cid)); cid = gg_fix64(cid); @@ -788,6 +808,8 @@ return 0; } } +#else + (void)tmp; #endif if (gg_dcc7_get_relay_addr(dcc) == -1) { @@ -804,7 +826,8 @@ return 0; default: - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unhandled transfer type (%d)\n", p->type); + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info()" + " unhandled transfer type (%d)\n", p->type); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; return 0; @@ -814,12 +837,12 @@ /* jeśli nadal czekamy na połączenie przychodzące, a druga strona nie * daje rady i oferuje namiary na siebie, bierzemy co dają. */ - if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) { - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n"); - e->type = GG_EVENT_DCC7_ERROR; - e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; - return 0; - } + if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) { + gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n"); + e->type = GG_EVENT_DCC7_ERROR; + e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE; + return 0; + } #endif if (dcc->state == GG_STATE_LISTENING) { @@ -827,7 +850,7 @@ dcc->fd = -1; dcc->reverse = 1; } - + if (dcc->type == GG_SESSION_DCC7_SEND) { e->type = GG_EVENT_DCC7_ACCEPT; e->event.dcc7_accept.dcc7 = dcc; @@ -871,7 +894,7 @@ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() unknown dcc session\n"); return 0; } - + if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) { gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() invalid state\n"); e->type = GG_EVENT_DCC7_ERROR; @@ -911,7 +934,7 @@ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() not enough memory\n"); return -1; } - + memset(dcc, 0, sizeof(struct gg_dcc7)); dcc->type = GG_SESSION_DCC7_GET; dcc->dcc_type = GG_DCC7_TYPE_FILE; @@ -923,7 +946,9 @@ dcc->sess = sess; if (gg_dcc7_session_add(sess, dcc) == -1) { - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unable to add to session\n"); + gg_debug_session(sess, GG_DEBUG_MISC, + "// gg_dcc7_handle_new() unable to " + "add to session\n"); gg_dcc7_free(dcc); return -1; } @@ -943,7 +968,7 @@ gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_packet() not enough memory\n"); return -1; } - + memset(dcc, 0, sizeof(struct gg_dcc7)); dcc->type = GG_SESSION_DCC7_VOICE; @@ -956,7 +981,9 @@ dcc->sess = sess; if (gg_dcc7_session_add(sess, dcc) == -1) { - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unable to add to session\n"); + gg_debug_session(sess, GG_DEBUG_MISC, + "// gg_dcc7_handle_new() unable to add " + "to session\n"); gg_dcc7_free(dcc); return -1; } @@ -967,7 +994,10 @@ break; default: - gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unknown dcc type (%d) from %ld\n", gg_fix32(p->type), gg_fix32(p->uin_from)); + gg_debug_session(sess, GG_DEBUG_MISC, + "// gg_dcc7_handle_new() unknown dcc type (%d) " + "from %u\n", gg_fix32(p->type), + gg_fix32(p->uin_from)); break; } @@ -978,7 +1008,7 @@ /** * \internal Ustawia odpowiednie stany wewnętrzne w zależności od rodzaju * połączenia. - * + * * \param dcc Struktura połączenia * * \return 0 jeśli się powiodło, -1 w przypadku błędu. @@ -1034,7 +1064,10 @@ gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_watch_fd(%p)\n", dcc); - if (!dcc || (dcc->type != GG_SESSION_DCC7_SEND && dcc->type != GG_SESSION_DCC7_GET && dcc->type != GG_SESSION_DCC7_VOICE)) { + if (!dcc || (dcc->type != GG_SESSION_DCC7_SEND && + dcc->type != GG_SESSION_DCC7_GET && + dcc->type != GG_SESSION_DCC7_VOICE)) + { gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid parameters\n"); errno = EINVAL; return NULL; @@ -1053,26 +1086,25 @@ { struct sockaddr_in sin; int fd; -#ifdef FIONBIO - int one = 1; -#endif socklen_t sin_len = sizeof(sin); gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n"); if ((fd = accept(dcc->fd, (struct sockaddr*) &sin, &sin_len)) == -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() accept() failed (%s)\n", strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() accept() failed " + "(%s)\n", strerror(errno)); return e; } - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()" + " connection from %s:%d\n", + inet_ntoa(sin.sin_addr), htons(sin.sin_port)); -#ifdef FIONBIO - if (ioctl(fd, FIONBIO, &one) == -1) { -#else - if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { -#endif - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() can't set nonblocking (%s)\n", strerror(errno)); + if (!gg_fd_set_nonblocking(fd)) { + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() can't set " + "nonblocking (%s)\n", strerror(errno)); close(fd); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; @@ -1108,11 +1140,20 @@ if (dcc->timeout == 0) error = ETIMEDOUT; - if (error || (res = getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &error, &error_size)) == -1 || error != 0) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (%s)\n", (res == -1) ? strerror(errno) : strerror(error)); + if (error || (res = getsockopt(dcc->fd, SOL_SOCKET, + SO_ERROR, &error, &error_size)) == -1 || + error != 0) + { + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() connection " + "failed (%s)\n", (res == -1) ? + strerror(errno) : strerror(error)); if (dcc->relay) { - for (dcc->relay_index++; dcc->relay_index < dcc->relay_count; dcc->relay_index++) { + for (dcc->relay_index++; + dcc->relay_index < dcc->relay_count; + dcc->relay_index++) + { dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr; dcc->remote_port = dcc->relay_list[dcc->relay_index].port; @@ -1121,7 +1162,9 @@ } if (dcc->relay_index >= dcc->relay_count) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available\n"); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() " + "no relay available\n"); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; @@ -1160,7 +1203,10 @@ welcome_ok.id = dcc->cid; if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() recv() " + "failed (%d, %s)\n", res, + strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1178,7 +1224,10 @@ welcome_ok.id = dcc->cid; if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() recv() " + "failed (%d, %s)\n", + res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1216,7 +1265,10 @@ welcome.id = dcc->cid; if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() send() " + "failed (%d, %s)\n", + res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1228,7 +1280,10 @@ welcome.id = dcc->cid; if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() send() " + "failed (%d, %s)\n", res, + strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE; return e; @@ -1253,7 +1308,9 @@ size_t chunk; int res; - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()" + " GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", + dcc->offset, dcc->size); if (dcc->offset >= dcc->size) { gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() offset >= size, finished\n"); @@ -1263,7 +1320,9 @@ } if (dcc->seek && lseek(dcc->file_fd, dcc->offset, SEEK_SET) == (off_t) -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() lseek() failed (%s)\n", strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() lseek() failed " + "(%s)\n", strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_FILE; return e; @@ -1273,14 +1332,18 @@ chunk = sizeof(buf); if ((res = read(dcc->file_fd, buf, chunk)) < 1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (res=%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() read() failed " + "(res=%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_FILE : GG_ERROR_DCC7_EOF; return e; } if ((res = send(dcc->fd, buf, res, 0)) == -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() send() failed (%s)\n", strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() send() failed " + "(%s)\n", strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_NET; return e; @@ -1307,7 +1370,9 @@ char buf[1024]; int res, wres; - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_GETTING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()" + " GG_STATE_GETTING_FILE (offset=%d, size=%d)\n", + dcc->offset, dcc->size); if (dcc->offset >= dcc->size) { gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n"); @@ -1317,7 +1382,10 @@ } if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < 1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() recv() failed " + "(fd=%d, res=%d, %s)\n", dcc->fd, res, + strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF; return e; @@ -1326,7 +1394,10 @@ /* XXX zapisywać do skutku? */ if ((wres = write(dcc->file_fd, buf, res)) < res) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (fd=%d, res=%d, %s)\n", dcc->file_fd, wres, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() write() failed " + "(fd=%d, res=%d, %s)\n", dcc->file_fd, + wres, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_FILE; return e; @@ -1373,15 +1444,20 @@ return e; } - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), GG_RELAY_PORT); + gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()" + " resolved, connecting to %s:%d\n", + inet_ntoa(addr), GG_RELAY_PORT); if ((dcc->fd = gg_connect(&addr, GG_RELAY_PORT, 1)) == -1) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() connection " + "failed (errno=%d, %s), critical\n", + errno, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; } - + dcc->state = GG_STATE_CONNECTING_RELAY; dcc->check = GG_CHECK_WRITE; dcc->timeout = GG_DEFAULT_TIMEOUT; @@ -1399,9 +1475,12 @@ struct gg_dcc7_relay_req pkt; gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n"); - + if (getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) != 0 || res != 0) { - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() connection " + "failed (errno=%d, %s)\n", + res, strerror(res)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; @@ -1414,7 +1493,8 @@ pkt.type = gg_fix16(GG_DCC7_RELAY_TYPE_SERVER); pkt.dunno1 = gg_fix16(GG_DCC7_RELAY_DUNNO1); - gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd() send pkt(0x%.2x)\n", gg_fix32(pkt.magic)); + gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd()" + " send pkt(0x%.2x)\n", gg_fix32(pkt.magic)); gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt)); if ((res = send(dcc->fd, &pkt, sizeof(pkt), 0)) != sizeof(pkt)) { @@ -1436,6 +1516,7 @@ char buf[256]; struct gg_dcc7_relay_reply *pkt; struct gg_dcc7_relay_reply_server srv; + size_t max_relay_count = (sizeof(buf) - sizeof(*pkt)) / sizeof(srv); int res; int i; @@ -1444,7 +1525,9 @@ if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < (int) sizeof(*pkt)) { if (res == 0) errno = ECONNRESET; - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() recv() failed (%d, %s)\n", res, strerror(errno)); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() recv() failed " + "(%d, %s)\n", res, strerror(errno)); e->type = GG_EVENT_DCC7_ERROR; e->event.dcc_error = GG_ERROR_DCC7_RELAY; return e; @@ -1452,7 +1535,12 @@ pkt = (struct gg_dcc7_relay_reply*) buf; - if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY || gg_fix32(pkt->rcount) < 1 || gg_fix32(pkt->rcount > 256) || gg_fix32(pkt->len) < sizeof(*pkt) + gg_fix32(pkt->rcount) * sizeof(srv)) { + if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY || + gg_fix32(pkt->rcount) < 1 || + gg_fix32(pkt->rcount > 256) || + gg_fix32(pkt->len) < sizeof(*pkt) + + gg_fix32(pkt->rcount) * sizeof(srv)) + { gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_wathc_fd() invalid reply\n"); errno = EINVAL; e->type = GG_EVENT_DCC7_ERROR; @@ -1460,13 +1548,27 @@ return e; } - gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_get_relay() read pkt(0x%.2x)\n", gg_fix32(pkt->magic)); + gg_debug_dcc(dcc, GG_DEBUG_DUMP, + "// gg_dcc7_get_relay() read pkt(0x%.2x)\n", + gg_fix32(pkt->magic)); gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, buf, res); free(dcc->relay_list); dcc->relay_index = 0; dcc->relay_count = gg_fix32(pkt->rcount); + + if (dcc->relay_count > 0xffff || + (size_t)dcc->relay_count > max_relay_count) + { + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// gg_dcc7_watch_fd() relay_count out " + "of bounds (%d)\n", dcc->relay_count); + dcc->relay_count = 0; + free(e); + return NULL; + } + dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t)); if (dcc->relay_list == NULL) { @@ -1485,9 +1587,11 @@ dcc->relay_list[i].family = srv.family; addr.s_addr = srv.addr; - gg_debug_dcc(dcc, GG_DEBUG_MISC, "// %s %d %d\n", inet_ntoa(addr), gg_fix16(srv.port), srv.family); + gg_debug_dcc(dcc, GG_DEBUG_MISC, + "// %s %d %d\n", inet_ntoa(addr), + gg_fix16(srv.port), srv.family); } - + dcc->relay = 1; for (; dcc->relay_index < dcc->relay_count; dcc->relay_index++) { @@ -1548,4 +1652,3 @@ free(dcc); } -