PERFORCE change 127149 for review

Fredrik Lindberg fli at FreeBSD.org
Wed Oct 3 14:27:33 PDT 2007


http://perforce.freebsd.org/chv.cgi?CH=127149

Change 127149 by fli at fli_nexus on 2007/10/03 21:26:56

	- Add functions to get records from the additional section.
	- Fix a problem with name compression/decompression.
	- Add a psuedo header to work with during packet construction.
	- Make encoding/decoding functions handle other classes than IN. 
	- Missing return value checks and other minor fixes.

Affected files ...

.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/stack_packet.c#12 edit

Differences ...

==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/stack_packet.c#12 (text+ko) ====

@@ -48,8 +48,8 @@
 	size_t *, int);
 static int name_decompress(char *, char *, size_t, char *, size_t);
 static inline char * res_decode(char *, uint16_t *, uint16_t, char *, size_t);
-static inline void res_encode(struct hashtbl *, char *, uint16_t, char *,
-    size_t *, int);
+static inline int res_encode(struct hashtbl *, char *, char *, uint16_t,
+    uint16_t, char *, size_t *, int);
 
 static void pkg_free(struct mdns_pkgchain *, struct mdns_packet *);
 static int pkg_write(struct mdns_packet *, struct mdns_bufpool *);
@@ -63,7 +63,8 @@
 enum {
 	SEC_QUESTIONS = p_questions,
 	SEC_ANSWERS = p_answers,
-	SEC_AUTHORITY = p_auths
+	SEC_AUTHORITY = p_auths,
+	SEC_ADDITIONAL = p_addit
 };
 
 /*
@@ -415,20 +416,36 @@
 /*
  * Labelize (and name compress) resource data that needs it
  */
-static inline void
-res_encode(struct hashtbl *ht, char *buf, uint16_t type, char *res,
-    size_t *rlen, int plen)
+static inline int
+res_encode(struct hashtbl *ht, char *buf, char *end, uint16_t class,
+    uint16_t type, char *res, size_t *rlen, int plen)
 {
+	size_t len, sz;
+	int error = 0;
 
+	sz = end - buf;
+	if (class != mdns_c_in) {
+		if (*rlen > sz)
+			return (-1);
+		memcpy(buf, res, *rlen);
+		return (0);
+	}
+
 	switch (type) {
 	case mdns_in_ptr:
 	case mdns_in_cname:
-		name_compress(ht, res, *rlen, buf, rlen, plen);
+		len = end - buf;
+		error = name_compress(ht, res, *rlen, buf, &len, plen);
+		if (error == 0)
+			*rlen = len;
 		break;
 	default:
+		if (*rlen > sz)
+			return (-1);
 		memcpy(buf, res, *rlen);
 		break;
 	}
+	return (error);
 }
 
 /*
@@ -441,6 +458,22 @@
 mdns_pkg_sethdr(struct mdns_pkgchain *pc, uint16_t id, int flags)
 {
 	struct mdns_packet *pkg;
+
+	MDNS_INIT_ASSERT(pc, pc_magic);
+	pkg = pc->pc_pkg;
+
+	if (pkg == NULL)
+		pkg = pkg_alloc(pc);
+	if (pkg == NULL)
+		return (-1);
+	MDNS_INIT_ASSERT(pkg, p_magic);
+
+	pkg->p_head.h_id = id;
+	pkg->p_head.h_flags = flags;
+	pkg->p_len += MDNS_HEADER_LEN;
+
+	return (0);
+#if 0
 	struct mdns_buf *buf;
 	struct mdns_header *h;
 
@@ -468,6 +501,7 @@
 	pkg->p_len += MDNS_HEADER_LEN;
 	MDNS_BUFLEN(buf) += MDNS_HEADER_LEN;
 	return (0);
+#endif
 }
 
 /*
@@ -602,9 +636,8 @@
 	struct mdns_pkg_res *pr;
 	struct mdns_packet *pkg;
 	struct mdns *md;
-	struct mdns_header *h;
 	size_t slen;
-	struct mdns_head head;
+	struct mdns_head *head;
 
 	MDNS_INIT_ASSERT(pc, pc_magic);
 	md = pc->pc_md;
@@ -654,11 +687,11 @@
 				errno = EMSGSIZE;
 				return (-1);
 			}
-			h = (struct mdns_header *)pkg->p_buf(p_hdr);
-			h->h_tc = 1;
-			mdns_pkg_gethdr(pkg, &head);
+
+			head = &pkg->p_head;
 			pkg = pkg_alloc(pc);
-			mdns_pkg_sethdr(pc, head.h_id, head.h_flags);
+			mdns_pkg_sethdr(pc, head->h_id, head->h_flags);
+			head->h_flags |= MDNS_HEAD_TC;
 
 			/*
 			 * Only one resource record is allowed in
@@ -668,7 +701,7 @@
 			if (pr->pr_what && pr->pr_res.rs.r_datalen >
 			    md->md_maxpkgsz) {
 				pkg_alloc(pc);
-				mdns_pkg_sethdr(pc, head.h_id, head.h_flags);
+				mdns_pkg_sethdr(pc, head->h_id, head->h_flags);
 			}
 		}
 	}
@@ -763,16 +796,12 @@
 mdns_pkg_addquestion(struct mdns_pkgchain *pc, struct mdns_qset *qs,
     int flags)
 {
-	struct mdns_header *h;
 	struct mdns_packet *hpkg;
 	int error;
 
 	error = addres(pc, SEC_QUESTIONS, qs, flags, &hpkg);
 	if (error != 0)
 		return (error);
-	assert(hpkg != NULL);
-	h = (struct mdns_header *)hpkg->p_buf(p_hdr);
-	h->h_qcount = htons(ntohs(h->h_qcount) + 1);
 	return (0);
 }
 
@@ -784,16 +813,12 @@
 struct mdns_qset *
 mdns_pkg_delquestion(struct mdns_pkgchain *pc, struct mdns_qset *qs)
 {
-	struct mdns_header *h;
 	struct mdns_packet *hpkg;
 	struct mdns_pkg_res *pr;
 
 	pr = delres(pc, SEC_QUESTIONS, qs, &hpkg);
 	if (pr == NULL)
 		return (NULL);
-	assert(hpkg != NULL);
-	h = (struct mdns_header *)hpkg->p_buf(p_hdr);
-	h->h_qcount = htons(ntohs(h->h_qcount) - 1);
 	return (&pr->pr_res.qs);
 }
 
@@ -810,16 +835,12 @@
 mdns_pkg_addauth(struct mdns_pkgchain *pc, struct mdns_rrset *rs,
     int flags)
 {
-	struct mdns_header *h;
 	struct mdns_packet *hpkg;
 	int error;
 
 	error = addres(pc, SEC_AUTHORITY, rs, flags, &hpkg);
 	if (error != 0)
 		return (error);
-	assert(hpkg != NULL);
-	h = (struct mdns_header *)hpkg->p_buf(p_hdr);
-	h->h_nscount = htons(ntohs(h->h_nscount) + 1);
 	return (0);
 }
 
@@ -831,16 +852,12 @@
 struct mdns_rrset *
 mdns_pkg_delauth(struct mdns_pkgchain *pc, struct mdns_rrset *rs)
 {
-	struct mdns_header *h;
 	struct mdns_packet *hpkg;
 	struct mdns_pkg_res *pr;
 
 	pr = delres(pc, SEC_AUTHORITY, rs, &hpkg);
 	if (pr == NULL)
 		return (NULL);
-	assert(hpkg != NULL);
-	h = (struct mdns_header *)hpkg->p_buf(p_hdr);
-	h->h_nscount = htons(ntohs(h->h_nscount) - 1);
 	return (&pr->pr_res.rs);
 }
 
@@ -857,16 +874,12 @@
 mdns_pkg_addanswer(struct mdns_pkgchain *pc, struct mdns_rrset *rs,
     int flags)
 {
-	struct mdns_header *h;
 	struct mdns_packet *hpkg;
 	int error;
 
 	error = addres(pc, SEC_ANSWERS, rs, flags, &hpkg);
 	if (error != 0)
 		return (error);
-	assert(hpkg != NULL);
-	h = (struct mdns_header *)hpkg->p_buf(p_hdr);
-	h->h_acount = htons(ntohs(h->h_acount) + 1);
 	return (0);
 }
 
@@ -878,16 +891,12 @@
 struct mdns_rrset *
 mdns_pkg_delanswer(struct mdns_pkgchain *pc, struct mdns_rrset *rs)
 {
-	struct mdns_header *h;
 	struct mdns_packet *hpkg;
 	struct mdns_pkg_res *pr;
 
 	pr = delres(pc, SEC_ANSWERS, rs, &hpkg);
 	if (pr == NULL)
 		return (NULL);
-	assert(hpkg != NULL);
-	h = (struct mdns_header *)hpkg->p_buf(p_hdr);
-	h->h_acount = htons(ntohs(h->h_acount) - 1);
 	return (&pr->pr_res.rs);
 }
 
@@ -903,18 +912,20 @@
 	struct mdns_rrset *rs;
 	struct mdns_qset *qs;
 	struct mdns_pkg_res *pr;
-	size_t namlen, namclen;
+	size_t namlen, namclen, reslen;
 	int error, i;
 	struct mdns_qsec qsec;
 	struct mdns_rsec rsec;
 	size_t pkglen;
+	uint16_t *count;
+	char *end;
 	struct hashtbl nc;
 
 	hashtbl_init(&nc, 8, 128, 3);
 	pkglen = MDNS_HEADER_LEN;
 
 	MDNS_INIT_ASSERT(pkg, p_magic);
-	for (i = 1; i < 4; i++) {
+	for (i = 1; i < 5; i++) {
 		if (pkg->p_data[i].buf == NULL) {
 			pkg->p_data[i].buf =
 			    mdns_buf_alloc(bp, &pkg->p_buflist, 0, 0);
@@ -923,18 +934,48 @@
 		}
 		buf = pkg->p_data[i].buf;
 		MDNS_BUFLEN(buf) = 0;
+		end = MDNS_BUF(buf) + MDNS_BUFSZ(buf);
 
+		switch (i) {
+		case p_questions: 	
+			count = &pkg->p_head.h_cquestion;
+			break;
+		case p_answers:
+			count = &pkg->p_head.h_canswer;
+			break;
+		case p_auths:
+			count = &pkg->p_head.h_cauth;
+			break;
+		case p_addit:
+			count = &pkg->p_head.h_caddit;
+			break;
+		default:
+			abort();
+		}
+		*count = 0;
+
 		TAILQ_FOREACH(pr, &pkg->p_data[i].res_head, pr_next) {
 			qs = &pr->pr_res.qs;
 			rs = &pr->pr_res.rs;
 			namlen = strlen(qs->q_name);
 			namclen = MDNS_RECORD_LEN;
+
+			if ((pkglen + namlen + MDNS_RRSET_HLEN) >
+			    MDNS_BUFSZ(buf)) {
+				dprintf(DEBUG_STACK, "Ran out of space in "
+				    "buffer, pkglen=%d, bufsz=%d",
+				    pkglen, MDNS_BUFSZ(buf));
+				goto out;
+			}
+
 			error = name_compress(&nc, qs->q_name, namlen,
 			    MDNS_BUFPOS(buf), &namclen, pkglen);
 			if (error != 0)
-				goto out;
+				continue;
+
 			MDNS_BUFLEN(buf) += namclen;
 			pkglen += namclen;
+
 			if (pr->pr_what) {
 				rsec.rs_class = rs->r_class;
 				if (rs->r_cflush)
@@ -943,18 +984,29 @@
 				rsec.rs_type = htons(rs->r_type);
 				rsec.rs_ttl = htonl(rs->r_ttl);
 
-				namclen = rs->r_datalen;
-				res_encode(&nc,
-				    MDNS_BUFPOS(buf) + MDNS_RRSET_HLEN,
-				    rs->r_type, rs->r_data, &namclen,
-				    pkglen + MDNS_RRSET_HLEN);
+				reslen = rs->r_datalen;
+				error = res_encode(&nc,
+				    MDNS_BUFPOS(buf) + MDNS_RRSET_HLEN, end,
+				    rs->r_class, rs->r_type, rs->r_data,
+				    &reslen, pkglen + MDNS_RRSET_HLEN);
+
+				/*
+				 * Failed to encode resource data, roll back
+				 * name and try next resource.
+				 */
+				if (error != 0) {
+					MDNS_BUFLEN(buf) -= namclen;
+					pkglen -= namclen;
+					hashtbl_flush(&nc);
+					continue;
+				}
 
-				rsec.rs_rdlen = htons(namclen);
+				rsec.rs_rdlen = htons(reslen);
 				memcpy(MDNS_BUFPOS(buf), &rsec,
 				    MDNS_RRSET_HLEN);
 
-				MDNS_BUFLEN(buf) += MDNS_RRSET_HLEN + namclen;
-				pkglen += MDNS_RRSET_HLEN + namclen;
+				MDNS_BUFLEN(buf) += MDNS_RRSET_HLEN + reslen;
+				pkglen += MDNS_RRSET_HLEN + reslen;
 			}
 			else {
 				qsec.qs_class = qs->q_class;
@@ -967,13 +1019,19 @@
 				MDNS_BUFLEN(buf) += MDNS_QSET_HLEN;
 				pkglen += MDNS_QSET_HLEN;
 			}
+			(*count)++;
 		}
 	}
 
+	hashtbl_destroy(&nc);
 	return (0);
-	hashtbl_destroy(&nc);
 out:
+	for (i = 1; i < 5; i++) {
+		buf = pkg->p_data[i].buf;
+		MDNS_BUFLEN(buf) = 0;
+	}
 	hashtbl_destroy(&nc);
+	dprintf(DEBUG_STACK, "Failed to write packet data into buffers");
 	return (-1);
 }
 
@@ -988,20 +1046,53 @@
 {
 	struct mdns_packet *pkg;
 	struct mdns_bufpool *bp;
+	struct mdns_buf *buf;
+	struct mdns_head *head;
+	struct mdns_header *h;
 	int error, retval = -1;
 
 	MDNS_INIT_ASSERT(pc, pc_magic);
 	MDNS_INIT_ASSERT(pc->pc_md, md_magic);
 	bp = pc->pc_md->md_bp;
 
-	dprintf(DEBUG_STACK, "Finalizing packet chain pc=%x", pc);
+	dprintf(DEBUG_STACK, "Finalizing packet chain pc=%x, empty=%d",
+	    pc, TAILQ_EMPTY(&pc->pc_head));
+
 	TAILQ_FOREACH(pkg, &pc->pc_head, p_list) {
+		buf = MDNS_BUFH(&pkg->p_buflist);
+		if (buf == NULL) {
+			buf = mdns_buf_alloc(bp, &pkg->p_buflist, 0, 0);
+			if (buf == NULL)
+				break;
+			bzero(MDNS_BUF(buf), MDNS_HEADER_LEN);
+			pkg->p_bufseg(p_hdr) = buf;
+			pkg->p_buf(p_hdr) = MDNS_BUF(buf);
+		}
+
 		error = pkg_write(pkg, bp);
 		if (error != 0)
-			goto out;
+			continue;
+		head = &pkg->p_head;
+		if (head->h_cquestion == 0 && head->h_canswer == 0 &&
+		    head->h_cauth == 0 && head->h_caddit == 0) {
+			dprintf(DEBUG_STACK, "Ignoring empty packet");
+			continue;
+		}
+
+		h = (struct mdns_header *)MDNS_BUF(buf);
+		h->h_qr = head->h_flags & MDNS_HEAD_QUERY ?
+		    MDNS_HDR_QUERY : MDNS_HDR_RESP;
+		h->h_tc = head->h_flags & MDNS_HEAD_TC ? 1 : 0;
+		h->h_aa = head->h_flags & MDNS_HEAD_AA ? 1 : 0;
+		h->h_id = htons(head->h_id);
+		h->h_qcount = htons(head->h_cquestion);
+		h->h_acount = htons(head->h_canswer);
+		h->h_nscount = htons(head->h_cauth);
+		h->h_rcount = htons(head->h_caddit);
+		MDNS_BUFLEN(buf) += MDNS_HEADER_LEN;
+		retval = 0;
 	}
-	retval = 0;
-out:
+
 	if (retval != 0) {
 		dprintf(DEBUG_STACK, "Packet chain finalization failed");
 	}
@@ -1030,6 +1121,13 @@
 	return (getres(pkg, SEC_AUTHORITY, offset, (void *)rs));
 }
 
+int
+mdns_pkg_getaddit(struct mdns_packet *pkg, int offset, struct mdns_rrset *rs)
+{
+
+	return (getres(pkg, SEC_ADDITIONAL, offset, (void *)rs));
+}
+
 /*
  * Return an entry from a section in a packet
  *   pkg     - Pointer to packet
@@ -1056,10 +1154,9 @@
 	struct mdns_buf *buf, *hbuf;
 	struct mdns_rrset *rs = (struct mdns_rrset *)set;
 	struct mdns_qset *qs = (struct mdns_qset *)set;
-	char *p, ***offsets, **offset, *end;
+	char *p, ***offsets, **offset, *end, *wp;
 	int error, i, j, *last_offset, entries;
 	uint16_t tmp[3], rlen;
-	char *wp;
 
 	MDNS_INIT_ASSERT(pkg, p_magic);
 
@@ -1077,6 +1174,8 @@
 		pkg->p_buf(p_questions) = MDNS_BUF(hbuf) + MDNS_HEADER_LEN;
 		pkg->p_secoff(p_questions) =
 			malloc(sizeof(char *) * ntohs(h->h_qcount));
+		if (pkg->p_secoff(p_questions) == NULL)
+			return (-1);
 		bzero(pkg->p_secoff(p_questions),
 		    sizeof(char *) * ntohs(h->h_qcount));
 	}


More information about the p4-projects mailing list