Date: Wed, 3 Oct 2007 21:27:32 GMT From: Fredrik Lindberg <fli@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 127149 for review Message-ID: <200710032127.l93LRWqs097132@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=127149 Change 127149 by fli@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)); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710032127.l93LRWqs097132>