/* -*-c-*-
*
- * $Id: peer.c,v 1.3 2001/02/04 17:10:58 mdw Exp $
+ * $Id$
*
* Communication with the peer
*
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: peer.c,v $
- * Revision 1.3 2001/02/04 17:10:58 mdw
- * Make file descriptors be nonblocking and close-on-exec.
- *
- * Revision 1.2 2001/02/03 22:40:29 mdw
- * Put timer information into the entropy pool when packets are received
- * and on similar events. Reseed the generator on the interval timer.
- *
- * Revision 1.1 2001/02/03 20:26:37 mdw
- * Initial checkin.
- *
- */
-
/*----- Header files ------------------------------------------------------*/
#include "tripe.h"
sz = sizeof(addr);
n = recvfrom(fd, buf_i, sizeof(buf_i), 0, &a.sa, &sz);
if (n < 0) {
- a_warn("error reading socket: %s", strerror(errno));
+ a_warn("PEER - socket-read-error -- %s", strerror(errno));
return;
}
p->peer.sin.sin_port == a.sin.sin_port)
goto found;
}
- a_warn("packet from unexpected peer: %s:%u",
- inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port));
+ a_warn("PEER - unexpected-source INET %s %u",
+ inet_ntoa(a.sin.sin_addr), (unsigned)ntohs(a.sin.sin_port));
return;
found:
/* --- Pick the packet apart --- */
+ p->st.t_last = time(0);
+ p->st.n_in++;
+ p->st.sz_in += n;
buf_init(&b, buf_i, n);
if ((ch = buf_getbyte(&b)) < 0) {
- a_warn("bad packet from `%s': no type byte", p->name);
+ a_warn("PEER %s bad-packet no-type", p->name);
return;
}
- switch (ch) {
+ switch (ch & MSG_CATMASK) {
case MSG_PACKET:
+ if (ch & MSG_TYPEMASK) {
+ a_warn("PEER %s bad-packet unknown-type 0x%02x", p->name, ch);
+ p->st.n_reject++;
+ return;
+ }
buf_init(&bb, buf_o, sizeof(buf_o));
- if (ks_decrypt(&p->ks, &b, &bb)) {
- a_warn("couldn't decrypt inbound packet");
+ if (ksl_decrypt(&p->ks, MSG_PACKET, &b, &bb)) {
+ p->st.n_reject++;
+ a_warn("PEER %s decrypt-failed", p->name);
return;
}
- if (BOK(&bb))
+ if (BOK(&bb)) {
+ p->st.n_ipin++;
+ p->st.sz_ipin += BSZ(&b);
tun_inject(&p->t, &bb);
- else
- a_warn("packet build failed");
- break;
- case MSG_PRECHALLENGE:
- kx_prechallenge(&p->kx, &b);
- break;
- case MSG_CHALLENGE:
- kx_challenge(&p->kx, &b);
+ } else {
+ p->st.n_reject++;
+ a_warn("PEER %s packet-build-failed", p->name);
+ }
break;
- case MSG_RESPONSE:
- kx_response(&p->kx, &b);
+ case MSG_KEYEXCH:
+ kx_message(&p->kx, ch & MSG_TYPEMASK, &b);
break;
default:
- a_warn("bad packet from `%s': unknown packet type", p->name);
+ p->st.n_reject++;
+ a_warn("PEER %s bad-packet unknown-category 0x%02x", p->name, ch);
break;
}
}
void p_txend(peer *p)
{
if (!BOK(&p->b)) {
- a_warn("packet build failed");
+ a_warn("PEER %s packet-build-failed", p->name);
return;
}
IF_TRACING(T_PEER, trace_block(T_PACKET, "peer: sending packet",
BBASE(&p->b), BLEN(&p->b)); )
if (sendto(sock.fd, BBASE(&p->b), BLEN(&p->b),
0, &p->peer.sa, p->sasz) < 0)
- a_warn("packet send to `%s' failed: %s", p->name, strerror(errno));
+ a_warn("PEER %s socket-write-error -- %s", p->name, strerror(errno));
+ else {
+ p->st.n_out++;
+ p->st.sz_out += BLEN(&p->b);
+ }
}
/* --- @p_tun@ --- *
void p_tun(peer *p, buf *b)
{
buf *bb = p_txstart(p, MSG_PACKET);
+
TIMER;
- if (ks_encrypt(&p->ks, b, bb))
+ if (ksl_encrypt(&p->ks, MSG_PACKET, b, bb))
kx_start(&p->kx);
- if (BCUR(bb) > BBASE(bb))
+ if (BOK(bb) && BLEN(bb)) {
+ p->st.n_ipout++;
+ p->st.sz_ipout += BLEN(bb);
p_txend(p);
+ }
}
/* --- @p_interval@ --- *
pp = p->next;
if (reload)
kx_newkeys(&p->kx);
- ks_prune(&p->ks);
+ ksl_prune(&p->ks);
}
}
+/* --- @p_stats@ --- *
+ *
+ * Arguments: @peer *p@ = pointer to a peer block
+ *
+ * Returns: A pointer to the peer's statistics.
+ */
+
+stats *p_stats(peer *p) { return (&p->st); }
+
/* --- @p_ifname@ --- *
*
* Arguments: @peer *p@ = pointer to a peer block
/* --- @p_init@ --- *
*
- * Arguments: @unsigned port@ = port number to listen to
+ * Arguments: @struct in_addr addr@ = address to bind to
+ * @unsigned port@ = port number to listen to
*
* Returns: ---
*
* Use: Initializes the peer system; creates the socket.
*/
-void p_init(unsigned port)
+void p_init(struct in_addr addr, unsigned port)
{
int fd;
struct sockaddr_in sin;
+ int len = PKBUFSZ;
+
+ /* --- Note on socket buffer sizes --- *
+ *
+ * For some bizarre reason, Linux 2.2 (at least) doubles the socket buffer
+ * sizes I pass to @setsockopt@. I'm not putting special-case code here
+ * for Linux: BSD (at least TCPv2) does what I tell it rather than second-
+ * guessing me.
+ */
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
die(EXIT_FAILURE, "socket creation failed: %s", strerror(errno));
BURN(sin);
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_addr = addr;
sin.sin_port = htons(port);
if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)))
die(EXIT_FAILURE, "bind failed: %s", strerror(errno));
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) ||
+ setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len))) {
+ die(EXIT_FAILURE, "failed to set socket buffer sizes: %s",
+ strerror(errno));
+ }
fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
sel_initfile(&sel, &sock, fd, SEL_READ, p_read, 0);
sel_addfile(&sock);
p->prev = 0;
memcpy(&p->peer.sa, sa, sz);
p->sasz = sz;
+ memset(&p->st, 0, sizeof(stats));
+ p->st.t_start = time(0);
if (kx_init(&p->kx, p, &p->ks))
goto tidy_0;
if (tun_create(&p->t, p))
if (peers)
peers->prev = p;
peers = p;
+ switch (p->peer.sa.sa_family) {
+ case AF_INET:
+ a_notify("ADD %s INET %s %u",
+ name,
+ inet_ntoa(p->peer.sin.sin_addr),
+ (unsigned)ntohs(p->peer.sin.sin_port));
+ break;
+ default:
+ a_notify("ADD %s UNKNOWN", name);
+ break;
+ }
return (p);
tidy_1:
void p_destroy(peer *p)
{
T( trace(T_PEER, "peer: destroying peer `%s'", p->name); )
- ks_free(&p->ks);
+ a_notify("KILL %s", p->name);
+ ksl_free(&p->ks);
kx_free(&p->kx);
tun_destroy(&p->t);
xfree(p->name);