switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written)) {
case IO_SUCCESS:
- cli_flags(cptr) &= ~FLAGS_BLOCKED;
+ ClrFlag(cptr, FLAG_BLOCKED);
cli_sendB(cptr) += bytes_written;
cli_sendB(&me) += bytes_written;
* say it was blocked
*/
if (bytes_written < bytes_count)
- cli_flags(cptr) |= FLAGS_BLOCKED;
+ SetFlag(cptr, FLAG_BLOCKED);
break;
case IO_BLOCKED:
- cli_flags(cptr) |= FLAGS_BLOCKED;
+ SetFlag(cptr, FLAG_BLOCKED);
break;
case IO_FAILURE:
cli_error(cptr) = errno;
- cli_flags(cptr) |= FLAGS_DEADSOCKET;
+ SetFlag(cptr, FLAG_DEADSOCKET);
break;
}
return bytes_written;
* Make us timeout after twice the timeout for DNS look ups
*/
cli_lasttime(cptr) = CurrentTime;
- cli_flags(cptr) |= FLAGS_PINGSENT;
+ SetFlag(cptr, FLAG_PINGSENT);
sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s :%s",
cli_name(&me), cli_serv(&me)->timestamp, newts,
socket_del(&(cli_socket(cptr))); /* queue a socket delete */
cli_fd(cptr) = -1;
}
- cli_flags(cptr) |= FLAGS_DEADSOCKET;
+ SetFlag(cptr, FLAG_DEADSOCKET);
MsgQClear(&(cli_sendQ(cptr)));
client_drop_sendq(cli_connect(cptr));
close(fd);
return;
}
+ /*
+ * Disable IP (*not* TCP) options. In particular, this makes it impossible
+ * to use source routing to connect to the server. If we didn't do this
+ * (and if intermediate networks didn't drop source-routed packets), an
+ * attacker could successfully IP spoof us...and even return the anti-spoof
+ * ping, because the options would cause the packet to be routed back to
+ * the spoofer's machine. When we disable the IP options, we delete the
+ * source route, and the normal routing takes over.
+ */
+ os_disable_options(fd);
/*
* Add this local client to the IPcheck registry.
*
* If they're throttled, murder them, but tell them why first.
*/
- if (!IPcheck_local_connect(addr.sin_addr, &next_target) && !listener->server) {
+ if (!IPcheck_local_connect(addr.sin_addr, &next_target) && !listener->server)
+ {
++ServerStats->is_ref;
- write(fd, throttle_message, strlen(throttle_message));
- close(fd);
- return;
+ write(fd, throttle_message, strlen(throttle_message));
+ close(fd);
+ return;
}
new_client = make_client(0, ((listener->server) ?
* Copy ascii address to 'sockhost' just in case. Then we have something
* valid to put into error messages...
*/
+ SetIPChecked(new_client);
ircd_ntoa_r(cli_sock_ip(new_client), (const char*) &addr.sin_addr);
strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
(cli_ip(new_client)).s_addr = addr.sin_addr.s_addr;
DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))) {
switch (os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length)) {
case IO_SUCCESS:
- if (length) {
- cli_lasttime(cptr) = CurrentTime;
+ if (length)
+ {
+ if (!IsServer(cptr))
+ cli_lasttime(cptr) = CurrentTime;
if (cli_lasttime(cptr) > cli_since(cptr))
cli_since(cptr) = cli_lasttime(cptr);
- cli_flags(cptr) &= ~(FLAGS_PINGSENT | FLAGS_NONL);
+ ClrFlag(cptr, FLAG_PINGSENT);
+ ClrFlag(cptr, FLAG_NONL);
}
break;
case IO_BLOCKED:
break;
case IO_FAILURE:
cli_error(cptr) = errno;
- /* cptr->flags |= FLAGS_DEADSOCKET; */
+ /* SetFlag(cpt, FLAG_DEADSOCKET); */
return 0;
}
}
* For server connections, we process as many as we can without
* worrying about the time of day or anything :)
*/
- if (length > 0 && IsServer(cptr)) {
+ if (length > 0 && IsServer(cptr))
return server_dopacket(cptr, readbuf, length);
- }
- else {
+ else if (length > 0 && (IsHandshake(cptr) || IsConnecting(cptr)))
+ return connect_dopacket(cptr, readbuf, length);
+ else
+ {
/*
* Before we even think of parsing what we just read, stick
* it on the end of the receive queue and do it when its
* turn comes around.
*/
- if (length > 0 && 0 == dbuf_put(&(cli_recvQ(cptr)), readbuf, length)) {
+ if (length > 0 && dbuf_put(&(cli_recvQ(cptr)), readbuf, length) == 0)
return exit_client(cptr, cptr, &me, "dbuf_put fail");
- }
- /*
- * XXX - cptr will always be a user or unregistered
- */
- if (IsUser(cptr) &&
- DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))
+ if (DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))
return exit_client(cptr, cptr, &me, "Excess Flood");
while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) &&
(IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10))
{
- /*
- * If it has become registered as a Server
- * then skip the per-message parsing below.
- */
- if (IsServer(cptr)) {
- dolen = dbuf_get(&(cli_recvQ(cptr)), readbuf, sizeof(readbuf));
- return (dolen) ? server_dopacket(cptr, readbuf, dolen) : 1;
- }
dolen = dbuf_getmsg(&(cli_recvQ(cptr)), cli_buffer(cptr), BUFSIZE);
/*
* Devious looking...whats it do ? well..if a client
* deletes the rest of the buffer contents.
* -avalon
*/
- if (0 == dolen) {
+ if (dolen == 0)
+ {
if (DBufLength(&(cli_recvQ(cptr))) < 510)
- cli_flags(cptr) |= FLAGS_NONL;
+ SetFlag(cptr, FLAG_NONL);
else
DBufClear(&(cli_recvQ(cptr)));
}
- else if (CPTR_KILLED == client_dopacket(cptr, dolen))
+ else if (client_dopacket(cptr, dolen) == CPTR_KILLED)
return CPTR_KILLED;
+ /*
+ * If it has become registered as a Server
+ * then skip the per-message parsing below.
+ */
+ if (IsHandshake(cptr) || IsServer(cptr))
+ {
+ while (-1)
+ {
+ dolen = dbuf_get(&(cli_recvQ(cptr)), readbuf, sizeof(readbuf));
+ if (dolen <= 0)
+ return 1;
+ else if (dolen == 0)
+ {
+ if (DBufLength(&(cli_recvQ(cptr))) < 510)
+ SetFlag(cptr, FLAG_NONL);
+ else
+ DBufClear(&(cli_recvQ(cptr)));
+ }
+ else if ((IsServer(cptr) &&
+ server_dopacket(cptr, readbuf, dolen) == CPTR_KILLED) ||
+ (!IsServer(cptr) &&
+ connect_dopacket(cptr, readbuf, dolen) == CPTR_KILLED))
+ return CPTR_KILLED;
+ }
+ }
}
/* If there's still data to process, wait 2 seconds first */
if (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) &&
- !(cli_freeflag(cptr) & FREEFLAG_TIMER)) {
+ !t_onqueue(&(cli_proc(cptr))))
+ {
Debug((DEBUG_LIST, "Adding client process timer for %C", cptr));
cli_freeflag(cptr) |= FREEFLAG_TIMER;
timer_add(&(cli_proc(cptr)), client_timer_callback, cli_connect(cptr),
case ET_EOF: /* end of file on socket */
Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d", cli_fd(cptr),
cli_error(cptr)));
- cli_flags(cptr) |= FLAGS_DEADSOCKET;
+ SetFlag(cptr, FLAG_DEADSOCKET);
if ((IsServer(cptr) || IsHandshake(cptr)) && cli_error(cptr) == 0) {
exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)",
cli_name(cptr), cli_serv(cptr)->last_error_msg);
break;
case ET_WRITE: /* socket is writable */
- cli_flags(cptr) &= ~FLAGS_BLOCKED;
+ ClrFlag(cptr, FLAG_BLOCKED);
if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048)
list_next_channels(cptr, 64);
Debug((DEBUG_SEND, "Sending queued data to %C", cptr));
assert(0 == cptr || con == cli_connect(cptr));
- con_freeflag(con) &= ~FREEFLAG_TIMER; /* timer has expired... */
-
if (ev_type(ev)== ET_DESTROY) {
+ con_freeflag(con) &= ~FREEFLAG_TIMER; /* timer has expired... */
+
if (!con_freeflag(con) && !cptr)
free_connection(con); /* client is being destroyed */
} else {