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