Commit Diff


commit - 2bf43d27c2a9ef1adf1dddf45a3bd685d518b45d
commit + 5c485996696ebb2f12799297a00ef02d89d91246
blob - 4f46a4a6100f51eddfb822e354d336daa0c77cb9
blob + 652cf8c8e71ac26adb15fc524c3eee92bcbbcdaa
--- client.c
+++ client.c
@@ -35,12 +35,18 @@ static struct imsgev	*iev_listener;
 static struct evbuffer	*evb;
 static uint32_t		 peerid;
 
+static int		 handshaked;
+uint32_t		 msize;
+
 static ATTR_DEAD void	client_shutdown(void);
 static void		client_sig_handler(int, short, void *);
 static void		client_dispatch_listener(int, short, void *);
 static void		client_privdrop(const char *, const char *);
 
 static int		client_send_listener(int, const void *, uint16_t);
+
+static void		parse_message(uint8_t *, size_t, struct np_msg_header *,
+			    uint8_t **);
 
 static void		np_error(uint16_t, const char *);
 
@@ -245,8 +251,9 @@ client_send_listener(int type, const void *data, uint1
 	return ret;
 }
 
-static inline void
-parse_message(uint8_t *data, size_t len, struct np_msg_header *hdr, void **cnt)
+static void
+parse_message(uint8_t *data, size_t len, struct np_msg_header *hdr,
+    uint8_t **cnt)
 {
 	if (len < 4)
 		goto err;
@@ -292,6 +299,16 @@ np_header(uint32_t len, uint8_t type, uint16_t tag)
 	evbuffer_add(evb, &len, sizeof(len));
 	evbuffer_add(evb, &type, sizeof(type));
 	evbuffer_add(evb, &tag, sizeof(tag));
+}
+
+static inline void
+np_string(uint16_t len, const char *str)
+{
+	uint16_t l = len;
+
+	len = htole16(len);
+	evbuffer_add(evb, &len, sizeof(len));
+	evbuffer_add(evb, str, l);
 }
 
 static inline void
@@ -306,6 +323,23 @@ do_send(void)
 }
 
 static void
+np_version(uint16_t tag, uint32_t msize, const char *version)
+{
+	uint32_t len = HEADERSIZE;
+	uint16_t l;
+
+	l = strlen(version);
+	len += sizeof(msize) + sizeof(l) + l;
+
+	msize = htole32(msize);
+
+	np_header(len, Rversion, tag);
+	evbuffer_add(evb, &msize, sizeof(msize));
+	np_string(l, version);
+	do_send();
+}
+
+static void
 np_error(uint16_t tag, const char *errstr)
 {
 	uint32_t len = HEADERSIZE;
@@ -315,21 +349,66 @@ np_error(uint16_t tag, const char *errstr)
 	len += sizeof(l) + l;
 
 	np_header(len, Rerror, tag);
-	evbuffer_add(evb, &l, sizeof(l));
-	evbuffer_add(evb, errstr, l);
-
+	np_string(l, errstr);
 	do_send();
 }
 
 static void
 handle_message(struct imsg *imsg, size_t len)
 {
-	struct np_msg_header hdr;
-	void *data;
+	struct np_msg_header	 hdr;
+	uint16_t		 slen;
+	uint8_t			*data;
 
 	parse_message(imsg->data, len, &hdr, &data);
+	len -= HEADERSIZE;
 
-	/* for now, log the request and reply with an error. */
-	log_debug("got request type %s", pp_msg_type(hdr.type));
-	np_error(hdr.tag, "Not supported.");
+	log_debug("got request: len=%d type=%d[%s] tag=%d",
+	    hdr.len, hdr.type, pp_msg_type(hdr.type), hdr.tag);
+
+	if (!handshaked && hdr.type != Tversion)
+		goto err;
+
+	switch (hdr.type) {
+	case Tversion:
+		if (handshaked)
+			goto err;
+
+		/* msize[4] + version[s] */
+		if (len < 6)
+			goto err;
+
+		memcpy(&msize, data, sizeof(msize));
+		data += sizeof(msize);
+		len = le32toh(len);
+
+		memcpy(&slen, data, sizeof(slen));
+		data += sizeof(slen);
+		slen = le16toh(slen);
+
+		if (slen != strlen(VERSION9P) ||
+		    memcpy(data, VERSION9P, strlen(VERSION9P)) != 0 ||
+		    msize == 0) {
+			np_version(hdr.tag, MSIZE9P, "unknown");
+			return;
+		}
+
+		handshaked = 1;
+
+		msize = MIN(msize, MSIZE9P);
+		client_send_listener(IMSG_MSIZE, &msize, sizeof(msize));
+		np_version(hdr.tag, msize, VERSION9P);
+		break;
+
+	default:
+		/* for now, log the request and reply with an error. */
+		np_error(hdr.tag, "Not supported.");
+		break;
+	}
+
+	return;
+
+err:
+	client_send_listener(IMSG_CLOSE, NULL, 0);
+	client_shutdown();
 }
blob - 4f58841a8c8c7dc714b0b7f4ef54034e6fefd90d
blob + 313f07d8e6f7e00f60bd8efec086ac5edae8a8f1
--- kamid.h
+++ kamid.h
@@ -56,6 +56,8 @@ enum imsg_type {
 	IMSG_AUTH_TLS,
 	IMSG_CONN_GONE,
 	IMSG_BUF,
+	IMSG_MSIZE,
+	IMSG_CLOSE,
 };
 
 struct kd_options_conf {
blob - b9cb509cb9873fee593543536b0fc8c8a5b486ae
blob + 46ad95e3716e051f2e3e9c2e1e60b2872bad4f76
--- listener.c
+++ listener.c
@@ -477,6 +477,29 @@ listener_dispatch_client(int fd, short event, void *d)
 				break;
 			}
 			break;
+
+		case IMSG_MSIZE:
+			if (IMSG_DATA_SIZE(imsg) != sizeof(client->msize))
+				fatal("IMSG_MSIZE size mismatch: "
+				    "got %zu want %zu", IMSG_DATA_SIZE(imsg),
+				    sizeof(client->msize));
+
+			memcpy(&client->msize, imsg.data,
+			    sizeof(client->msize));
+
+			if (client->msize == 0)
+				fatal("IMSG_MSIZE got msize = 0");
+
+			break;
+
+		case IMSG_CLOSE:
+			/*
+			 * Both EVBUFFER_READ or EVBUFFER_WRITE should
+			 * be fine.
+			 */
+			client_error(client->bev, EVBUFFER_READ, client);
+			break;
+
 		default:
 			log_debug("%s: unexpected imsg %d", __func__,
 			    imsg.hdr.type);