openslp/extensions.diff

4045 lines
121 KiB
Diff
Raw Blame History

--- ./common/Makefile.am.orig 2003-02-13 05:19:57.000000000 +0000
+++ ./common/Makefile.am 2006-11-16 16:19:30.000000000 +0000
@@ -24,6 +24,7 @@ libcommonlibslp_la_SOURCES = \
slp_parse.c \
slp_pid.c \
slp_dhcp.c \
+ slp_mdns.c \
$(slp_v1message_SRCS) \
$(slp_security_SRCS)
@@ -46,6 +47,7 @@ libcommonslpd_la_SOURCES = \
slp_filter_l.l \
slp_predicate.c \
slp_dhcp.c \
+ slp_mdns.c \
$(slp_v1message_SRCS) \
$(slp_security_SRCS)
@@ -75,6 +77,7 @@ noinst_HEADERS = \
slp_filter.h \
slp_filter_y.h \
slp_predicate.h \
+ slp_mdns.h \
slp_dhcp.h
AM_YFLAGS = -d
--- ./common/slp_compare.c.orig 2002-12-03 21:04:49.000000000 +0000
+++ ./common/slp_compare.c 2006-11-16 16:19:30.000000000 +0000
@@ -146,6 +146,17 @@ int SLPCompareNamingAuth(int srvtypelen,
if(namingauthlen == 0xffff) /* match all naming authorities */
return 0;
+ /* Skip "service:" */
+ if(srvtypelen > 8 && strncasecmp(srvtype,"service:",8) == 0)
+ {
+ srvtypelen -= 8;
+ srvtype += 8;
+ }
+ dot = memchr(srvtype,':',srvtypelen);
+ if (dot)
+ {
+ srvtypelen = dot - srvtype;
+ }
dot = memchr(srvtype,'.',srvtypelen);
if(!namingauthlen) /* IANA naming authority */
--- ./common/slp_mdns.c.orig 2006-11-16 16:19:30.000000000 +0000
+++ ./common/slp_mdns.c 2006-11-16 16:19:30.000000000 +0000
@@ -0,0 +1,573 @@
+#include "slp_mdns.h"
+#include "slp_message.h"
+
+
+#ifdef DEBUG
+
+#include <stdio.h>
+
+unsigned char *SLPMDNSDumpN(unsigned char *bp, unsigned char *start)
+{
+ unsigned char *obp = 0;
+ int x;
+
+ for (;;) {
+ if ((*bp & 0xc0) == 0xc0) {
+ if (!obp)
+ obp = bp + 2;
+ x = (*bp & 0x3f) << 8 | bp[1];
+ printf("%d:", x);
+ bp = start + x;
+ }
+ if (!*bp) {
+ printf("0");
+ return obp ? obp : bp + 1;
+ }
+ printf("%d ", *bp);
+ fwrite(bp + 1, *bp, 1, stdout);
+ printf(" ");
+ bp += *bp + 1;
+ }
+}
+
+unsigned char *SLPMDNSDumpRR(unsigned char *start, unsigned char *bp)
+{
+ int t, l, l2;
+ printf(" ");
+ bp = SLPMDNSDumpN(bp, start);
+ t = AsUINT16(bp);
+ printf(" TYPE=%d CLASS=%d TTL=%d", t, AsUINT16(bp + 2), AsUINT32(bp + 4));
+ l = AsUINT16(bp + 8);
+ bp += 10;
+ if (t == DNS_TYPE_A)
+ printf(" A=%d.%d.%d.%d", bp[0], bp[1], bp[2], bp[3]);
+ else if (t == DNS_TYPE_AAAA)
+ printf(" AAAA=%02x.%02x.%02x.%02x....", bp[0], bp[1], bp[2], bp[3]);
+ else if (t == DNS_TYPE_PTR)
+ {
+ putchar(' ');
+ SLPMDNSDumpN(bp, start);
+ }
+ else if (t == DNS_TYPE_SRV)
+ {
+ printf(" PRIO=%d WEIGHT=%d PORT=%d ", AsUINT16(bp), AsUINT16(bp + 2), AsUINT16(bp + 4));
+ SLPMDNSDumpN(bp + 6, start);
+ }
+ else if (t == DNS_TYPE_TXT)
+ {
+ while (l > 0)
+ {
+ l2 = *bp++;
+ l--;
+ putchar(' ');
+ putchar('"');
+ while (l2-- > 0 && l > 0)
+ {
+ putchar(*bp++);
+ l--;
+ }
+ putchar('"');
+ }
+ }
+ else
+ {
+ while (l > 0)
+ {
+ printf(" %02x", *bp++);
+ l--;
+ }
+ }
+ printf("\n");
+ return bp + l;
+}
+
+void SLPMDNSDumpDNS(SLPBuffer buf, char *head)
+{
+ int qcount, acount, ncount, xcount;
+ unsigned char *start = (unsigned char *)buf->start;
+ unsigned char *bp = start;
+
+ printf("%s DNS buffer\n", head);
+ printf(" ID %04x", AsUINT16(bp));
+ printf(" Flags %04x\n", AsUINT16(bp + 2));
+ qcount = AsUINT16(bp + 4);
+ acount = AsUINT16(bp + 6);
+ ncount = AsUINT16(bp + 8);
+ xcount = AsUINT16(bp + 10);
+ printf(" QCount %d\n", qcount);
+ bp += 12;
+ while (qcount-- > 0) {
+ printf(" ");
+ bp = SLPMDNSDumpN(bp, start);
+ printf(" TYPE=%d CLASS=%d\n", AsUINT16(bp), AsUINT16(bp + 2));
+ bp += 4;
+ }
+ printf(" ACount %d\n", acount);
+ while (acount-- > 0) {
+ bp = SLPMDNSDumpRR(start, bp);
+ }
+ printf(" NCount %d\n", ncount);
+ while (ncount-- > 0) {
+ bp = SLPMDNSDumpRR(start, bp);
+ }
+ printf(" XCount %d\n", xcount);
+ while (xcount-- > 0) {
+ bp = SLPMDNSDumpRR(start, bp);
+ }
+ printf("\n");
+}
+
+void SLPMDNSDumpBuf(unsigned char *buf, int len)
+{
+ int i;
+ while (len > 0)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (i < len)
+ printf(" %02x", buf[i]);
+ else
+ printf(" ");
+ }
+ printf(" ");
+ for (i = 0; i < 16; i++)
+ {
+ if (i < len)
+ putchar(buf[i] >= 32 && buf[i] < 127 ? buf[i] : '.');
+ else
+ break;
+ }
+ putchar('\n');
+ len -= 16;
+ buf += 16;
+ }
+}
+
+#endif
+
+unsigned char *SLPMDNSParseRR(unsigned char *bp, unsigned char *end,
+ int count,
+ unsigned char **dn,
+ unsigned char **dd, int *dc)
+{
+ int c = 0;
+ for (; count > 0; count--)
+ {
+ if (dn && c < SLP_MDNS_MAX_RR)
+ dn[c] = bp;
+ while (bp < end && *bp && (*bp & 0xc0) != 0xc0)
+ bp += *bp + 1;
+ if (bp < end && *bp)
+ bp++;
+ if (bp + 11 > end)
+ return end + 1;
+ if (dd && c < SLP_MDNS_MAX_RR)
+ dd[c++] = bp + 1;
+ bp += 11 + AsUINT16((char *)bp + 9);
+ }
+ if (dc)
+ *dc = c;
+ return bp;
+}
+
+int SLPMDNSCheckN(unsigned char *r,
+ unsigned char *e,
+ unsigned char *a,
+ int ini)
+{
+ int l = 0;
+
+ for (;;)
+ {
+ if (a < r || a >= e)
+ return 1;
+ if ((*a & 0xc0) == 0xc0)
+ {
+ ini = 0;
+ a = r + ((*a & 0x3f) << 8 | a[1]);
+ if (a < r || a >= e)
+ return 1;
+ }
+ if (!*a)
+ return 0;
+ if ((*a & 0xc0) != 0)
+ return 1;
+ l += *a + 1;
+ if (ini && ini < l + 1)
+ return 1;
+ a += *a + 1;
+ if (l > 254)
+ return 1;
+ }
+}
+
+int SLPMDNSCheckRR(unsigned char *r,
+ unsigned char *e,
+ unsigned char **dn,
+ unsigned char **dd, int *dc)
+{
+ int i, j, c, t, l;
+
+ c = *dc;
+ for (i = j = 0; i < c; i++)
+ {
+ if (SLPMDNSCheckN(r, e, dn[i], 0))
+ continue;
+ t = AsUINT16(dd[i]);
+ l = AsUINT16(dd[i] + 8);
+ if (t == DNS_TYPE_PTR)
+ {
+ if (l < 1)
+ continue;
+ if (SLPMDNSCheckN(r, e, dd[i] + 10, l))
+ continue;
+ }
+ else if (t == DNS_TYPE_A)
+ {
+ if (l < 4)
+ continue;
+ }
+ else if (t == DNS_TYPE_AAAA)
+ {
+ if (l < 16)
+ continue;
+ }
+ else if (t == DNS_TYPE_SRV)
+ {
+ if (l < 7)
+ continue;
+ if (SLPMDNSCheckN(r, e, dd[i] + 16, l - 6))
+ continue;
+ }
+ if (j < i)
+ {
+ dn[j] = dn[i];
+ dd[j] = dd[i];
+ }
+ j++;
+ }
+ *dc = j;
+ return i == j ? 0 : 1;
+}
+
+int SLPMDNSCmpN(unsigned char *a, unsigned char *ar,
+ unsigned char *b, unsigned char *br)
+{
+ for (;;)
+ {
+ if ((*a & 0xc0) == 0xc0)
+ a = ar + ((*a & 0x3f) << 8 | a[1]);
+ if ((*b & 0xc0) == 0xc0)
+ b = br + ((*b & 0x3f) << 8 | b[1]);
+ if (*a != *b)
+ return 1;
+ if (*a == 0)
+ return 0;
+ if (memcmp(a + 1, b + 1, *a))
+ return 1;
+ a += *a + 1;
+ b += *b + 1;
+ }
+}
+
+unsigned char *SLPMDNSCompN(unsigned char *bp, unsigned char *end,
+ unsigned char *a, unsigned char *ar,
+ unsigned char **cvec, int *ncvecp,
+ unsigned char *r)
+{
+ int i;
+ unsigned char *first = 0;
+ int ncvec = ncvecp ? *ncvecp : 0;
+
+ for (;;)
+ {
+ if ((*a & 0xc0) == 0xc0)
+ a = ar + ((*a & 0x3f) << 8 | a[1]);
+ if ((*a & 0xc0) == 0xc0)
+ return 0;
+ if (*a)
+ {
+ for (i = 0; i < ncvec; i++)
+ if (!SLPMDNSCmpN(a, ar, cvec[i], r))
+ break;
+ if (i < ncvec)
+ {
+ if (bp + 1 >= end)
+ return 0;
+ *bp++ = (cvec[i] - r) >> 8 | 0xc0;
+ *bp++ = (cvec[i] - r) & 0xff;
+ break;
+ }
+ }
+ if (first == 0 && *a)
+ first = bp;
+ if (bp + *a + 1 >= end)
+ return 0;
+ memcpy(bp, a, *a + 1);
+ bp += *a + 1;
+ if (*a == 0)
+ break;
+ a += *a + 1;
+ }
+ if (first && ncvecp && ncvec < 256)
+ {
+ cvec[ncvec] = first;
+ *ncvecp = ncvec + 1;
+ }
+ return bp;
+}
+
+unsigned char *SLPMDNSNToStr(unsigned char *bp, unsigned char *end,
+ unsigned char *a, unsigned char *ar, int nolastdot)
+{
+ if (!*a && bp < end)
+ *bp++ = '.';
+ for (;;)
+ {
+ if ((*a & 0xc0) == 0xc0)
+ a = ar + ((*a & 0x3f) << 8 | a[1]);
+ if (*a >= 64 || bp + *a >= end)
+ return 0;
+ if (!*a)
+ break;
+ memcpy(bp, a + 1, *a);
+ bp += *a;
+ a += *a + 1;
+ if (!nolastdot || *a)
+ *bp++ = '.';
+ }
+ return bp;
+}
+
+unsigned char *MDNSStrToN(unsigned char *bp, unsigned char *end,
+ const char *str, int len)
+{
+ unsigned char *op;
+
+ for (op = ++bp; ; str++, len--)
+ {
+ if (bp >= end)
+ return 0;
+ if (len == 0 || *str == '.')
+ {
+ if (bp != op)
+ {
+ if (bp - op >= 64)
+ return 0;
+ op[-1] = bp - op;
+ op = ++bp;
+ }
+ if (len == 0)
+ break;
+ continue;
+ }
+ *bp++ = *str;
+ }
+ bp[-1] = 0;
+ return bp;
+}
+
+unsigned char *SLPMDNSCopyN(unsigned char *bp, unsigned char *end, unsigned char *a, unsigned char *ar)
+{
+ for (;;)
+ {
+ if ((*a & 0xc0) == 0xc0)
+ a = ar + ((*a & 0x3f) << 8 | a[1]);
+ if (bp + *a + 1 > end)
+ return 0;
+ memcpy(bp, a, *a + 1);
+ bp += *a + 1;
+ if (!*a)
+ return bp;
+ a += *a + 1;
+ }
+}
+
+unsigned char *SLPMDNSAddRR(unsigned char *bp, unsigned char *start,
+ unsigned char *end,
+ unsigned char *q, unsigned char *qr,
+ int type,
+ int ttl,
+ unsigned char **cvec,
+ int *ncvec,
+ int data1,
+ unsigned char *data2,
+ unsigned char **dp)
+{
+ unsigned char *oldbp;
+
+ bp = SLPMDNSCompN(bp, end, q, qr, cvec, ncvec, start);
+ if (!bp || bp + 10 > end)
+ return 0;
+ ToUINT16(bp, type);
+ ToUINT16(bp + 2, DNS_CLASS_IN);
+ ToUINT32(bp + 4, ttl);
+ bp += 10;
+ oldbp = bp;
+ if (type == DNS_TYPE_PTR)
+ {
+ bp = SLPMDNSCompN(bp, end, data2, qr, cvec, ncvec, start);
+ if (!bp)
+ return 0;
+ }
+ else if (type == DNS_TYPE_A)
+ {
+ if (bp + 4 > end)
+ return 0;
+ memcpy(bp, data2, 4);
+ bp += 4;
+ }
+ else if (type == DNS_TYPE_TXT)
+ {
+ if (bp + data1 > end)
+ return 0;
+ memcpy(bp, data2, data1);
+ bp += data1;
+ }
+ else if (type == DNS_TYPE_SRV)
+ {
+ if (bp + 6 > end)
+ return 0;
+ ToUINT16(bp, 0);
+ ToUINT16(bp + 2, 0);
+ ToUINT16(bp + 4, data1);
+ /* rfc says target is not compressed */
+ bp = SLPMDNSCopyN(bp + 6, end, data2, 0);
+ if (!bp)
+ return 0;
+ }
+ else
+ return 0;
+ ToUINT16(oldbp - 2, bp - oldbp);
+ if (dp)
+ *dp = oldbp - 10;
+ return bp;
+}
+
+int SLPMDNSNToSrvtype(unsigned char *a, unsigned char *ar, char *buf, int len)
+{
+ char *sp;
+ int l, l2;
+
+ if (len < 9)
+ return 0;
+ memcpy(buf, "service", 8);
+ sp = buf + 7;
+ len -= 7;
+ l2 = 1; /* the \0 */
+ for (;;)
+ {
+ if ((*a & 0xc0) == 0xc0)
+ a = ar + ((*a & 0x3f) << 8 | a[1]);
+ l = *a++;
+ if (l == 0)
+ break;
+ if (l == 4 && (!strncasecmp(a, "_tcp", 4) || !strncasecmp(a, "_udp", 4)))
+ break;
+ if (*a == '_' && l > 1)
+ {
+ a++;
+ l--;
+ }
+ if (l2 + l + 1 > len)
+ return 0; /* doesn't fit */
+ memmove(sp + l + 1, sp, l2);
+ l2 += l + 1;
+ *sp++ = ':';
+ for (; l-- > 0; a++)
+ *sp++ = *a != ':' ? *a : '.';
+ sp = buf + 7;
+ }
+ sp += l2 - 1;
+ if (l2 == 1)
+ {
+ *sp++ = ':';
+ *sp = 0;
+ }
+ return sp - buf;
+}
+
+unsigned char *SLPMDNSSrvtypeToN(unsigned char *bp, unsigned char *end, const char *buf, int len)
+{
+ int l, l2;
+ unsigned char *bb;
+ char *p;
+
+ if (len > 8 && !strncasecmp(buf, "service:", 8))
+ {
+ len -= 8;
+ buf += 8;
+ }
+ if (len <= 0)
+ return 0;
+ l2 = 0;
+ for (;;)
+ {
+ p = memchr(buf, ':', len);
+ l = p ? p - buf : len;
+ if (l >= 63 || bp + l2 + l + 2 > end)
+ return 0;
+ if (l2)
+ memmove(bp + l + 2, bp, l2);
+ l2 += l + 2;
+ bb = bp;
+ *bp++ = l + 1;
+ *bp++ = '_';
+ for (; l > 0; l--)
+ {
+ *bp++ = *buf != '.' ? *buf : ':';
+ buf++;
+ len--;
+ }
+ bp = bb;
+ if (!p)
+ break;
+ buf++;
+ len--;
+ }
+ bp += l2;
+ if (bp + 12 > end)
+ return 0;
+ memcpy(bp, "\004_tcp\005local\000", 12);
+ return bp + 12;
+}
+
+char *SLPMDNSFindInTxt(unsigned char *txtbuf, int txtlen, char *name, int *valuelen)
+{
+ int namelen;
+ int l;
+
+ namelen = strlen(name);
+ while (txtlen >= namelen + 1)
+ {
+ l = *txtbuf++;
+ if (l >= namelen && !memcmp(txtbuf, name, namelen))
+ {
+ *valuelen = l - namelen;
+ return txtbuf + namelen;
+ }
+ txtbuf += l;
+ txtlen -= l + 1;
+ }
+ return 0;
+}
+
+int SLPMDNSAddTxt(unsigned char *txtbuf, int buflen, int *txtlenp, const char *name, const char *value, int valuelen)
+{
+ int txtlen = *txtlenp;
+ int namelen;
+ char *tp;
+
+ namelen = strlen(name);
+ if (namelen + valuelen > 255)
+ return 1;
+ if (txtlen + 1 + namelen + valuelen > buflen)
+ return 1;
+ tp = txtbuf + txtlen;
+ *tp++ = namelen + valuelen;
+ memcpy(tp, name, namelen);
+ memcpy(tp + namelen, value, valuelen);
+ *txtlenp = txtlen + 1 + namelen + valuelen;
+ return 0;
+}
+
--- ./common/slp_mdns.h.orig 2006-11-16 16:19:30.000000000 +0000
+++ ./common/slp_mdns.h 2006-11-16 16:19:30.000000000 +0000
@@ -0,0 +1,102 @@
+#ifndef SLP_MDNS_H_INCLUDED
+#define SLP_MDNS_H_INCLUDED
+
+#include "slp_buffer.h"
+
+#define MDNS_RESERVED_PORT 5353
+#define MDNS_MCAST_ADDRESS 0xe00000fb
+
+#define DNS_TYPE_A 1
+#define DNS_TYPE_PTR 12
+#define DNS_TYPE_HINFO 13
+#define DNS_TYPE_TXT 16
+#define DNS_TYPE_AAAA 28
+#define DNS_TYPE_SRV 33
+#define DNS_TYPE_ANY 255
+
+#define DNS_CLASS_IN 1
+#define DNS_CLASS_ANY 255
+
+#define SLP_MDNS_MAX_RR 128
+
+#ifdef DEBUG
+
+extern unsigned char *SLPMDNSDumpN(unsigned char *bp,
+ unsigned char *start);
+extern unsigned char *SLPMDNSDumpRR(unsigned char *start,
+ unsigned char *bp);
+extern void SLPMDNSDumpDNS(SLPBuffer buf,
+ char *head);
+extern void SLPMDNSDumpBuf(unsigned char *buf,
+ int len);
+#endif
+
+extern unsigned char *SLPMDNSParseRR(unsigned char *bp,
+ unsigned char *end,
+ int count,
+ unsigned char **dn,
+ unsigned char **dd,
+ int *dc);
+extern int SLPMDNSCheckN(unsigned char *r,
+ unsigned char *e,
+ unsigned char *a,
+ int ini);
+extern int SLPMDNSCheckRR(unsigned char *r,
+ unsigned char *e,
+ unsigned char **dn,
+ unsigned char **dd, int *dc);
+extern int SLPMDNSCmpN(unsigned char *a,
+ unsigned char *ar,
+ unsigned char *b,
+ unsigned char *br);
+extern unsigned char *SLPMDNSCompN(unsigned char *bp,
+ unsigned char *end,
+ unsigned char *a,
+ unsigned char *ar,
+ unsigned char **cvec,
+ int *ncvecp,
+ unsigned char *r);
+extern unsigned char *SLPMDNSNToStr(unsigned char *bp,
+ unsigned char *end,
+ unsigned char *a,
+ unsigned char *ar,
+ int nolastdot);
+extern unsigned char *MDNSStrToN(unsigned char *bp,
+ unsigned char *end,
+ const char *str,
+ int len);
+extern unsigned char *SLPMDNSCopyN(unsigned char *bp,
+ unsigned char *end,
+ unsigned char *a,
+ unsigned char *ar);
+extern unsigned char *SLPMDNSAddRR(unsigned char *bp,
+ unsigned char *start,
+ unsigned char *end,
+ unsigned char *q, unsigned char *qr,
+ int type,
+ int ttl,
+ unsigned char **cvec,
+ int *ncvec,
+ int data1,
+ unsigned char *data2,
+ unsigned char **dp);
+extern int SLPMDNSNToSrvtype(unsigned char *a,
+ unsigned char *ar,
+ char *buf,
+ int len);
+extern unsigned char *SLPMDNSSrvtypeToN(unsigned char *bp,
+ unsigned char *end,
+ const char *buf,
+ int len);
+extern char *SLPMDNSFindInTxt(unsigned char *txtbuf,
+ int txtlen,
+ char *name,
+ int *valuelen);
+extern int SLPMDNSAddTxt(unsigned char *txtbuf,
+ int buflen,
+ int *txtlenp,
+ const char *name,
+ const char *value,
+ int valuelen);
+
+#endif
--- ./common/slp_message.h.orig 2003-04-04 06:52:07.000000000 +0000
+++ ./common/slp_message.h 2006-11-16 16:19:30.000000000 +0000
@@ -170,6 +170,10 @@ typedef UINT32* PUINT32;
#define SLP_REG_SOURCE_LOCAL 2 /* from localhost or IPC */
#define SLP_REG_SOURCE_STATIC 3 /* from the slp.reg file */
+#define SLP_REG_WATCH_TCP (1<<0)
+#define SLP_REG_WATCH_UDP (1<<1)
+#define SLP_REG_WATCH_CHECKING (1<<8)
+#define SLP_REG_WATCH_DEAD (1<<9)
/*=========================================================================*/
/* SLP Extension IDs */
@@ -274,6 +278,8 @@ typedef struct _SLPSrvReg
SLPAuthBlock* autharray;
/* The following are used for OpenSLP specific extensions */
uint32_t pid;
+ int watchport;
+ int watchflags;
/* The following are not part of the RFC protocol. They are used by */
/* the OpenSLP implementation for convenience */
int source;
--- ./common/slp_net.c.orig 2006-11-16 16:19:17.000000000 +0000
+++ ./common/slp_net.c 2006-11-16 16:19:30.000000000 +0000
@@ -80,7 +80,19 @@ int SLPNetGetThisHostname(char** hostfdn
if(gethostname(host, MAX_HOST_NAME) == 0)
{
- he = gethostbyname(host);
+ if (*host >= '0' && *host <= '9' && inet_aton(host, &ifaddr))
+ {
+ if (numeric_only)
+ {
+ *hostfdn = xstrdup(inet_ntoa(ifaddr));
+ return 0;
+ }
+ he = gethostbyaddr((char *)&ifaddr, sizeof(ifaddr), AF_INET);
+ }
+ else
+ {
+ he = gethostbyname(host);
+ }
if(he)
{
/* if the hostname has a '.' then it is probably a qualified
--- ./common/slp_property.c.orig 2002-12-03 21:04:50.000000000 +0000
+++ ./common/slp_property.c 2006-11-16 16:19:30.000000000 +0000
@@ -219,7 +219,7 @@ int SetDefaultValues()
/*=========================================================================*/
-int SLPPropertyReadFile(const char* conffile)
+int SLPPropertyReadFileFP(FILE *fp)
/* Reads and sets properties from the specified configuration file */
/* */
/* conffile (IN) the path of the config file to read. */
@@ -230,7 +230,6 @@ int SLPPropertyReadFile(const char* conf
{
char* line;
char* alloced;
- FILE* fp;
char* namestart;
char* nameend;
char* valuestart;
@@ -240,6 +239,10 @@ int SLPPropertyReadFile(const char* conf
{
return -1;
}
+ if(!fp)
+ {
+ return 0;
+ }
alloced = xmalloc(4096);
if(alloced == 0)
@@ -249,14 +252,7 @@ int SLPPropertyReadFile(const char* conf
return -1;
}
- fp = fopen(conffile,"r");
- if(!fp)
- {
- goto CLEANUP;
- }
-
- /* Set the property that keeps track of conffile */
- SLPPropertySet("net.slp.OpenSLPConfigFile",conffile);
+ rewind(fp);
while(fgets(alloced,4096,fp))
{
@@ -324,13 +320,6 @@ int SLPPropertyReadFile(const char* conf
}
}
-
- CLEANUP:
- if(fp)
- {
- fclose(fp);
- }
-
if(alloced)
{
xfree(alloced);
@@ -340,6 +329,33 @@ int SLPPropertyReadFile(const char* conf
}
/*=========================================================================*/
+int SLPPropertyReadFile(const char* conffile)
+/* Reads and sets properties from the specified configuration file */
+/* */
+/* conffile (IN) the path of the config file to read. */
+/* */
+/* Returns - zero on success. non-zero on error. Properties will be set*/
+/* to default on error. */
+/*=========================================================================*/
+{
+ FILE* fp;
+ int ret;
+
+ fp = fopen(conffile,"r");
+ if (fp)
+ {
+ /* Set the property that keeps track of conffile */
+ SLPPropertySet("net.slp.OpenSLPConfigFile",conffile);
+ }
+ ret = SLPPropertyReadFileFP(fp);
+ if (fp)
+ {
+ fclose(fp);
+ }
+ return ret;
+}
+
+/*=========================================================================*/
int SLPPropertyAsBoolean(const char* property)
/*=========================================================================*/
{
--- ./common/slp_spi.c.orig 2006-11-16 16:19:17.000000000 +0000
+++ ./common/slp_spi.c 2006-11-16 16:19:30.000000000 +0000
@@ -395,6 +395,8 @@ SLPCryptoDSAKey* SLPSpiGetDSAKey(SLPSpiH
}
tmp->key = SLPSpiReadKeyFile(tmp->keyfilename,keytype);
+ if (!tmp->key)
+ return 0;
}
*key = SLPCryptoDSAKeyDup(tmp->key);
@@ -456,4 +458,15 @@ int SLPSpiCanSign(SLPSpiHandle hspi,
spistr) != 0);
}
-
+void SLPSpiFill(SLPSpiHandle hspi)
+{
+ SLPSpiEntry* entry = (SLPSpiEntry*)hspi->cache.head;
+ while(entry)
+ {
+ if(entry->keytype != SLPSPI_KEY_TYPE_PRIVATE || hspi->cacheprivate)
+ {
+ entry->key = SLPSpiReadKeyFile(entry->keyfilename,entry->keytype);
+ }
+ entry = (SLPSpiEntry*)entry->listitem.next;
+ }
+}
--- ./common/slp_spi.h.orig 2002-03-19 23:52:15.000000000 +0000
+++ ./common/slp_spi.h 2006-11-16 16:19:30.000000000 +0000
@@ -172,7 +172,13 @@ int SLPSpiCanSign(SLPSpiHandle hspi,
/* Returns Non-zero if we sign using the specified SPI */
/*=========================================================================*/
-#endif
+/*=========================================================================*/
+void SLPSpiFill(SLPSpiHandle hspi);
+/* Fill up all entries with private/public keys. */
+/* */
+/* Parameters: hspi (IN) handle obtained from call to SLPSpiOpen() */
+/*=========================================================================*/
+#endif
--- ./common/slp_xcast.c.orig 2003-04-04 06:52:07.000000000 +0000
+++ ./common/slp_xcast.c 2006-11-16 16:19:30.000000000 +0000
@@ -72,6 +72,7 @@
#include "slp_xcast.h"
#include "slp_message.h"
+#include "slp_property.h"
/*========================================================================*/
int SLPBroadcastSend(const SLPIfaceInfo* ifaceinfo,
@@ -172,12 +173,15 @@ int SLPMulticastSend(const SLPIfaceInfo*
int flags = 0;
int xferbytes;
struct in_addr saddr;
+ int optarg;
#if defined(MSG_NOSIGNAL)
flags = MSG_NOSIGNAL;
#endif
+ optarg = atoi(SLPPropertyGet("net.slp.multicastTTL"));
+
for (socks->sock_count = 0;
socks->sock_count < ifaceinfo->iface_count;
socks->sock_count++)
@@ -199,6 +203,14 @@ int SLPMulticastSend(const SLPIfaceInfo*
/* error setting socket option */
return -1;
}
+ if(setsockopt(socks->sock[socks->sock_count],
+ IPPROTO_IP,
+ IP_MULTICAST_TTL,
+ &optarg,
+ sizeof(optarg)))
+ {
+ return -1;
+ }
socks->peeraddr[socks->sock_count].sin_family = AF_INET;
socks->peeraddr[socks->sock_count].sin_port = htons(SLP_RESERVED_PORT);
--- ./libslp/Makefile.am.orig 2001-07-11 21:03:59.000000000 +0000
+++ ./libslp/Makefile.am 2006-11-16 16:19:30.000000000 +0000
@@ -23,6 +23,7 @@ libslp_la_SOURCES = libslp_dereg.c \
libslp_delattrs.c \
libslp_findsrvtypes.c \
libslp_knownda.c \
+ libslp_mdns.c \
libslp.h
libslp_la_LIBADD = ../common/libcommonlibslp.la
libslp_la_LDFLAGS = -version-info 1:0:0
--- ./libslp/libslp_findsrvs.c.orig 2003-04-04 06:52:08.000000000 +0000
+++ ./libslp/libslp_findsrvs.c 2006-11-16 16:29:43.000000000 +0000
@@ -54,7 +54,8 @@ SLPBoolean ColateSLPSrvURLCallback(SLPHa
const char* pcSrvURL,
unsigned short sLifetime,
SLPError errCode,
- void *pvCookie)
+ void *pvCookie,
+ struct sockaddr_in *peerinfo)
/*-------------------------------------------------------------------------*/
{
SLPSrvUrlColatedItem* collateditem;
@@ -107,12 +108,13 @@ SLPBoolean ColateSLPSrvURLCallback(SLPHa
if(collateditem == NULL)
{
collateditem = (SLPSrvUrlColatedItem*) xmalloc(sizeof(SLPSrvUrlColatedItem) + \
- strlen(pcSrvURL) + 1);
+ strlen(pcSrvURL) + 1 + sizeof(*peerinfo));
if(collateditem)
{
memset(collateditem,0,sizeof(SLPSrvUrlColatedItem));
collateditem->srvurl = (char*)(collateditem + 1);
strcpy(collateditem->srvurl,pcSrvURL);
+ memcpy(collateditem->srvurl + strlen(pcSrvURL) + 1, (char *)peerinfo, sizeof(*peerinfo));
collateditem->lifetime = sLifetime;
/* Add the new item to the collated list */
@@ -146,6 +148,38 @@ CLEANUP:
return SLP_FALSE;
}
+char * SLPAPI SLPGetPeer(SLPHandle hSLP, const char *pcURL)
+{
+ PSLPHandleInfo handle;
+ SLPSrvUrlColatedItem* collateditem;
+ struct sockaddr_in peer;
+
+ /*------------------------------*/
+ /* check for invalid parameters */
+ /*------------------------------*/
+ if(hSLP == 0 || *(unsigned int*)hSLP != SLP_HANDLE_SIG || pcURL == 0 || pcURL[0] == 0)
+ {
+ return 0;
+ }
+
+ /*-----------------------------------------*/
+ /* cast the SLPHandle into a SLPHandleInfo */
+ /*-----------------------------------------*/
+ handle = (PSLPHandleInfo)hSLP;
+
+ collateditem = (SLPSrvUrlColatedItem*) handle->collatedsrvurls.head;
+ while(collateditem)
+ {
+ if (strcmp(collateditem->srvurl, pcURL) == 0)
+ {
+ memcpy((char *)&peer, collateditem->srvurl + strlen(collateditem->srvurl) + 1, sizeof(peer));
+ return xstrdup(inet_ntoa(peer.sin_addr));
+ }
+ collateditem = (SLPSrvUrlColatedItem*)collateditem->listitem.next;
+ }
+ return 0;
+}
+
/*-------------------------------------------------------------------------*/
SLPBoolean ProcessSrvRplyCallback(SLPError errorcode,
struct sockaddr_in* peerinfo,
@@ -173,7 +207,8 @@ SLPBoolean ProcessSrvRplyCallback(SLPErr
0,
0,
errorcode,
- handle->params.findsrvs.cookie);
+ handle->params.findsrvs.cookie,
+ peerinfo);
}
/*--------------------*/
@@ -215,7 +250,8 @@ SLPBoolean ProcessSrvRplyCallback(SLPErr
urlentry[i].url,
(unsigned short)urlentry[i].lifetime,
SLP_OK,
- handle->params.findsrvs.cookie);
+ handle->params.findsrvs.cookie,
+ peerinfo);
if(result == SLP_FALSE)
{
break;
@@ -242,7 +278,8 @@ SLPBoolean ProcessSrvRplyCallback(SLPErr
replymsg->body.daadvert.url,
SLP_LIFETIME_MAXIMUM,
SLP_OK,
- handle->params.findsrvs.cookie);
+ handle->params.findsrvs.cookie,
+ peerinfo);
}
else if(replymsg->header.functionid == SLP_FUNCT_SAADVERT)
{
@@ -264,7 +301,8 @@ SLPBoolean ProcessSrvRplyCallback(SLPErr
replymsg->body.saadvert.url,
SLP_LIFETIME_MAXIMUM,
SLP_OK,
- handle->params.findsrvs.cookie);
+ handle->params.findsrvs.cookie,
+ peerinfo);
}
}
--- ./libslp/libslp_mdns.c.orig 2006-11-16 16:19:30.000000000 +0000
+++ ./libslp/libslp_mdns.c 2006-11-16 16:19:30.000000000 +0000
@@ -0,0 +1,915 @@
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <io.h>
+#include <errno.h>
+#define ETIMEDOUT 110
+#define ENOTCONN 107
+#else
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+#include <stdio.h>
+
+#ifndef UNICAST_NOT_SUPPORTED
+#include "../libslp/slp.h"
+#endif
+
+#include "slp_compare.h"
+#include "slp_xcast.h"
+#include "slp_message.h"
+#include "libslp_mdns.h"
+
+
+/*========================================================================*/
+SLPBuffer SLPBufToMDNS(char* buf, int bufsize, int buftype)
+/* Description:
+ * Convert the data part of a SLP request to a MDNS request
+ *========================================================================*/
+{
+ char *srvtype;
+ int srvtypelen;
+ char *scopelist;
+ int scopelistlen;
+ unsigned char *bp, *end;
+ SLPBuffer mdnsbuf;
+ unsigned char txtbuf[512];
+ int txtlen;
+ char *na;
+ int nalen;
+ char *pred;
+ int predlen;
+ char *slpurl;
+ int slpurllen;
+ char *taglist;
+ int taglistlen;
+
+ bp = (unsigned char *)buf;
+ txtlen = 0;
+
+ if (buftype == SLP_FUNCT_SRVTYPERQST)
+ {
+ nalen = AsUINT16(bp);
+ bp += 2;
+ na = bp;
+ if (nalen != 65535)
+ bp += nalen;
+ scopelistlen = AsUINT16(bp);
+ scopelist = bp + 2;
+ if (!SLPContainsStringList(scopelistlen, scopelist, 5, "_mdns"))
+ return 0;
+ bp += 2 + scopelistlen;
+ if (!(mdnsbuf = SLPBufferAlloc(8000)))
+ return 0;
+ bp = mdnsbuf->start;
+ bp[0] = bp[1] = 0; /* ID */
+ bp[2] = 0x01; /* normal query */
+ bp[3] = 0x00;
+ bp[4] = 0x00; /* qcount = 1 */
+ bp[5] = 0x01;
+ bp[6] = bp[7] = 0; /* acount = 0 */
+ bp[8] = bp[9] = 0; /* ncount = 0 */
+ bp[10] = bp[11] = 0; /* xcount = 0 */
+ memcpy(bp + 12, "\011_services\007_dns-sd\004_udp\005local\000", 30);
+ bp += 12 + 30;
+ bp[0] = 0;
+ bp[1] = DNS_TYPE_PTR;
+ bp[2] = 0;
+ bp[3] = DNS_CLASS_IN;
+ mdnsbuf->end = bp + 4;
+ if (nalen != 65535)
+ SLPMDNSAddTxt(txtbuf, sizeof(txtbuf), &txtlen, "namingauth=", na, nalen);
+ }
+ else if (buftype == SLP_FUNCT_SRVRQST)
+ {
+ srvtypelen = AsUINT16(bp);
+ srvtype = bp + 2;
+ bp += 2 + srvtypelen;
+ scopelistlen = AsUINT16(bp);
+ scopelist = bp + 2;
+ bp += 2 + scopelistlen;
+ if (!SLPContainsStringList(scopelistlen, scopelist, 5, "_mdns"))
+ return 0;
+ predlen = AsUINT16(bp);
+ pred = bp + 2;
+ bp += 2 + predlen;
+ if (bp[0] || bp[1]) /* slpspilen */
+ return 0;
+ mdnsbuf = SLPBufferAlloc(8000);
+ if (!mdnsbuf)
+ return 0;
+ bp = mdnsbuf->start;
+ bp[0] = bp[1] = 0; /* ID */
+ bp[2] = 0x01;
+ bp[3] = 0x00;
+ bp[4] = 0x00;
+ bp[5] = 0x01;
+ bp[6] = bp[7] = 0;
+ bp[8] = bp[9] = 0;
+ bp[10] = bp[11] = 0;
+ end = mdnsbuf->start + mdnsbuf->allocated;
+ if (!(bp = SLPMDNSSrvtypeToN(bp + 12, end, srvtype, srvtypelen)) || bp + 4 > end)
+ {
+ SLPBufferFree(mdnsbuf);
+ return 0;
+ }
+ bp[0] = 0;
+ bp[1] = DNS_TYPE_PTR;
+ bp[2] = 0;
+ bp[3] = DNS_CLASS_IN;
+ mdnsbuf->end = bp + 4;
+ SLPMDNSAddTxt(txtbuf, sizeof(txtbuf), &txtlen, "scope=", scopelist, scopelistlen);
+ if (predlen)
+ SLPMDNSAddTxt(txtbuf, sizeof(txtbuf), &txtlen, "predicate=", pred, predlen);
+ }
+ else if (buftype == SLP_FUNCT_ATTRRQST)
+ {
+ slpurllen = AsUINT16(bp);
+ slpurl = bp + 2;
+ bp += 2 + slpurllen;
+ srvtype = slpurl;
+ for (srvtypelen = 0; srvtypelen < slpurllen; srvtypelen++)
+ if (srvtypelen > 2 && slpurl[srvtypelen] == '/' && slpurl[srvtypelen - 1] == '/' && slpurl[srvtypelen - 2] == ':')
+ break;
+ if (srvtypelen != slpurllen)
+ srvtypelen -= 2;
+ else
+ slpurllen = 0;
+ if (srvtypelen <= 0)
+ return 0;
+ scopelistlen = AsUINT16(bp);
+ scopelist = bp + 2;
+ bp += 2 + scopelistlen;
+ if (!SLPContainsStringList(scopelistlen, scopelist, 5, "_mdns"))
+ return 0;
+ taglistlen = AsUINT16(bp);
+ taglist = bp + 2;
+ bp += 2 + taglistlen;
+ if (bp[0] || bp[1]) /* slpspilen */
+ return 0;
+ mdnsbuf = SLPBufferAlloc(8000);
+ if (!mdnsbuf)
+ return 0;
+ bp = mdnsbuf->start;
+ bp[0] = bp[1] = 0; /* ID */
+ bp[2] = 0x01;
+ bp[3] = 0x00;
+ bp[4] = 0x00;
+ bp[5] = 0x01;
+ bp[6] = bp[7] = 0;
+ bp[8] = bp[9] = 0;
+ bp[10] = bp[11] = 0;
+ end = mdnsbuf->start + mdnsbuf->allocated;
+ if (!(bp = SLPMDNSSrvtypeToN(bp + 12, end, srvtype, srvtypelen)) || bp + 4 > end)
+ {
+ SLPBufferFree(mdnsbuf);
+ return 0;
+ }
+ bp[0] = 0;
+ bp[1] = DNS_TYPE_PTR;
+ bp[2] = 0;
+ bp[3] = DNS_CLASS_IN;
+ mdnsbuf->end = bp + 4;
+ if (slpurllen)
+ SLPMDNSAddTxt(txtbuf, sizeof(txtbuf), &txtlen, "slpurl=", slpurl, slpurllen);
+ if (taglistlen)
+ SLPMDNSAddTxt(txtbuf, sizeof(txtbuf), &txtlen, "taglist=", taglist, taglistlen);
+ }
+ else
+ {
+ return 0;
+ }
+ if (txtlen)
+ {
+ /* small hack: we patch in the compression vector afterwards */
+ bp = SLPMDNSAddRR(mdnsbuf->end, mdnsbuf->start, mdnsbuf->start + mdnsbuf->allocated, "\012_slpqueryX\000", 0, DNS_TYPE_TXT, 0, 0, 0, txtlen, txtbuf, 0);
+ if (bp)
+ {
+ /* set compression pointer to query */
+ mdnsbuf->end[0] = 9;
+ mdnsbuf->end[10] = 0xc0;
+ mdnsbuf->end[11] = 12;
+ mdnsbuf->end = bp;
+ mdnsbuf->start[7]++; /* increment acount */
+ }
+ }
+#ifdef DEBUG
+ SLPMDNSDumpDNS(mdnsbuf, "-> srvtype");
+#endif
+ return mdnsbuf;
+}
+
+static int SLPMDNSCmpRRData(unsigned char *a, unsigned char *ra, unsigned char *b, unsigned char *rb)
+{
+ int type = AsUINT16(a);
+ if (memcmp(a, b, 4))
+ return 1;
+ if (type == DNS_TYPE_PTR)
+ return SLPMDNSCmpN(a + 10, ra, b + 10, rb);
+ if (type == DNS_TYPE_SRV)
+ {
+ if (memcmp(a + 10, b + 10, 6))
+ return 1;
+ return SLPMDNSCmpN(a + 16, ra, b + 16, rb);
+ }
+ return memcmp(a + 8, b + 8, 2 + AsUINT16(a + 8));
+}
+
+int SLPMDNSNToAttrs(unsigned char *txtbuf, int txtlen, char *buf, int len)
+{
+ char *bp = buf;
+ int i, l;
+ int comma = 0;
+
+ while (txtlen)
+ {
+ l = *txtbuf++;
+ txtlen--;
+ if (l > txtlen)
+ return 0;
+ for (i = 0; i < l; i++)
+ if (txtbuf[i] == '=')
+ break;
+ if (comma)
+ {
+ if (len == 0)
+ return 0;
+ *bp++ = ',';
+ len--;
+ }
+ comma = 1;
+ if (i == l)
+ {
+ /* keyword */
+ if (l > len)
+ return 0;
+ memcpy(bp, txtbuf, l);
+ bp += l;
+ len -= l;
+ }
+ else
+ {
+ if (l + 2 > len)
+ return 0;
+ /* (keyword=values) */
+ *bp++ = '(';
+ memcpy(bp, txtbuf, l);
+ bp += l;
+ *bp++ = ')';
+ len -= l + 2;
+ }
+ txtbuf += l;
+ txtlen -= l;
+ }
+ return bp - buf;
+}
+
+
+/*========================================================================*/
+int SLPMDNSToBuf(SLPBuffer buf, struct sockaddr *peer, int peerlen, SLPBuffer mdnssendbuf, int buftype, PSLPHandleInfo handle)
+/* Description:
+ * Convert the an MDNS answer to a SLP answer
+ *========================================================================*/
+{
+ int qcount, acount, ncount, xcount;
+ unsigned char *end = buf->end;
+ unsigned char *bp, *obp;
+ unsigned char slpbuf[8000], *slpbufend;
+ unsigned char *an[SLP_MDNS_MAX_RR];
+ unsigned char *ad[SLP_MDNS_MAX_RR];
+ unsigned char *xn[SLP_MDNS_MAX_RR];
+ unsigned char *xd[SLP_MDNS_MAX_RR];
+ int ac, xc, i, j, rac, l, type;
+ int jsrv, ja, jtxt;
+ unsigned char *cvec[256];
+ unsigned char *ran[SLP_MDNS_MAX_RR];
+ unsigned char *rad[SLP_MDNS_MAX_RR];
+ int ncvec;
+ unsigned char *slpurl;
+ unsigned int ttl;
+ unsigned char *name;
+ int namelen;
+ int urllen;
+
+ if (end - buf->start < 12)
+ return 1; /* too small */
+#ifdef DEBUG
+ SLPMDNSDumpDNS(buf, "<-");
+#endif
+ if (buf->start[0] != mdnssendbuf->start[0])
+ return 1; /* XID mismatch */
+ if (buf->start[1] != mdnssendbuf->start[1])
+ return 1; /* XID mismatch */
+ if ((buf->start[2] & 0xf0) != 0x80)
+ return 1; /* no standard response */
+ if ((buf->start[3] & 0x0f) != 0x00)
+ return 1; /* DNS error */
+ qcount = AsUINT16(buf->start + 4);
+ if (qcount > 1)
+ return 1; /* we didn't query this */
+
+ slpbuf[0] = 2;
+ if (buftype == SLP_FUNCT_SRVTYPERQST)
+ slpbuf[1] = SLP_FUNCT_SRVTYPERPLY;
+ else if (buftype == SLP_FUNCT_SRVRQST)
+ slpbuf[1] = SLP_FUNCT_SRVRPLY;
+ else if (buftype == SLP_FUNCT_ATTRRQST)
+ slpbuf[1] = SLP_FUNCT_ATTRRPLY;
+ else
+ return 1; /* internal error */
+ slpbuf[2] = slpbuf[3] = slpbuf[4] = 0; /* length */
+ slpbuf[5] = slpbuf[6] = 0; /* flags */
+ slpbuf[7] = slpbuf[8] = slpbuf[9] = 0; /* ext off */
+ slpbuf[10] = mdnssendbuf->start[0]; /* xid */
+ slpbuf[11] = mdnssendbuf->start[1]; /* xid */
+ slpbuf[12] = slpbuf[13] = 0; /* ltaglen */
+ slpbuf[14] = slpbuf[15] = 0; /* error code */
+ slpbuf[16] = slpbuf[17] = 0; /* url count */
+ slpurl = slpbuf + 18;
+
+ acount = AsUINT16(buf->start + 6);
+ ncount = AsUINT16(buf->start + 8);
+ xcount = AsUINT16(buf->start + 10);
+
+ /* set up compression vector from old query */
+ cvec[0] = bp = mdnssendbuf->start + 12;
+ ncvec = 1;
+ while (bp < end && *bp)
+ bp += *bp + 1;
+ bp += 1 + 4;
+ bp = SLPMDNSParseRR(bp, mdnssendbuf->end, AsUINT16(mdnssendbuf->start + 6), ran, rad, &rac);
+ for (i = 0; i < rac; i++)
+ {
+ if ((ran[i][0] & 0xc0) == 0xc0 && ncvec < 256)
+ cvec[ncvec++] = ran[i];
+ if (AsUINT16(rad[i]) == DNS_TYPE_PTR)
+ {
+ if ((rad[i][10] & 0xc0) == 0xc0 && ncvec < 256)
+ cvec[ncvec++] = rad[i] + 10;
+ }
+ }
+
+ bp = buf->start + 12;
+ /* skip query section */
+ if (qcount)
+ {
+ while (bp < end && *bp && (*bp & 0xc0) != 0xc0)
+ bp += *bp + 1;
+ if (bp < end && *bp)
+ bp++;
+ bp += 5;
+ }
+ bp = SLPMDNSParseRR(bp, end, acount, an, ad, &ac);
+ if (bp > end)
+ return 1;
+ bp = SLPMDNSParseRR(bp, end, ncount, 0, 0, 0);
+ bp = SLPMDNSParseRR(bp, end, xcount, xn, xd, &xc);
+
+ /* now that we know the end of the packet validate rrs */
+ SLPMDNSCheckRR(buf->start, bp > end ? end : bp, an, ad, &ac);
+ SLPMDNSCheckRR(buf->start, bp > end ? end : bp, xn, xd, &xc);
+ /* printf("checked rrs: ac=%d, xc=%d\n", ac, xc); */
+
+ /* add answer rrs to our query if not already there */
+ for (i = 0; i < ac; i++)
+ {
+ /* is this an answer we are looking for? */
+ if (SLPMDNSCmpN(an[i], buf->start,
+ mdnssendbuf->start + 12, mdnssendbuf->start))
+ continue;
+ type = AsUINT16(ad[i]);
+ /* skip everything but PTR RR, CLASS INs */
+ if (type != DNS_TYPE_PTR)
+ continue;
+ if (AsUINT16(ad[i] + 2) != DNS_CLASS_IN)
+ continue;
+
+ for (j = 0; j < rac; j++)
+ if (!SLPMDNSCmpRRData(ad[i], buf->start, rad[j], mdnssendbuf->start))
+ break;
+ if (j < rac)
+ continue;
+ /* new rr, add it to query */
+ if (rac < SLP_MDNS_MAX_RR)
+ {
+ bp = mdnssendbuf->end;
+ ran[rac] = bp;
+ bp = SLPMDNSAddRR(bp, mdnssendbuf->start, mdnssendbuf->start + mdnssendbuf->allocated, an[i], buf->start, type, AsUINT32(ad[i] + 4), cvec, &ncvec, 0, ad[i] + 10, rad + rac);
+ if (bp)
+ {
+ mdnssendbuf->end = bp;
+ j = AsUINT16(mdnssendbuf->start + 6);
+ ToUINT16(mdnssendbuf->start + 6, j + 1);
+ rac++;
+ }
+ }
+#ifdef DEBUG
+ SLPMDNSDumpDNS(mdnssendbuf, "updated sendbuf");
+#endif
+
+ slpbufend = slpbuf + sizeof(slpbuf);
+ if (buftype == SLP_FUNCT_SRVTYPERQST)
+ {
+ int comma = slpbuf[16] || slpbuf[17] ? 1 : 0;
+ l = SLPMDNSNToSrvtype(ad[i] + 10, buf->start, slpurl + comma, slpbufend - (slpurl + comma));
+ if (!l)
+ continue;
+ if (comma)
+ *slpurl++ = ',';
+ slpurl += l;
+ ToUINT16(slpbuf + 16, slpurl - (slpbuf + 18));
+ continue;
+ }
+ if (buftype == SLP_FUNCT_ATTRRQST)
+ {
+ unsigned char *txtbuf;
+ int txtlen;
+
+ int comma = slpbuf[16] || slpbuf[17] ? 1 : 0;
+ /* find TXT record in additional section */
+ for (jtxt = 0; jtxt < xcount; jtxt++)
+ if (AsUINT16(xd[jtxt]) == DNS_TYPE_TXT
+ && !SLPMDNSCmpN(ad[i] + 10, buf->start, xn[jtxt], buf->start))
+ break;
+ if (jtxt == xcount)
+ continue; /* oops, no TXT */
+ txtbuf = xd[jtxt] + 10;
+ txtlen = AsUINT16(xd[jtxt] + 8);
+ /* skip internal slpurl attribute */
+ if (txtlen > 7 && *txtbuf > 7 && *txtbuf + 1 <= txtlen && !strncasecmp(txtbuf + 1, "slpurl=", 7)) {
+ txtlen -= *txtbuf + 1;
+ txtbuf += *txtbuf + 1;
+ }
+ /* extra +1 for # of AttrAuths added later */
+ l = SLPMDNSNToAttrs(txtbuf, txtlen, slpurl + comma, slpbufend - (slpurl + comma + 1));
+ if (!l)
+ continue;
+ if (comma)
+ *slpurl++ = ',';
+ slpurl += l;
+ ToUINT16(slpbuf + 16, slpurl - (slpbuf + 18));
+ continue;
+ }
+
+ /* now create a nice url */
+ /* find SRV record in the additional section */
+ for (jsrv = 0; jsrv < xcount; jsrv++)
+ if (AsUINT16(xd[jsrv]) == DNS_TYPE_SRV
+ && !SLPMDNSCmpN(ad[i] + 10, buf->start, xn[jsrv], buf->start))
+ break;
+ if (jsrv == xcount)
+ continue; /* oops, server didn't send SRV RR */
+ for (ja = 0; ja < xcount; ja++)
+ if (AsUINT16(xd[ja]) == DNS_TYPE_A
+ && !SLPMDNSCmpN(xd[jsrv] + 10 + 6, buf->start, xn[ja], buf->start))
+ break;
+ if (ja == xcount)
+ ja = -1;
+ for (jtxt = 0; jtxt < xcount; jtxt++)
+ if (AsUINT16(xd[jtxt]) == DNS_TYPE_TXT
+ && !SLPMDNSCmpN(ad[i] + 10, buf->start, xn[jtxt], buf->start))
+ break;
+ if (jtxt == xcount)
+ jtxt = -1;
+
+ /* calculate slp TTL */
+ ttl = AsUINT32(xd[jsrv] + 4);
+ if (ttl > 65535)
+ ttl = 65535;
+
+ /* check if we hava an "slpurl" attribute in the TXT entry */
+ if (jtxt >= 0)
+ {
+ char *txt;
+ l = 0;
+ txt = SLPMDNSFindInTxt(xd[jtxt] + 10, AsUINT16(xd[jtxt] + 8), "slpurl=", &l);
+ if (txt && l)
+ {
+ /* found it, great! add the slpurl */
+ if (slpurl + 6 + l >= slpbufend)
+ continue;
+ *slpurl = 0; /* reserved */
+ ToUINT16(slpurl + 1, ttl);
+ ToUINT16(slpurl + 3, l);
+ memcpy(slpurl + 5, txt, l);
+ slpurl[5 + l] = 0; /* url auths */
+ slpurl += 6 + l;
+ if (++slpbuf[17] == 0)
+ slpbuf[16]++;
+ continue;
+ }
+ }
+
+ bp = mdnssendbuf->start + 12; /* equal to an[i], not compr. */
+ l = *bp++;
+ if (*bp == '_')
+ {
+ l--;
+ bp++;
+ }
+ if (l == 0 || l >= 64 || slpurl + 16 + l >= slpbufend)
+ continue;
+ memcpy(slpurl, "\0\0\0\0\0service:", 13);
+ ToUINT16(slpurl + 1, ttl);
+ memcpy(slpurl + 13, bp, l);
+ bp = slpurl + 13;
+ /* convert : to . */
+ for (; *bp && l-- > 0; bp++)
+ if (*bp == ':')
+ *bp = '.';
+ *bp++ = ':';
+ *bp++ = '/';
+ *bp++ = '/';
+ obp = bp;
+ bp = SLPMDNSNToStr(bp, slpbufend - 1 - 8, xd[jsrv] + 10 + 6, buf->start, 1);
+ if (bp == 0)
+ continue;
+ if (ja >= 0 && (xd[ja][10] != 169 || xd[ja][11] != 254) && bp - obp > 6 && !strncmp(bp - 6, ".local", 6))
+ {
+ /* got .local address but ip isn't local. Lookup. */
+ struct sockaddr_in sai;
+ sai.sin_family = AF_INET;
+ memcpy(&sai.sin_addr.s_addr, xd[ja] + 10, 4);
+ if (getnameinfo((struct sockaddr *)&sai, sizeof(sai),
+ obp, slpbufend - 1 - 8 - obp,
+ (char *)0, 0, NI_NAMEREQD) == 0
+ && obp + strlen(obp) < slpbufend - 1 - 9)
+ {
+ bp = obp + strlen(obp);
+ }
+ else
+ {
+ /* recreate old content */
+ bp = SLPMDNSNToStr(obp, slpbufend - 1 - 8, xd[jsrv] + 10 + 6, buf->start, 1);
+ }
+ }
+ sprintf(bp, ":%u", AsUINT16(xd[jsrv] + 14));
+ bp += strlen(bp);
+ urllen = bp - (slpurl + 5);
+ ToUINT16(slpurl + 3, urllen);
+ *bp++ = 0; /* 0 url blocks */
+
+ /* add extra name info */
+ name = ad[i] + 10;
+ if ((*name & 0xc0) == 0xc0)
+ name = buf->start + ((*name & 0x3f) << 8 | name[1]);
+ namelen = *name++;
+ if (namelen && urllen && buftype == SLP_FUNCT_SRVRQST)
+ {
+ SLPSrvUrlColatedItem *collateditem;
+ collateditem = (SLPSrvUrlColatedItem*) xmalloc(sizeof(SLPSrvUrlColatedItem) + 3 + urllen + namelen);
+ if (collateditem)
+ {
+ memset(collateditem,0,sizeof(SLPSrvUrlColatedItem));
+ collateditem->srvurl = (char*)(collateditem + 1);
+ collateditem->srvurl[0] = 0;
+ strcpy(collateditem->srvurl + 1, slpurl + 5);
+ memcpy(collateditem->srvurl + 1 + urllen + 1, name, namelen);
+ collateditem->srvurl[2 + urllen + namelen] = 0;
+ SLPListLinkTail(&(handle->collatedsrvurls), (SLPListItem*)collateditem);
+ }
+ }
+
+ /* sucessfully added url */
+ slpurl = bp;
+ if (++slpbuf[17] == 0)
+ slpbuf[16]++;
+ }
+ if ((!slpbuf[16] && !slpbuf[17]) || slpurl - slpbuf > buf->allocated)
+ return 1;
+ if (buftype == SLP_FUNCT_ATTRRQST)
+ {
+ /* we already know there is room for this byte */
+ *slpurl++ = 0;
+ }
+ ToUINT24(slpbuf + 2, slpurl - slpbuf);
+ memcpy(buf->start, slpbuf, slpurl - slpbuf);
+#ifdef DEBUG
+ printf("SLP buffer\n");
+ SLPMDNSDumpBuf(slpbuf, slpurl - slpbuf);
+#endif
+ buf->end = buf->start + (slpurl - slpbuf);
+ buf->curpos = buf->start;
+ return 0;
+}
+
+const char *SLPAPI SLPGetMDNSName(SLPHandle hSLP, const char *pcURL)
+{
+
+ PSLPHandleInfo handle;
+ SLPSrvUrlColatedItem* collateditem;
+
+ /*------------------------------*/
+ /* check for invalid parameters */
+ /*------------------------------*/
+ if(hSLP == 0 || *(unsigned int*)hSLP != SLP_HANDLE_SIG || pcURL == 0)
+ {
+ return 0;
+ }
+
+ /*-----------------------------------------*/
+ /* cast the SLPHandle into a SLPHandleInfo */
+ /*-----------------------------------------*/
+ handle = (PSLPHandleInfo)hSLP;
+
+ collateditem = (SLPSrvUrlColatedItem*) handle->collatedsrvurls.head;
+ while(collateditem)
+ {
+ if (collateditem->srvurl[0] == 0
+ && strcmp(collateditem->srvurl + 1,pcURL) == 0)
+ return collateditem->srvurl + strlen(collateditem->srvurl + 1) + 2;
+ collateditem = (SLPSrvUrlColatedItem*)collateditem->listitem.next;
+ }
+ return 0;
+}
+
+
+/*========================================================================*/
+int SLPMDNSMulticastSend(const SLPIfaceInfo* ifaceinfo,
+ SLPBuffer msg,
+ SLPXcastSockets* socks)
+/* Description:
+ * Multicast a message.
+ *
+ * Parameters:
+ * ifaceinfo (IN) Pointer to the SLPIfaceInfo structure that contains
+ * information about the interfaces to send on
+ * msg (IN) Buffer to send
+ *
+ * socks (OUT) Sockets used to multicast. May be used to recv()
+ * responses. MUST be close by caller using
+ * SLPXcastSocketsClose()
+ *
+ * Returns:
+ * Zero on sucess. Non-zero with errno set on error
+ *========================================================================*/
+{
+ int flags = 0;
+ int on = 1;
+ int xferbytes;
+ struct in_addr saddr;
+
+#if defined(MSG_NOSIGNAL)
+ flags = MSG_NOSIGNAL;
+#endif
+
+ for (socks->sock_count = 0;
+ socks->sock_count < ifaceinfo->iface_count;
+ socks->sock_count++)
+ {
+ socks->sock[socks->sock_count] = socket(AF_INET, SOCK_DGRAM, 0);
+ if (socks->sock[socks->sock_count] < 0)
+ {
+ /* error creating socket */
+ return -1;
+ }
+ if (setsockopt(socks->sock[socks->sock_count],
+ SOL_IP,
+ IP_RECVTTL,
+ &on,
+ sizeof(on))) {
+ /* error setting socket option */
+ return -1;
+ }
+
+ saddr.s_addr = ifaceinfo->iface_addr[socks->sock_count].sin_addr.s_addr;
+ if( setsockopt(socks->sock[socks->sock_count],
+ IPPROTO_IP,
+ IP_MULTICAST_IF,
+ (char*)&saddr,
+ sizeof(struct in_addr)))
+ {
+ /* error setting socket option */
+ return -1;
+ }
+
+ socks->peeraddr[socks->sock_count].sin_family = AF_INET;
+ socks->peeraddr[socks->sock_count].sin_port = htons(MDNS_RESERVED_PORT);
+ socks->peeraddr[socks->sock_count].sin_addr.s_addr = htonl(MDNS_MCAST_ADDRESS);
+
+ xferbytes = sendto(socks->sock[socks->sock_count],
+ msg->start,
+ msg->end - msg->start,
+ flags,
+ (struct sockaddr *) &(socks->peeraddr[socks->sock_count]),
+ sizeof(struct sockaddr_in));
+ if (xferbytes <= 0)
+ {
+ /* error sending */
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/*=========================================================================*/
+int SLPMDNSXcastRecvMessage(const SLPXcastSockets* sockets,
+ const SLPXcastSockets* mdnssockets,
+ SLPBuffer *buf,
+ struct sockaddr_in* peeraddr,
+ struct timeval* timeout,
+ SLPBuffer mdnssendbuf, int buftype,
+ PSLPHandleInfo handle)
+/* Description:
+ * Receives datagram messages from one of the sockets in the specified <20>
+ * SLPXcastsSockets structure
+ *
+ * Parameters:
+ * sockets (IN) Pointer to the SOPXcastSockets structure that describes
+ * which sockets to read slp messages from.
+ * sockets (IN) Pointer to the SOPXcastSockets structure that describes
+ * which sockets to read mdns messages from.
+ * buf (OUT) Pointer to SLPBuffer that will contain the message upon
+ * successful return.
+ * peeraddr (OUT) Pointer to struc sockaddr_in that will contain the
+ * address of the peer that sent the received message.
+ * timeout (IN/OUT) pointer to the struct timeval that indicates how much
+ * time to wait for a message to arrive
+ * mdnssendbuf (IN/OUT) Pointer to SLPBuffer that contains the MDNS message.
+ * We will add our received RRs here (known answer
+ * suppression)
+ *
+ * Returns:
+ * Zero on success, non-zero with errno set on failure.
+ *========================================================================*/
+{
+ fd_set readfds;
+ int highfd;
+ int i;
+ int readable;
+ size_t bytesread;
+ int recvloop;
+ int peeraddrlen = sizeof(struct sockaddr_in);
+ char peek[16];
+ int result = 0;
+ struct msghdr mhdr;
+ struct iovec iov;
+ unsigned char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *cmsg;
+ int ttl;
+
+ /* recv loop */
+ recvloop = 1;
+ while(recvloop)
+ {
+ /* Set the readfds */
+ FD_ZERO(&readfds);
+ highfd = 0;
+ for (i=0; i<sockets->sock_count; i++)
+ {
+ FD_SET(sockets->sock[i],&readfds);
+ if(sockets->sock[i] > highfd)
+ highfd = sockets->sock[i];
+ }
+ for (i=0; i<mdnssockets->sock_count; i++)
+ {
+ FD_SET(mdnssockets->sock[i],&readfds);
+ if(mdnssockets->sock[i] > highfd)
+ highfd = mdnssockets->sock[i];
+ }
+
+ /* Select */
+ readable = select(highfd + 1,&readfds,NULL,NULL,timeout);
+ if(readable > 0)
+ {
+ /* Read the datagram */
+ for (i=0; i<sockets->sock_count; i++)
+ {
+ if(FD_ISSET(sockets->sock[i],&readfds))
+ {
+ /* Peek at the first 16 bytes of the header */
+ bytesread = recvfrom(sockets->sock[i],
+ peek,
+ 16,
+ MSG_PEEK,
+ (struct sockaddr *)peeraddr,
+ &peeraddrlen);
+ if(bytesread == 16
+#ifdef _WIN32
+ /* Win32 returns WSAEMSGSIZE if the message is larger than
+ * the requested size, even with MSG_PEEK. But if this is the
+ * error code we can be sure that the message is at least 16
+ * bytes */
+ || (bytesread == (size_t)-1 && WSAGetLastError() == WSAEMSGSIZE)
+#endif
+ )
+ {
+ if(AsUINT24(peek + 2) <= SLP_MAX_DATAGRAM_SIZE)
+ {
+ *buf = SLPBufferRealloc(*buf, AsUINT24(peek + 2));
+ bytesread = recv(sockets->sock[i],
+ (*buf)->curpos,
+ (*buf)->end - (*buf)->curpos,
+ 0);
+ if(bytesread != AsUINT24(peek + 2))
+ {
+ /* This should never happen but we'll be paranoid*/
+ (*buf)->end = (*buf)->curpos + bytesread;
+ }
+
+ /* Message read. We're done! */
+ result = 0;
+ recvloop = 0;
+ break;
+ }
+ else
+ {
+ /* we got a bad message, or one that is too big! */
+#ifndef UNICAST_NOT_SUPPORTED
+ /* Reading SLP_MAX_DATAGRAM_SIZE bytes on the socket */
+ *buf = SLPBufferRealloc(*buf, SLP_MAX_DATAGRAM_SIZE);
+ bytesread = recv(sockets->sock[i],
+ (*buf)->curpos,
+ (*buf)->end - (*buf)->curpos,
+ 0);
+ if(bytesread != SLP_MAX_DATAGRAM_SIZE)
+ {
+ /* This should never happen but we'll be paranoid*/
+ (*buf)->end = (*buf)->curpos + bytesread;
+ }
+ result = SLP_RETRY_UNICAST;
+ recvloop = 0;
+ return result;
+#endif
+ }
+ }
+ else
+ {
+ /* Not even 16 bytes available */
+ }
+ }
+ }
+ for (i=0; i<mdnssockets->sock_count; i++)
+ {
+ if(!FD_ISSET(mdnssockets->sock[i],&readfds))
+ continue;
+ *buf = SLPBufferRealloc(*buf, 8000);
+ (*buf)->curpos = (*buf)->start;
+#if 1
+ iov.iov_base = (*buf)->curpos;
+ iov.iov_len = (*buf)->end - (*buf)->curpos;
+ mhdr.msg_name = (struct sockaddr *)peeraddr;
+ mhdr.msg_namelen = peeraddrlen;
+ mhdr.msg_iov = &iov;
+ mhdr.msg_iovlen = 1;
+ mhdr.msg_control = cmsgbuf;
+ mhdr.msg_controllen = sizeof(cmsgbuf);
+ mhdr.msg_flags = 0;
+ bytesread = recvmsg(mdnssockets->sock[i], &mhdr, 0);
+ if (bytesread < 12)
+ continue;
+ cmsg = CMSG_FIRSTHDR(&mhdr);
+ for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; CMSG_NXTHDR(&mhdr, cmsg))
+ if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL)
+ break;
+ if (!cmsg)
+ continue;
+ ttl = *(int *)CMSG_DATA(cmsg);
+ if (ttl != 255)
+ {
+ continue;
+ }
+#else
+ bytesread = recvfrom(mdnssockets->sock[i],
+ (*buf)->curpos,
+ (*buf)->end - (*buf)->curpos,
+ 0,
+ (struct sockaddr *)peeraddr,
+ &peeraddrlen);
+ if (bytesread < 12)
+ continue;
+#endif
+ (*buf)->end = (*buf)->start + bytesread;
+ if (SLPMDNSToBuf(*buf, (struct sockaddr *)peeraddr, peeraddrlen, mdnssendbuf, buftype, handle) == 0)
+ {
+ result = 0;
+ recvloop = 0;
+ break;
+ }
+ }
+ }
+ else if(readable == 0)
+ {
+ result = -1;
+ errno = ETIMEDOUT;
+ recvloop = 0;
+ }
+ else
+ {
+ result = -1;
+ recvloop = 0;
+ }
+ }
+
+ return result;
+}
+
--- ./libslp/libslp_mdns.h.orig 2006-11-16 16:19:30.000000000 +0000
+++ ./libslp/libslp_mdns.h 2006-11-16 16:19:30.000000000 +0000
@@ -0,0 +1,14 @@
+#include "slp_mdns.h"
+#include "libslp.h"
+
+extern SLPBuffer SLPBufToMDNS(char* buf, int bufsize, int buftype);
+extern int SLPMDNSToBuf(SLPBuffer buf, struct sockaddr *peer,
+ int peerlen, SLPBuffer mdnssendbuf, int buftype, PSLPHandleInfo handle);
+extern int SLPMDNSMulticastSend(const SLPIfaceInfo* ifaceinfo,
+ SLPBuffer msg, SLPXcastSockets* socks);
+extern int SLPMDNSXcastRecvMessage(const SLPXcastSockets* sockets,
+ const SLPXcastSockets* mdnssockets,
+ SLPBuffer *buf,
+ struct sockaddr_in* peeraddr,
+ struct timeval* timeout,
+ SLPBuffer mdnssendbuf, int buftype, PSLPHandleInfo handle);
--- ./libslp/libslp_network.c.orig 2003-08-20 05:25:58.000000000 +0000
+++ ./libslp/libslp_network.c 2006-11-16 16:19:30.000000000 +0000
@@ -49,6 +49,7 @@
#include "slp.h"
#include "libslp.h"
+#include "libslp_mdns.h"
/*=========================================================================*/
@@ -660,6 +661,15 @@ SLPError NetworkMcastRqstRply(const char
SLPIfaceInfo ifaceinfo;
SLPXcastSockets xcastsocks;
+ int usemdns = 1;
+ int useslp = 1;
+ SLPBuffer mdnssendbuf = 0;
+ SLPXcastSockets mdnsxcastsocks;
+
+ /* initialize sock_count so that CLEANUP won't get hurt */
+ xcastsocks.sock_count = 0;
+ mdnsxcastsocks.sock_count = 0;
+
#ifdef DEBUG
/* This function only supports multicast or broadcast of the following
* messages
@@ -726,6 +736,7 @@ SLPError NetworkMcastRqstRply(const char
/* SLP_FUNCT_DASRVRQST is a fake function. We really want to */
/* send a SRVRQST */
buftype = SLP_FUNCT_SRVRQST;
+ usemdns = 0;
}
/*---------------------------------------------------------------------*/
@@ -744,6 +755,13 @@ SLPError NetworkMcastRqstRply(const char
*prlist = 0;
prlistlen = 0;
+ if (usemdns)
+ {
+ mdnssendbuf = SLPBufToMDNS(buf, bufsize, buftype);
+ if (!mdnssendbuf)
+ usemdns = 0;
+ }
+
/*--------------------------*/
/* Main retransmission loop */
/*--------------------------*/
@@ -831,14 +849,23 @@ SLPError NetworkMcastRqstRply(const char
/*----------------------*/
/* send the send buffer */
/*----------------------*/
- if(usebroadcast)
- {
- result = SLPBroadcastSend(&ifaceinfo,sendbuf,&xcastsocks);
- }
- else
- {
- result = SLPMulticastSend(&ifaceinfo,sendbuf,&xcastsocks);
- }
+ result = 0;
+ if (useslp)
+ {
+ if(usebroadcast)
+ {
+ result = SLPBroadcastSend(&ifaceinfo,sendbuf,&xcastsocks);
+ }
+ else
+ {
+ result = SLPMulticastSend(&ifaceinfo,sendbuf,&xcastsocks);
+ }
+ }
+ if (result == 0 && usemdns)
+ {
+ ToUINT16(mdnssendbuf->start,xid);
+ result = SLPMDNSMulticastSend(&ifaceinfo,mdnssendbuf,&mdnsxcastsocks);
+ }
if(result != 0)
{
/* we could not send the message for some reason */
@@ -851,20 +878,19 @@ SLPError NetworkMcastRqstRply(const char
/*----------------*/
while(1)
{
- #ifndef UNICAST_NOT_SUPPORTED
- int retval = 0;
- if((retval = SLPXcastRecvMessage(&xcastsocks,
- &recvbuf,
- &peeraddr,
- &timeout)) != 0)
- #else
-
- if(SLPXcastRecvMessage(&xcastsocks,
- &recvbuf,
- &peeraddr,
- &timeout) != 0)
- #endif
-
+ int retval;
+ if (usemdns)
+ retval = SLPMDNSXcastRecvMessage(&xcastsocks,
+ &mdnsxcastsocks,
+ &recvbuf,
+ &peeraddr,
+ &timeout, mdnssendbuf, buftype, handle);
+ else
+ retval = SLPXcastRecvMessage(&xcastsocks,
+ &recvbuf,
+ &peeraddr,
+ &timeout);
+ if (retval != 0)
{
/* An error occured while receiving the message */
/* probably a just time out error. break for re-send. */
@@ -972,13 +998,16 @@ SLPError NetworkMcastRqstRply(const char
goto CLEANUP;
}
- /* add the peer to the previous responder list */
- if(prlistlen != 0)
- {
- strcat(prlist,",");
- }
- strcat(prlist,inet_ntoa(peeraddr.sin_addr));
- prlistlen = strlen(prlist);
+ if (prlistlen + 14 < mtu)
+ {
+ /* add the peer to the previous responder list */
+ if(prlistlen != 0)
+ {
+ strcat(prlist,",");
+ }
+ strcat(prlist,inet_ntoa(peeraddr.sin_addr));
+ prlistlen = strlen(prlist);
+ }
}
}
@@ -1016,8 +1045,11 @@ SLPError NetworkMcastRqstRply(const char
/*----------------*/
if(prlist) xfree(prlist);
SLPBufferFree(sendbuf);
+ SLPBufferFree(mdnssendbuf);
SLPBufferFree(recvbuf);
SLPXcastSocketsClose(&xcastsocks);
+ if (usemdns)
+ SLPXcastSocketsClose(&mdnsxcastsocks);
return result;
}
@@ -1190,6 +1222,7 @@ SLPError NetworkUcastRqstRply(PSLPHandle
/* send the send buffer */
/*----------------------*/
+ peeraddr = handle->unicastaddr;
handle->unicastsock = SLPNetworkConnectStream(&(handle->unicastaddr), &timeout);
if ( handle->unicastsock >= 0 ) {
retval1 = SLPNetworkSendMessage(handle->unicastsock, SOCK_STREAM, sendbuf, &(handle->unicastaddr), &timeout);
--- ./libslp/slp.h.orig 2003-04-21 11:26:54.000000000 +0000
+++ ./libslp/slp.h 2006-11-16 16:42:16.000000000 +0000
@@ -981,6 +981,41 @@ SLPEXP SLPError SLPAPI SLPParseAttrs(con
/* was not found otherwise SLP_OK */
/*=========================================================================*/
+
+/*=========================================================================*/
+SLPEXP const char* SLPAPI SLPGetMDNSName(SLPHandle hSLP,
+ const char *pcURL);
+/* */
+/* Used to get the MDNS name corresponding to a service URL. This function */
+/* may only be called from a SLPSrvURLCallback. */
+/* */
+/* hSLP The language specific SLPHandle on which to search for */
+/* the MDNS name. */
+/* */
+/* pcURL (IN) The service URL. */
+/* */
+/* Returns: Returns NULL if no name is available for the URL, otherwise */
+/* the name. Note that the memory belongs to libslp and must not */
+/* be freed! */
+/*=========================================================================*/
+
+
+/*=========================================================================*/
+SLPEXP char * SLPAPI SLPGetPeer(SLPHandle hSLP,
+ const char *pcURL);
+/* */
+/* Used to get the peer info corresponding to a service URL. This function */
+/* may only be called from a SLPSrvURLCallback. */
+/* The memory should be freed by calling SLPFree(). */
+/* */
+/* hSLP The language specific SLPHandle on which to search for */
+/* the MDNS name. */
+/* */
+/* pcURL (IN) The service URL. */
+/* */
+/* Returns: the ip address if the peer, NULL if not available */
+/*=========================================================================*/
+
#if(defined __cplusplus)
}
#endif
--- ./libslpattr/libslpattr.c.orig 2002-11-23 03:44:53.000000000 +0000
+++ ./libslpattr/libslpattr.c 2006-11-16 16:19:30.000000000 +0000
@@ -360,6 +360,11 @@ int find_value_list_end(char const *valu
(*cur)++;
}
+ if (type_guess == TYPE_UNKNOWN)
+ {
+ return 0; /* empty */
+ }
+
*type = type_guess;
return 1;
}
--- ./slpd/Makefile.am.orig 2002-03-19 23:52:15.000000000 +0000
+++ ./slpd/Makefile.am 2006-11-16 16:19:30.000000000 +0000
@@ -38,6 +38,7 @@ slpd_regfile.c \
slpd_knownda.c \
slpd_incoming.c \
slpd_outgoing.c \
+slpd_mdns.c \
slpd.h \
slpd_knownda.h \
slpd_process.h \
@@ -49,6 +50,7 @@ slpd_database.h \
slpd_outgoing.h \
slpd_regfile.h \
slpd_incoming.h \
+slpd_mdns.h \
slpd_socket.h
slpd_LDADD = ../common/libcommonslpd.la \
--- ./slpd/slpd_database.c.orig 2003-03-19 05:03:21.000000000 +0000
+++ ./slpd/slpd_database.c 2006-11-16 16:19:30.000000000 +0000
@@ -69,6 +69,13 @@
#include "slp_xmalloc.h"
#include "slp_pid.h"
+extern char *reg_file_dir;
+FILE *regfileFP;
+
+/*=========================================================================*/
+/* standard header files */
+/*=========================================================================*/
+#include <dirent.h>
/*=========================================================================*/
SLPDDatabase G_SlpdDatabase;
@@ -414,6 +421,8 @@ int SLPDDatabaseSrvRqstStart(SLPMessage
/* entry reg is the SrvReg message from the database */
entryreg = &(entry->msg->body.srvreg);
+ if ((entryreg->watchflags & SLP_REG_WATCH_DEAD) != 0)
+ continue;
/* check the service type */
if ( SLPCompareSrvType(srvrqst->srvtypelen,
@@ -548,6 +557,8 @@ int SLPDDatabaseSrvTypeRqstStart(SLPMess
/* entry reg is the SrvReg message from the database */
entryreg = &(entry->msg->body.srvreg);
+ if ((entryreg->watchflags & SLP_REG_WATCH_DEAD) != 0)
+ continue;
if ( SLPCompareNamingAuth(entryreg->srvtypelen,
entryreg->srvtype,
@@ -658,6 +669,8 @@ int SLPDDatabaseAttrRqstStart(SLPMessage
/* entry reg is the SrvReg message from the database */
entryreg = &(entry->msg->body.srvreg);
+ if ((entryreg->watchflags & SLP_REG_WATCH_DEAD) != 0)
+ continue;
if ( SLPCompareString(attrrqst->urllen,
@@ -775,18 +788,19 @@ SLPMessage SLPDDatabaseEnum(void* eh, SL
/*=========================================================================*/
{
SLPDatabaseEntry* entry;
- entry = SLPDatabaseEnum((SLPDatabaseHandle) eh);
- if ( entry )
+ SLPSrvReg* entryreg;
+
+ while ((entry = SLPDatabaseEnum((SLPDatabaseHandle) eh)) != 0)
{
+ entryreg = &(entry->msg->body.srvreg);
+ if ((entryreg->watchflags & SLP_REG_WATCH_DEAD) != 0)
+ continue;
*msg = entry->msg;
*buf = entry->buf;
+ return *msg;
}
- else
- {
- *msg = 0;
- *buf = 0;
- }
-
+ *msg = 0;
+ *buf = 0;
return *msg;
}
@@ -840,12 +854,141 @@ int SLPDDatabaseInit(const char* regfile
SLPDatabaseInit(&G_SlpdDatabase.database);
/* Call the reinit function */
- return SLPDDatabaseReInit(regfile);
+ if (regfileFP)
+ {
+ fclose(regfileFP);
+ }
+ regfileFP = fopen(regfile, "r");
+ return SLPDDatabaseReInit();
}
+/*=========================================================================*/
+static void SLPDDatabaseWatcher_fd(int fd, int flag, unsigned char *porthash)
+{
+ SLPDatabaseHandle dh;
+ SLPDatabaseEntry* entry;
+ SLPSrvReg* srvreg;
+ char buf[4096], *p[6];
+ int l, o, i, j, k, c, n, port;
+
+ if (fd < 0)
+ return;
+ lseek(fd, (off_t)0, SEEK_SET);
+ o = 0;
+ while ((l = read(fd, buf + o, sizeof(buf) - o)) > 0) {
+ l += o;
+ n = 0;
+ for (;;) {
+ for (i = n; i < l; i++)
+ if (buf[i] == '\n')
+ break;
+ if (i == l) {
+ if (l > n)
+ memmove(buf, buf + n, l - n);
+ o = l > n ? l - n : 0;
+ break;
+ }
+ k = 0;
+ for (j = n; j < i; j++) {
+ c = buf[j];
+ if (!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'F') && !(c >= 'a' && c <= 'f'))
+ buf[j] = 0;
+ else if ((j == n || buf[j - 1] == 0) && k < 6)
+ p[k++] = buf + j;
+ }
+ n = i + 1;
+ if (k < 6 || strlen(p[1]) < 8)
+ continue;
+ if (strlen(p[1]) == 8 && strtol(p[1], (char **)0, 16) == htonl(0x7f000001))
+ continue;
+ if ((flag & SLP_REG_WATCH_TCP) != 0 && strtol(p[5], (char **)0, 16) != 10)
+ continue;
+ port = strtol(p[2], (char **)0, 16);
+ if (!(porthash[(port / 8) & 255] & (1 << (port & 7))))
+ continue;
+ dh = SLPDatabaseOpen(&G_SlpdDatabase.database);
+ while ((entry = SLPDatabaseEnum(dh)) != 0) {
+ srvreg = &(entry->msg->body.srvreg);
+ if (!(srvreg->watchflags & flag))
+ continue;
+ if (port == srvreg->watchport)
+ srvreg->watchflags &= ~SLP_REG_WATCH_CHECKING;
+ }
+ SLPDatabaseClose(dh);
+ }
+ }
+}
/*=========================================================================*/
-int SLPDDatabaseReInit(const char* regfile)
+void SLPDDatabaseWatcher(void)
+{
+ static int initialized = 0;
+ static int proctcp, procudp, proctcp6, procudp6;
+ unsigned char porthash[256];
+ int flags, port;
+ SLPDatabaseHandle dh;
+ SLPDatabaseEntry* entry;
+ SLPSrvReg* srvreg;
+
+ if (!initialized) {
+ proctcp = open("/proc/net/tcp_listen", O_RDONLY);
+ if (proctcp == -1)
+ proctcp = open("/proc/net/tcp", O_RDONLY);
+ procudp = open("/proc/net/udp", O_RDONLY);
+ proctcp6 = open("/proc/net/tcp6_listen", O_RDONLY);
+ if (proctcp6 == -1)
+ proctcp6 = open("/proc/net/tcp6", O_RDONLY);
+ procudp6 = open("/proc/net/udp6", O_RDONLY);
+ initialized = 1;
+ }
+ flags = 0;
+ memset(porthash,0,sizeof(porthash));
+ dh = SLPDatabaseOpen(&G_SlpdDatabase.database);
+ while ((entry = SLPDatabaseEnum(dh)) != 0) {
+ srvreg = &(entry->msg->body.srvreg);
+ if (!srvreg->watchflags)
+ continue;
+ flags |= srvreg->watchflags;
+ port = srvreg->watchport;
+ porthash[(port / 8) & 255] |= 1 << (port & 7);
+ srvreg->watchflags |= SLP_REG_WATCH_CHECKING;
+ }
+ SLPDatabaseClose(dh);
+ if ((flags & SLP_REG_WATCH_TCP) != 0) {
+ SLPDDatabaseWatcher_fd(proctcp, SLP_REG_WATCH_TCP, porthash);
+ SLPDDatabaseWatcher_fd(proctcp6, SLP_REG_WATCH_TCP, porthash);
+ }
+ if ((flags & SLP_REG_WATCH_UDP) != 0) {
+ SLPDDatabaseWatcher_fd(procudp, SLP_REG_WATCH_UDP, porthash);
+ SLPDDatabaseWatcher_fd(procudp6, SLP_REG_WATCH_UDP, porthash);
+ }
+ dh = SLPDatabaseOpen(&G_SlpdDatabase.database);
+ while ((entry = SLPDatabaseEnum(dh)) != 0) {
+ srvreg = &(entry->msg->body.srvreg);
+ if (!srvreg->watchflags)
+ continue;
+ switch (srvreg->watchflags & (SLP_REG_WATCH_CHECKING | SLP_REG_WATCH_DEAD)) {
+ case SLP_REG_WATCH_CHECKING:
+ srvreg->watchflags |= SLP_REG_WATCH_DEAD;
+ SLPDKnownDADeRegisterWithAllDas(entry->msg, entry->buf);
+ SLPDLogRegistration("port dead",entry);
+ break;
+ case SLP_REG_WATCH_DEAD:
+ srvreg->watchflags ^= SLP_REG_WATCH_DEAD;
+ SLPDKnownDARegisterWithAllDas(entry->msg, entry->buf);
+ SLPDLogRegistration("port living",entry);
+ break;
+ }
+ srvreg->watchflags &= ~SLP_REG_WATCH_CHECKING;
+ }
+ SLPDatabaseClose(dh);
+}
+
+
+
+
+/*=========================================================================*/
+int SLPDDatabaseReInit()
/* Re-initialize the database with changed registrations from a regfile. */
/* */
/* regfile (IN) the regfile to register. */
@@ -857,6 +1000,8 @@ int SLPDDatabaseReInit(const char* regfi
SLPDatabaseEntry* entry;
SLPMessage msg;
SLPBuffer buf;
+ struct dirent *direntry;
+ DIR *dirfp;
FILE* fd;
/*------------------------------------------------------------------*/
@@ -882,19 +1027,40 @@ int SLPDDatabaseReInit(const char* regfi
/*--------------------------------------*/
/* Read static registration file if any */
/*--------------------------------------*/
- if ( regfile )
+ if ( regfileFP )
{
- fd = fopen(regfile,"rb");
- if ( fd )
+ rewind(regfileFP);
+ while ( SLPDRegFileReadSrvReg(regfileFP, &msg, &buf) == 0 )
{
- while ( SLPDRegFileReadSrvReg(fd, &msg, &buf) == 0 )
- {
- SLPDDatabaseReg(msg, buf);
- }
+ SLPDDatabaseReg(msg, buf);
+ }
+ }
- fclose(fd);
+ /*------------------------------------------------------------------*/
+ /* Read all static registration file, which comes with any package */
+ /* SuSE ONLY */
+ /*------------------------------------------------------------------*/
+ dirfp = opendir(reg_file_dir);
+ while ( dirfp && (direntry = readdir(dirfp)) != 0) {
+ if ( direntry->d_name && direntry->d_name[0] != '.' ){
+ char filename[1024];
+ snprintf( filename, 1023, "%s/%s", reg_file_dir, direntry->d_name );
+
+ if ( strlen(filename)>4 &&
+ strcmp(filename+strlen(filename)-4, ".reg") == 0 &&
+ (fd=fopen(filename,"rb")) )
+ {
+ while ( SLPDRegFileReadSrvReg(fd, &msg, &buf) == 0 )
+ {
+ SLPDDatabaseReg(msg, buf);
+ }
+
+ fclose(fd);
+ }
}
- }
+ }
+ if ( dirfp )
+ closedir(dirfp);
return 0;
}
--- ./slpd/slpd_database.h.orig 2001-05-10 15:04:19.000000000 +0000
+++ ./slpd/slpd_database.h 2006-11-16 16:19:30.000000000 +0000
@@ -266,7 +266,7 @@ int SLPDDatabaseIsEmpty();
/*=========================================================================*/
-int SLPDDatabaseInit(const char* regfile);
+int SLPDDatabaseInit();
/* Initialize the database with registrations from a regfile. */
/* */
/* regfile (IN) the regfile to register. Pass in NULL for no regfile */
@@ -276,7 +276,7 @@ int SLPDDatabaseInit(const char* regfile
/*=========================================================================*/
-int SLPDDatabaseReInit(const char* regfile);
+int SLPDDatabaseReInit();
/* Re-initialize the database with changed registrations from a regfile. */
/* */
/* regfile (IN) the regfile to register. */
@@ -284,6 +284,8 @@ int SLPDDatabaseReInit(const char* regfi
/* Returns - zero on success or non-zero on error. */
/*=========================================================================*/
+void SLPDDatabaseWatcher(void);
+
#ifdef DEBUG
/*=========================================================================*/
void SLPDDatabaseDeinit(void);
--- ./slpd/slpd_knownda.c.orig 2003-02-04 20:41:15.000000000 +0000
+++ ./slpd/slpd_knownda.c 2006-11-16 16:19:30.000000000 +0000
@@ -1640,7 +1640,7 @@ void SLPDKnownDARegisterWithAllDas(SLPMe
/* Returns: None */
/*=========================================================================*/
{
- if (msg->header.functionid == SLP_FUNCT_SRVDEREG)
+ if (msg->header.functionid == SLP_FUNCT_SRVREG)
{
/* Simply echo the message through as is */
SLPDKnownDAEcho(msg,buf);
--- ./slpd/slpd_log.c.orig 2002-12-03 21:04:53.000000000 +0000
+++ ./slpd/slpd_log.c 2006-11-16 16:19:30.000000000 +0000
@@ -271,6 +271,7 @@ void SLPDLogSrvTypeRqstMessage(SLPSrvTyp
/*-------------------------------------------------------------------------*/
{
SLPDLog("Message SRVTYPERQST:\n");
+ SLPDLogBuffer(" scope = ", srvtyperqst->scopelistlen, srvtyperqst->scopelist);
}
/*-------------------------------------------------------------------------*/
--- ./slpd/slpd_main.c.orig 2002-12-03 21:04:53.000000000 +0000
+++ ./slpd/slpd_main.c 2006-11-16 16:19:30.000000000 +0000
@@ -54,6 +54,7 @@
#include "slpd_log.h"
#include "slpd_socket.h"
#include "slpd_incoming.h"
+#include "slpd_mdns.h"
#include "slpd_outgoing.h"
#include "slpd_database.h"
#include "slpd_cmdline.h"
@@ -73,7 +74,9 @@
/*==========================================================================*/
int G_SIGALRM;
int G_SIGTERM;
-int G_SIGHUP;
+int G_SIGHUP;
+char *reg_file_dir;
+
#ifdef DEBUG
int G_SIGINT; /* Signal being used for dumping registrations */
#endif
@@ -160,6 +163,9 @@ void HandleSigTerm()
/* close all incoming sockets */
SLPDIncomingDeinit();
+#ifdef ENABLE_MDNS_SLPD
+ SLPDMDNSDeinit();
+#endif
/* unregister with all DAs */
SLPDKnownDADeinit();
@@ -218,15 +224,22 @@ void HandleSigHup()
SLPDKnownDADeinit();
/* re-read properties */
+#if 0
SLPDPropertyInit(G_SlpdCommandLine.cfgfile);
+#else
+ SLPDPropertyInit((char *)0);
+#endif
#ifdef ENABLE_SLPv2_SECURITY
+ /* does not work in chroot, sorry */
+# if 0
/* Re-initialize SPI stuff*/
SLPDSpiInit(G_SlpdCommandLine.spifile);
+# endif
#endif
/* Re-read the static registration file (slp.reg)*/
- SLPDDatabaseReInit(G_SlpdCommandLine.regfile);
+ SLPDDatabaseReInit();
/* Rebuild Known DA database */
SLPDKnownDAInit();
@@ -247,6 +260,7 @@ void HandleSigAlrm()
SLPDKnownDAPassiveDAAdvert(SLPD_AGE_INTERVAL,0);
SLPDKnownDAActiveDiscovery(SLPD_AGE_INTERVAL);
SLPDDatabaseAge(SLPD_AGE_INTERVAL,G_SlpdProperty.isDA);
+ SLPDDatabaseWatcher();
}
@@ -377,11 +391,21 @@ int Daemonize(const char* pidfile)
close(2);
setsid(); /* will only fail if we are already the process group leader */
+ pwent = getpwnam("daemon");
+ /*---------------------*/
+ /* chroot to slp.reg.d */
+ /*---------------------*/
+ if (chroot(reg_file_dir))
+ {
+ exit(1);
+ }
+ free(reg_file_dir);
+ reg_file_dir = strdup(".");
+
/*----------------*/
/* suid to daemon */
/*----------------*/
/* TODO: why do the following lines mess up my signal handlers? */
- pwent = getpwnam("daemon");
if(pwent)
{
if(setgroups(1, &pwent->pw_gid) < 0 ||
@@ -389,7 +413,10 @@ int Daemonize(const char* pidfile)
setuid(pwent->pw_uid) < 0)
{
/* TODO: should we log here and return fail */
+ exit(1);
}
+ }else{
+ exit(1);
}
/*--------------------*/
@@ -469,6 +496,8 @@ int main(int argc, char* argv[])
int highfd;
int fdcount = 0;
+ reg_file_dir = strdup("/etc/slp.reg.d");
+
#ifdef DEBUG
xmalloc_init("/var/log/slpd_xmalloc.log",0);
#endif
@@ -534,6 +563,9 @@ int main(int argc, char* argv[])
#endif
SLPDDatabaseInit(G_SlpdCommandLine.regfile) ||
SLPDIncomingInit() ||
+#ifdef ENABLE_MDNS_SLPD
+ SLPDMDNSInit() ||
+#endif
SLPDOutgoingInit() ||
SLPDKnownDAInit())
{
@@ -543,6 +575,11 @@ int main(int argc, char* argv[])
SLPDLog("Agent URL = %s\n",G_SlpdProperty.myUrl);
/*---------------------------*/
+ /* init watcher */
+ /*---------------------------*/
+ SLPDDatabaseWatcher();
+
+ /*---------------------------*/
/* make slpd run as a daemon */
/*---------------------------*/
if(Daemonize(G_SlpdCommandLine.pidfile))
@@ -585,6 +622,10 @@ int main(int argc, char* argv[])
LoadFdSets(&G_IncomingSocketList, &highfd, &readfds,&writefds);
LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds);
+#ifdef ENABLE_MDNS_SLPD
+ LoadFdSets(&G_MDNSSocketList, &highfd, &readfds,&writefds);
+#endif
+
/*--------------------------------------------------*/
/* Before select(), check to see if we got a signal */
/*--------------------------------------------------*/
@@ -601,6 +642,10 @@ int main(int argc, char* argv[])
{
SLPDIncomingHandler(&fdcount,&readfds,&writefds);
SLPDOutgoingHandler(&fdcount,&readfds,&writefds);
+
+#ifdef ENABLE_MDNS_SLPD
+ SLPDMDNSHandler(&fdcount,&readfds,&writefds);
+#endif
}
/*----------------*/
--- ./slpd/slpd_mdns.c.orig 2006-11-16 16:19:30.000000000 +0000
+++ ./slpd/slpd_mdns.c 2006-11-16 16:19:30.000000000 +0000
@@ -0,0 +1,906 @@
+#include "slpd_mdns.h"
+#include "slpd_socket.h"
+#include "slpd_property.h"
+#include "slpd_database.h"
+#include "slpd_log.h"
+
+#include "slp_compare.h"
+#ifdef ENABLE_PREDICATES
+# include "slpd_predicate.h"
+#endif
+
+
+extern SLPDDatabase G_SlpdDatabase;
+
+extern int JoinSLPMulticastGroup(sockfd_t sockfd, struct in_addr* maddr,
+ struct in_addr* addr);
+extern int EnableBroadcast(sockfd_t sockfd);
+
+
+#define MDNS_MAX_DATAGRAM_SIZE 8000
+
+/*=========================================================================*/
+/* common code includes */
+/*=========================================================================*/
+#include "slp_xmalloc.h"
+
+
+static void MDNSDatagramRead(SLPList* socklist, SLPDSocket* sock);
+static int MDNSHandleSrvTypeRqst(SLPBuffer buf, SLPBuffer obuf, unsigned char *q, int qtype, unsigned char **an, unsigned char **ad, int ac, int mdnspeer, unsigned char *txtbuf, int txtlen);
+static int MDNSHandleSrvsRqst(SLPBuffer buf, SLPBuffer obuf, unsigned char *q, int qtype, unsigned char **an, unsigned char **ad, int ac, int mdnspeer, unsigned char *txtbuf, int txtlen, struct sockaddr_in *);
+static int MDNSHandleARqst(SLPBuffer buf, SLPBuffer obuf, unsigned char *q, int qtype, unsigned char **an, unsigned char **ad, int ac, int mdnspeer, struct sockaddr_in *ifaddr);
+
+
+SLPList G_MDNSSocketList = {0,0,0};
+
+
+SLPDSocket* SLPDMDNSCreateBoundDatagram(struct in_addr* myaddr,
+ struct in_addr* peeraddr,
+ int type)
+{
+ SLPDSocket* sock;
+ struct in_addr* bindaddr;
+ struct sockaddr_in mysockaddr;
+#ifdef _WIN32
+ BOOL reuse = TRUE;
+#else
+ int reuse = 1;
+#endif
+ unsigned char ttl = 255;
+
+ /*------------------------------------------*/
+ /* Adjust for multicast binding differences */
+ /*------------------------------------------*/
+#ifdef LINUX
+ bindaddr = peeraddr;
+#else
+ if(type == DATAGRAM_MULTICAST)
+ bindaddr = NULL; /* must bind to INADDR_ANY for multicast */
+ else
+ bindaddr = peeraddr;
+#endif
+
+ /*------------------------*/
+ /* Create and bind socket */
+ /*------------------------*/
+ sock = SLPDSocketAlloc();
+ if (!sock)
+ return 0;
+ if (myaddr)
+ sock->ifaddr.sin_addr = *myaddr;
+ sock->recvbuf = SLPBufferAlloc(MDNS_MAX_DATAGRAM_SIZE);
+ sock->sendbuf = SLPBufferAlloc(MDNS_MAX_DATAGRAM_SIZE);
+ sock->fd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock->fd < 0)
+ {
+ SLPDSocketFree(sock);
+ return 0;
+ }
+ memset(&mysockaddr, 0, sizeof(mysockaddr));
+ mysockaddr.sin_family = AF_INET;
+ mysockaddr.sin_port = htons(MDNS_RESERVED_PORT);
+ mysockaddr.sin_addr.s_addr = INADDR_ANY;
+ if (bindaddr)
+ mysockaddr.sin_addr = *bindaddr;
+ setsockopt(sock->fd,SOL_SOCKET,SO_REUSEADDR,(const char *)&reuse,sizeof(reuse));
+ setsockopt(sock->fd,SOL_IP,IP_TTL,(const char *)&ttl,sizeof(ttl));
+ setsockopt(sock->fd,SOL_IP,IP_MULTICAST_TTL,(const char *)&ttl,sizeof(ttl));
+ if (bind(sock->fd, (struct sockaddr *) &mysockaddr,sizeof(mysockaddr)))
+ {
+ SLPDSocketFree(sock);
+ return 0;
+ }
+ if(peeraddr != NULL)
+ sock->peeraddr.sin_addr = *peeraddr;
+ switch(type)
+ {
+ case DATAGRAM_MULTICAST:
+ if(JoinSLPMulticastGroup(sock->fd, peeraddr, myaddr) == 0)
+ {
+ sock->state = DATAGRAM_MULTICAST;
+ return sock;
+ }
+ break;
+ case DATAGRAM_BROADCAST:
+ if(EnableBroadcast(sock->fd) == 0)
+ {
+ sock->state = DATAGRAM_BROADCAST;
+ return sock;
+ }
+ break;
+ case DATAGRAM_UNICAST:
+ default:
+ sock->state = DATAGRAM_UNICAST;
+ return sock;
+ }
+ SLPDSocketFree(sock);
+ return 0;
+}
+
+int SLPDMDNSInit(void)
+{
+ int iface;
+ struct in_addr myaddr;
+ struct in_addr mcastaddr;
+ SLPDSocket* sock;
+
+ /*------------------------------------------------------------*/
+ /* First, remove all of the sockets that might be in the list */
+ /*------------------------------------------------------------*/
+ while (G_MDNSSocketList.count)
+ {
+ SLPDSocketFree((SLPDSocket*)SLPListUnlink(&G_MDNSSocketList,G_MDNSSocketList.head));
+ }
+
+ /*----------------------------------------------------------------*/
+ /* Create sockets for all of the interfaces in the interface list */
+ /*----------------------------------------------------------------*/
+ mcastaddr.s_addr = htonl(MDNS_MCAST_ADDRESS);
+
+ for (iface = 0; iface < G_SlpdProperty.ifaceInfo.iface_count; iface++)
+ {
+ myaddr = G_SlpdProperty.ifaceInfo.iface_addr[iface].sin_addr;
+
+ /*----------------------------------------------------------------*/
+ /* Create socket that will handle multicast UDP. */
+ /*----------------------------------------------------------------*/
+
+ sock = SLPDMDNSCreateBoundDatagram(&myaddr,
+ &mcastaddr,
+ DATAGRAM_MULTICAST);
+ if (sock)
+ {
+ SLPListLinkTail(&G_MDNSSocketList,(SLPListItem*)sock);
+ SLPDLog("Multicast MDNS socket on %s ready\n",inet_ntoa(myaddr));
+ }
+ else
+ {
+ SLPDLog("Couldn't bind to multicast MDNS for interface %s (%s)\n",
+ inet_ntoa(myaddr), strerror(errno));
+ }
+
+ /*--------------------------------------------*/
+ /* Create socket that will handle unicast UDP */
+ /*--------------------------------------------*/
+ sock = SLPDMDNSCreateBoundDatagram(&myaddr,
+ &myaddr,
+ DATAGRAM_UNICAST);
+ if (sock)
+ {
+ SLPListLinkTail(&G_MDNSSocketList,(SLPListItem*)sock);
+ SLPDLog("Unicast MDNS socket on %s ready\n",inet_ntoa(myaddr));
+ }
+ }
+
+ if (G_MDNSSocketList.count == 0)
+ {
+ SLPDLog("No usable MDNS interfaces\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+/*=========================================================================*/
+int SLPDMDNSDeinit()
+/* Deinitialize incoming socket list to have appropriate sockets for all */
+/* network interfaces */
+/* */
+/* Returns Zero on success non-zero on error */
+/*=========================================================================*/
+{
+ SLPDSocket* del = 0;
+ SLPDSocket* sock = (SLPDSocket*)G_MDNSSocketList.head;
+ while (sock)
+ {
+ del = sock;
+ sock = (SLPDSocket*)sock->listitem.next;
+ if (del)
+ {
+ SLPDSocketFree((SLPDSocket*)SLPListUnlink(&G_MDNSSocketList,(SLPListItem*)del));
+ del = 0;
+ }
+ }
+
+ return 0;
+}
+
+/*=========================================================================*/
+void SLPDMDNSHandler(int* fdcount,
+ fd_set* readfds,
+ fd_set* writefds)
+/* Handles all outgoing requests that are pending on the specified file */
+/* discriptors */
+/* */
+/* fdcount (IN/OUT) number of file descriptors marked in fd_sets */
+/* */
+/* readfds (IN) file descriptors with pending read IO */
+/* */
+/* writefds (IN) file descriptors with pending read IO */
+/*=========================================================================*/
+{
+ SLPDSocket* sock;
+ sock = (SLPDSocket*) G_MDNSSocketList.head;
+ while (sock && *fdcount)
+ {
+ if (FD_ISSET(sock->fd,readfds))
+ {
+ switch (sock->state)
+ {
+ case DATAGRAM_UNICAST:
+ case DATAGRAM_MULTICAST:
+ case DATAGRAM_BROADCAST:
+ MDNSDatagramRead(&G_MDNSSocketList,sock);
+ break;
+ default:
+ break;
+ }
+
+ *fdcount = *fdcount - 1;
+ }
+ sock = (SLPDSocket*)sock->listitem.next;
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+static void MDNSDatagramRead(SLPList* socklist, SLPDSocket* sock)
+/*-------------------------------------------------------------------------*/
+{
+ int bytesread;
+ int bytestowrite;
+ int byteswritten;
+ int peeraddrlen = sizeof(struct sockaddr_in);
+ int qcount, acount, ncount, xcount;
+ unsigned char *bp, *end;
+ SLPBuffer buf;
+ int mdnspeer;
+ int qtype = 0;
+ int qclass = 0;
+ unsigned char * an[SLP_MDNS_MAX_RR];
+ unsigned char * ad[SLP_MDNS_MAX_RR];
+ int ac;
+ int result;
+ unsigned char * txtbuf = 0;
+ int txtlen = 0;
+
+
+ buf = sock->recvbuf;
+ bytesread = recvfrom(sock->fd,
+ buf->start,
+ MDNS_MAX_DATAGRAM_SIZE,
+ 0,
+ (struct sockaddr *) &(sock->peeraddr),
+ &peeraddrlen);
+ if (bytesread < 12)
+ return;
+ buf->end = buf->start + bytesread;
+#ifdef DEBUG
+ SLPMDNSDumpDNS(buf, "mdns incoming");
+#endif
+
+ if ((buf->start[2] & 0xf0) != 0x00)
+ return; /* no standard query */
+
+ qcount = AsUINT16(buf->start + 4);
+ if (qcount > 1)
+ return; /* not supported at the moment */
+ if (qcount == 0)
+ return; /* no query to answer */
+ acount = AsUINT16(buf->start + 6);
+ ncount = AsUINT16(buf->start + 8);
+ xcount = AsUINT16(buf->start + 10);
+
+ bp = (unsigned char *)buf->start + 12;
+ /* skip query section */
+ end = buf->end;
+ if (qcount)
+ {
+ while (bp < end && *bp && (*bp & 0xc0) != 0xc0)
+ bp += *bp + 1;
+ if (bp < end && *bp)
+ bp++;
+ bp += 5;
+ if (bp <= end)
+ {
+ qtype = AsUINT16(bp - 4);
+ qclass = AsUINT16(bp - 2);
+ }
+ }
+ bp = SLPMDNSParseRR(bp, end, acount, an, ad, &ac);
+ if (bp > end)
+ return;
+ bp = SLPMDNSParseRR(bp, end, ncount, 0, 0, 0);
+ bp = SLPMDNSParseRR(bp, end, xcount, 0, 0, 0);
+
+ /* validate DNS request */
+ if (qcount > 0 && SLPMDNSCheckN(buf->start, bp > end ? end : bp, buf->start + 12, 0))
+ return;
+ if (SLPMDNSCheckRR(buf->start, bp > end ? end : bp, an, ad, &ac))
+ return;
+
+ if (qcount == 0)
+ return;
+ if (qclass != DNS_CLASS_IN && qclass != DNS_CLASS_ANY)
+ return;
+ mdnspeer = (sock->peeraddr.sin_port == htons(MDNS_RESERVED_PORT));
+
+ if (qtype == DNS_TYPE_ANY || qtype == DNS_TYPE_A)
+ {
+ unsigned char myhostname[256];
+ if (MDNSStrToN(myhostname, myhostname + sizeof(myhostname), G_SlpdProperty.myHostname, G_SlpdProperty.myHostnameLen))
+ {
+ if (!SLPMDNSCmpN(buf->start + 12, buf->start, myhostname, 0))
+ {
+ result = MDNSHandleARqst(buf, sock->sendbuf, buf->start + 12, qtype, an, ad, ac, mdnspeer, &sock->ifaddr);
+ goto reply;
+ }
+ }
+ }
+
+ if (qtype != DNS_TYPE_PTR && qtype != DNS_TYPE_ANY)
+ return;
+ if (ac > 0 && !memcmp(an[0], "\011_slpquery\300\014", 12) && AsUINT16(ad[0]) == DNS_TYPE_TXT)
+ {
+ txtlen = AsUINT16(ad[0] + 8);
+ txtbuf = ad[0] + 10;
+ }
+
+ if (!SLPMDNSCmpN(buf->start + 12, buf->start, "\011_services\007_dns-sd\004_udp\005local\000", 0))
+ {
+ result = MDNSHandleSrvTypeRqst(buf, sock->sendbuf, buf->start + 12, qtype, an, ad, ac, mdnspeer, txtbuf, txtlen);
+ }
+ else
+ {
+ result = MDNSHandleSrvsRqst(buf, sock->sendbuf, buf->start + 12, qtype, an, ad, ac, mdnspeer, txtbuf, txtlen, &sock->ifaddr);
+ }
+
+reply:
+ if (result)
+ return;
+
+ bytestowrite = sock->sendbuf->end - sock->sendbuf->start;
+ if (bytestowrite > 0)
+ {
+ byteswritten = sendto(sock->fd,
+ sock->sendbuf->start,
+ bytestowrite,
+ 0,
+ (struct sockaddr *)&(sock->peeraddr),
+ sizeof(struct sockaddr_in));
+ if (byteswritten != bytestowrite)
+ {
+ SLPDLog("NETWORK_ERROR - %d replying %s\n",
+ errno,
+ inet_ntoa(sock->peeraddr.sin_addr));
+ }
+ }
+
+}
+
+static int MDNSParseHostPort(const char *url, int urllen, const char **hostp, int *portp)
+{
+ int l, hl, port;
+
+ for (l = 0; l < urllen; l++)
+ if (l && url[l] == '/' && url[l - 1] == '/')
+ break;
+ l++;
+ if (l >= urllen)
+ return 0;
+ url += l;
+ urllen -= l;
+ if (hostp)
+ *hostp = url;
+ for (l = 0; l < urllen ; l++)
+ if (url[l] == '/' || url[l] == ':')
+ break;
+ if (l == urllen || url[l] != ':')
+ {
+ if (portp)
+ *portp = 0;
+ return l;
+ }
+ port = 0;
+ hl = l++;
+ url += l;
+ urllen -= l;
+ for (l = 0; l < urllen ; l++)
+ if (url[l] <= '0' || url[l] >= '9')
+ break;
+ else
+ port = port * 10 + (url[l] - '0');
+ if (l < urllen && url[l] != '/')
+ return 0;
+ if (portp)
+ *portp = port;
+ return hl;
+}
+
+
+static int MDNSHandleSrvTypeRqst(SLPBuffer buf, SLPBuffer obuf, unsigned char *q, int qtype, unsigned char **an, unsigned char **ad, int ac, int mdnspeer, unsigned char *txtbuf, int txtlen)
+{
+ SLPDatabaseHandle dh;
+ SLPDatabaseEntry* entry;
+ SLPSrvReg* entryreg;
+ char srvbuf[80];
+ unsigned char *md[SLP_MDNS_MAX_RR];
+ unsigned char *oend, *bp, *oldbp;
+ unsigned char *cvec[256];
+ int i, port;
+ int ncvec;
+ int nans;
+ char *nameauth;
+ int nameauthlen;
+
+ nameauthlen = 0xffff;
+ nameauth = SLPMDNSFindInTxt(txtbuf, txtlen, "namingauth=", &nameauthlen);
+
+ obuf->start[0] = buf->start[0]; /* xid */
+ obuf->start[1] = buf->start[1]; /* xid */
+ obuf->start[2] = 0x84;
+ obuf->start[3] = 0x00;
+ obuf->start[4] = obuf->start[5] = 0; /* qcount */
+ obuf->start[6] = obuf->start[7] = 0; /* acount */
+ obuf->start[8] = obuf->start[9] = 0; /* ncount */
+ obuf->start[10] = obuf->start[11] = 0; /* xcount */
+
+ ncvec = 0;
+ bp = obuf->start + 12;
+ oend = obuf->start + obuf->allocated;
+ if (!mdnspeer)
+ {
+ bp = SLPMDNSCompN(bp, oend, q, buf->start, cvec, &ncvec, obuf->start);
+ if (!bp || bp + 4 >= oend)
+ return 1;
+ *bp++ = 0;
+ *bp++ = qtype;
+ *bp++ = 0;
+ *bp++ = DNS_CLASS_IN;
+ obuf->start[5] = 1;
+ }
+
+ nans = 0;
+ dh = SLPDatabaseOpen(&G_SlpdDatabase.database);
+ while ((entry = SLPDatabaseEnum(dh)) != 0)
+ {
+ entryreg = &(entry->msg->body.srvreg);
+ if ((entryreg->watchflags & SLP_REG_WATCH_DEAD) != 0)
+ continue;
+
+ if (SLPCompareNamingAuth(entryreg->srvtypelen,
+ entryreg->srvtype,
+ nameauthlen,
+ nameauth))
+ continue;
+
+#if 0
+ if (!SLPContainsStringList(entryreg->scopelistlen, entryreg->scopelist, 5, "_mdns"))
+ continue;
+#endif
+
+ if (!MDNSParseHostPort(entryreg->urlentry.url, entryreg->urlentry.urllen, 0, &port))
+ continue;
+ if (!port)
+ continue;
+
+ if (!SLPMDNSSrvtypeToN(srvbuf, srvbuf + sizeof(srvbuf), entryreg->srvtype, entryreg->srvtypelen))
+ continue;
+
+ /* check if answer is already known in query */
+ for (i = 0; i < ac; i++)
+ if (AsUINT16(ad[i]) == DNS_TYPE_PTR &&
+ !SLPMDNSCmpN(ad[i] + 10, buf->start, srvbuf, 0))
+ break;
+ if (i < ac)
+ continue;
+
+ /* check if answer already in our packet */
+ for (i = 0; i < nans; i++)
+ if (!SLPMDNSCmpN(md[i] + 10, obuf->start, srvbuf, 0))
+ break;
+ if (i < nans)
+ continue;
+
+ /* new answer, add to return buffer */
+ oldbp = bp;
+ bp = SLPMDNSAddRR(bp, obuf->start, oend, q, buf->start,
+ DNS_TYPE_PTR, mdnspeer ? entryreg->urlentry.lifetime : 10,
+ cvec, &ncvec, 0, srvbuf, md + nans);
+ if (!bp)
+ {
+ bp = oldbp;
+ break;
+ }
+ if (++nans == SLP_MDNS_MAX_RR)
+ break;
+ }
+ ToUINT16(obuf->start + 6, nans);
+ SLPDatabaseClose(dh);
+ if (bp >= oend)
+ return 1;
+ if (nans)
+ {
+ obuf->end = bp;
+#ifdef DEBUG
+ SLPMDNSDumpDNS(obuf, "mdns outgoing");
+#endif
+ }
+ else
+ obuf->end = obuf->start;
+ return 0;
+}
+
+
+static void SLPDAddAttrs(unsigned char *txtbuf, int txtbuflen, int *txtlen, const char *attr, int attrlen, char *taglist, int taglistlen)
+{
+ const char *ts, *vs;
+ int tl, vl, i;
+
+ while (attrlen > 0)
+ {
+ if (*attr != '(')
+ {
+ /* keyword */
+ vs = 0;
+ vl = 0;
+ ts = attr;
+ for (i = 0; i < attrlen; i++)
+ if (attr[i] == ',')
+ break;
+ tl = i;
+ attr += i;
+ attrlen -= i;
+ }
+ else
+ {
+ /* (key=value,value...) */
+ attr++;
+ attrlen--;
+ ts = attr;
+ for (i = 0; i < attrlen; i++)
+ if (attr[i] == '=')
+ break;
+ tl = i;
+ attr += i + 1;
+ attrlen -= i + 1;
+ if (attrlen <= 0)
+ break;
+ vs = attr;
+ for (i = 0; i < attrlen; i++)
+ if (attr[i] == ')')
+ break;
+ if (i == attrlen)
+ break;
+ vl = i;
+ attr += i + 1;
+ attrlen -= i + 1;
+ }
+ if (!taglistlen || SLPContainsStringList(taglistlen, taglist, tl, ts))
+ {
+ if (tl + 1 + vl <= 255)
+ {
+ char tagbuf[256];
+ memcpy(tagbuf, ts, tl);
+ if (vs)
+ {
+ tagbuf[tl] = '=';
+ tl++;
+ }
+ tagbuf[tl] = 0;
+ SLPMDNSAddTxt(txtbuf, txtbuflen, txtlen, tagbuf, vs, vl);
+ }
+ }
+ if (attrlen)
+ {
+ attr++;
+ attrlen--;
+ }
+ }
+}
+
+static int MDNSHandleSrvsRqst(SLPBuffer buf, SLPBuffer obuf, unsigned char *q, int qtype, unsigned char **an, unsigned char **ad, int ac, int mdnspeer, unsigned char *txtbuf, int txtlen, struct sockaddr_in *ifaddr)
+{
+ SLPDatabaseHandle dh;
+ SLPDatabaseEntry* entry;
+ SLPSrvReg* entryreg;
+ SLPUrlEntry* urlentry;
+ char srvtype[256];
+ int srvtypelen;
+ int i;
+ unsigned char *bp, *oend;
+ unsigned char *cvec[256];
+ int ncvec;
+ const char *host;
+ int hostlen, hostlennq;
+ int port;
+ unsigned char ptr[256];
+ int nans;
+ unsigned char *oldbp;
+ unsigned char xbuf[8000];
+ unsigned char *xn[SLP_MDNS_MAX_RR];
+ unsigned char *xd[SLP_MDNS_MAX_RR];
+ unsigned char *xp, *xend;
+ int xc = 0;
+ unsigned char *rad[SLP_MDNS_MAX_RR];
+ int unify;
+#ifdef ENABLE_PREDICATES
+ int predlen;
+ char *pred;
+#endif
+ char *slpurl;
+ int slpurllen;
+ char *taglist;
+ int taglistlen;
+ unsigned char otxtbuf[512];
+ int otxtlen;
+
+ slpurllen = 0;
+ slpurl = SLPMDNSFindInTxt(txtbuf, txtlen, "slpurl=", &slpurllen);
+ taglistlen = 0;
+ taglist = SLPMDNSFindInTxt(txtbuf, txtlen, "taglist=", &taglistlen);
+
+#ifdef ENABLE_PREDICATES
+ predlen = 0;
+ pred = SLPMDNSFindInTxt(txtbuf, txtlen, "predicate=", &predlen);
+#endif
+
+ xp = xbuf;
+ xend = xbuf + sizeof(xbuf);
+
+ obuf->start[0] = buf->start[0]; /* xid */
+ obuf->start[1] = buf->start[1]; /* xid */
+ obuf->start[2] = 0x84;
+ obuf->start[3] = 0x00;
+ obuf->start[4] = obuf->start[5] = 0; /* qcount */
+ obuf->start[6] = obuf->start[7] = 0; /* acount */
+ obuf->start[8] = obuf->start[9] = 0; /* ncount */
+ obuf->start[10] = obuf->start[11] = 0; /* xcount */
+
+ ncvec = 0;
+ bp = obuf->start + 12;
+ oend = obuf->start + obuf->allocated;
+ if (!mdnspeer)
+ {
+ bp = SLPMDNSCompN(bp, oend, q, buf->start, cvec, &ncvec, obuf->start);
+ if (!bp || bp + 4 >= oend)
+ return 1;
+ *bp++ = 0;
+ *bp++ = qtype;
+ *bp++ = 0;
+ *bp++ = DNS_CLASS_IN;
+ obuf->start[5] = 1;
+ }
+ /* convert query in srvtype (query is already checked) */
+ srvtypelen = SLPMDNSNToSrvtype(q, buf->start, srvtype, sizeof(srvtype) - 1);
+ if (srvtypelen == 0)
+ return 1;
+ srvtype[srvtypelen] = 0;
+ /* printf("srvtype: %s\n", srvtype); */
+
+ nans = 0;
+ dh = SLPDatabaseOpen(&G_SlpdDatabase.database);
+ while ((entry = SLPDatabaseEnum(dh)) != 0)
+ {
+ entryreg = &(entry->msg->body.srvreg);
+ if ((entryreg->watchflags & SLP_REG_WATCH_DEAD) != 0)
+ continue;
+ urlentry = &entryreg->urlentry;
+
+ /* limit to one exact url, used for AttrRqst */
+ if (slpurllen && SLPCompareString(urlentry->urllen, urlentry->url, slpurllen, slpurl))
+ continue;
+
+ /* limit to matching srvtypes */
+ if (!slpurllen && SLPCompareSrvType(srvtypelen,
+ srvtype,
+ entryreg->srvtypelen,
+ entryreg->srvtype) != 0)
+ continue;
+
+#ifdef ENABLE_PREDICATES
+ if (!SLPDPredicateTest(2,
+ entryreg->attrlistlen,
+ entryreg->attrlist,
+ predlen,
+ pred))
+ continue;
+#endif
+
+ otxtlen = 0;
+
+ /* printf("HIT: %.*s\n", urlentry->urllen, urlentry->url); */
+
+ hostlen = MDNSParseHostPort(urlentry->url, urlentry->urllen, &host, &port);
+ if (!hostlen || !port)
+ continue;
+ if (*host >= '0' && *host <= '9')
+ hostlennq = hostlen;
+ else
+ for (hostlennq = 0; hostlennq < hostlen; hostlennq++)
+ if (host[hostlennq] == '.')
+ break;
+ if (hostlennq == 0 || hostlennq > 63)
+ continue;
+
+ /* create an unique name */
+ for (unify = 0; unify < SLP_MDNS_MAX_RR; unify++)
+ {
+ ptr[0] = hostlennq;
+ memcpy(ptr + 1, host, hostlennq);
+ if (unify)
+ {
+ /* will always fit into ptr, as hostlennq < 64 */
+ sprintf(ptr + 1 + hostlennq, "_%d", unify == 1 ? port : unify);
+ i = strlen(ptr + 1);
+ if (i > 63)
+ break;
+ ptr[0] = i;
+ }
+ /* append query name */
+ if (!SLPMDNSCopyN(ptr + 1 + *ptr, ptr + sizeof(ptr), q, buf->start))
+ break;
+ for (i = 0; i < nans; i++)
+ if (!SLPMDNSCmpN(rad[i] + 10, obuf->start, ptr, 0))
+ break;
+ if (i == nans)
+ {
+ unify = -1;
+ break;
+ }
+ }
+ if (unify != -1)
+ continue;
+
+ /* check if it is already in the answer section of the query */
+ for (i = 0; i < ac; i++)
+ if (AsUINT16(ad[i]) == DNS_TYPE_PTR &&
+ !SLPMDNSCmpN(ad[i] + 10, buf->start, ptr, 0))
+ break;
+ if (i < ac)
+ continue;
+
+ /* great, a new entry */
+ oldbp = bp;
+ bp = SLPMDNSAddRR(bp, obuf->start, oend, q, buf->start,
+ DNS_TYPE_PTR, mdnspeer ? urlentry->lifetime : 10,
+ cvec, &ncvec, 0, ptr, rad + nans);
+ if (!bp)
+ {
+ bp = oldbp;
+ break;
+ }
+
+ /* set up extra answers */
+ if (xp && xc < SLP_MDNS_MAX_RR)
+ {
+ unsigned char data[256];
+ if (!MDNSStrToN(data, data + sizeof(data), host, hostlen))
+ continue;
+ xn[xc] = xp;
+ xp = SLPMDNSAddRR(xp, 0, xend, ptr, obuf->start,
+ DNS_TYPE_SRV, mdnspeer ? urlentry->lifetime : 10,
+ 0, 0, port, data, xd + xc);
+ if (xp)
+ xc++;
+ }
+ SLPMDNSAddTxt(otxtbuf, sizeof(otxtbuf), &otxtlen, "slpurl=", urlentry->url, urlentry->urllen);
+ SLPDAddAttrs(otxtbuf, sizeof(otxtbuf), &otxtlen, entryreg->attrlist, entryreg->attrlistlen, taglist, taglistlen);
+ if (xp && xc < SLP_MDNS_MAX_RR && otxtlen)
+ {
+ xn[xc] = xp;
+ xp = SLPMDNSAddRR(xp, 0, xend, ptr, obuf->start,
+ DNS_TYPE_TXT, mdnspeer ? urlentry->lifetime : 10,
+ 0, 0, otxtlen, otxtbuf, xd + xc);
+ if (xp)
+ xc++;
+ }
+ if (++nans == SLP_MDNS_MAX_RR)
+ break;
+ }
+ ToUINT16(obuf->start + 6, nans);
+ SLPDatabaseClose(dh);
+ if (bp >= oend)
+ return 1;
+
+ /* add an A RR of our hostname to x info */
+ if (nans && xp && xc < SLP_MDNS_MAX_RR)
+ {
+ unsigned char myhostname[256];
+ if (MDNSStrToN(myhostname, myhostname + sizeof(myhostname), G_SlpdProperty.myHostname, G_SlpdProperty.myHostnameLen))
+ {
+ xn[xc] = xp;
+ xp = SLPMDNSAddRR(xp, 0, xend, myhostname, 0,
+ DNS_TYPE_A, 10,
+ 0, 0, 4, (unsigned char *)&ifaddr->sin_addr,
+ xd + xc);
+ if (xp)
+ xc++;
+ }
+ }
+
+ if (nans)
+ {
+ /* add x info */
+ int nxans = 0;
+ for (i = 0; i < xc; i++)
+ {
+ int type;
+ type = AsUINT16(xd[i]);
+ oldbp = bp;
+ if (type == DNS_TYPE_SRV)
+ bp = SLPMDNSAddRR(bp, obuf->start, oend, xn[i], 0, type, AsUINT32(xd[i] + 4), cvec, &ncvec, AsUINT16(xd[i] + 14), xd[i] + 16, 0);
+ else if (type == DNS_TYPE_TXT || type == DNS_TYPE_A)
+ bp = SLPMDNSAddRR(bp, obuf->start, oend, xn[i], 0, type, AsUINT32(xd[i] + 4), cvec, &ncvec, AsUINT16(xd[i] + 8), xd[i] + 10, 0);
+ else
+ continue;
+ if (!bp)
+ {
+ bp = oldbp;
+ break;
+ }
+ nxans++;
+ }
+ ToUINT16(obuf->start + 10, nxans);
+ obuf->end = bp;
+#ifdef DEBUG
+ SLPMDNSDumpDNS(obuf, "mdns outgoing");
+#endif
+ }
+ else
+ obuf->end = obuf->start;
+ return 0;
+}
+
+static int MDNSHandleARqst(SLPBuffer buf, SLPBuffer obuf, unsigned char *q, int qtype, unsigned char **an, unsigned char **ad, int ac, int mdnspeer, struct sockaddr_in *ifaddr)
+{
+ unsigned char *data, *bp, *oend;
+ unsigned char *cvec[256];
+ int i, ncvec;
+
+ data = (unsigned char *)&ifaddr->sin_addr;
+
+ obuf->start[0] = buf->start[0]; /* xid */
+ obuf->start[1] = buf->start[1]; /* xid */
+ obuf->start[2] = 0x84;
+ obuf->start[3] = 0x00;
+ obuf->start[4] = obuf->start[5] = 0; /* qcount */
+ obuf->start[6] = obuf->start[7] = 0; /* acount */
+ obuf->start[8] = obuf->start[9] = 0; /* ncount */
+ obuf->start[10] = obuf->start[11] = 0; /* xcount */
+
+ ncvec = 0;
+ bp = obuf->start + 12;
+ oend = obuf->start + obuf->allocated;
+ if (!mdnspeer)
+ {
+ bp = SLPMDNSCompN(bp, oend, q, buf->start, cvec, &ncvec, obuf->start);
+ if (!bp || bp + 4 >= oend)
+ return 1;
+ *bp++ = 0;
+ *bp++ = qtype;
+ *bp++ = 0;
+ *bp++ = DNS_CLASS_IN;
+ obuf->start[5] = 1;
+ }
+
+ for (i = 0; i < ac; i++)
+ if (AsUINT16(ad[i]) == DNS_TYPE_A &&
+ !memcmp(ad[i] + 10, data, 4))
+ break;
+ if (i < ac)
+ {
+ obuf->end = obuf->start;
+ return 0;
+ }
+
+ bp = SLPMDNSAddRR(bp, obuf->start, oend, q, buf->start, DNS_TYPE_A, 10, cvec, &ncvec, 4, data, 0);
+ if (!bp)
+ return 1;
+ obuf->start[7] = 1;
+ obuf->end = bp;
+#ifdef DEBUG
+ SLPMDNSDumpDNS(obuf, "mdns outgoing");
+#endif
+ return 0;
+}
--- ./slpd/slpd_mdns.h.orig 2006-11-16 16:19:30.000000000 +0000
+++ ./slpd/slpd_mdns.h 2006-11-16 16:19:30.000000000 +0000
@@ -0,0 +1,50 @@
+#ifndef SLPD_MDNS_H_INCLUDE
+#define SLPD_MDNS_H_INCLUDE
+
+#include "slpd.h"
+
+/*=========================================================================*/
+/* common code includes */
+/*=========================================================================*/
+#include "slp_linkedlist.h"
+#include "slp_mdns.h"
+
+
+/*=========================================================================*/
+extern SLPList G_MDNSSocketList;
+/*=========================================================================*/
+
+
+/*=========================================================================*/
+void SLPDMDNSHandler(int* fdcount,
+ fd_set* readfds,
+ fd_set* writefds);
+/* Handles all outgoing requests that are pending on the specified file */
+/* discriptors */
+/* */
+/* fdcount (IN/OUT) number of file descriptors marked in fd_sets */
+/* */
+/* readfds (IN) file descriptors with pending read IO */
+/* */
+/* writefds (IN) file descriptors with pending read IO */
+/*=========================================================================*/
+
+
+/*=========================================================================*/
+int SLPDMDNSInit(void);
+/* Initialize incoming socket list to have appropriate sockets for all */
+/* network interfaces */
+/* */
+/* Returns Zero on success non-zero on error */
+/*=========================================================================*/
+
+
+/*=========================================================================*/
+int SLPDMDNSDeinit(void);
+/* Deinitialize incoming socket list to have appropriate sockets for all */
+/* network interfaces */
+/* */
+/* Returns Zero on success non-zero on error */
+/*=========================================================================*/
+
+#endif
--- ./slpd/slpd_process.c.orig 2003-02-20 16:43:57.000000000 +0000
+++ ./slpd/slpd_process.c 2006-11-16 16:19:30.000000000 +0000
@@ -1331,11 +1331,14 @@ int SLPDProcessMessage(struct sockaddr_i
SLPDLogMessage(SLPDLOG_TRACEMSG_IN,peerinfo,recvbuf);
- /* set the sendbuf empty */
- if(*sendbuf)
+ if(!*sendbuf)
{
- (*sendbuf)->end = (*sendbuf)->start;
+ *sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE);
+ if (!*sendbuf)
+ return SLP_ERROR_PARSE_ERROR;
}
+ /* set the sendbuf empty */
+ (*sendbuf)->end = (*sendbuf)->start;
/* zero out the header before parsing it */
memset(&header,0,sizeof(header));
--- ./slpd/slpd_property.c.orig 2002-06-11 17:25:40.000000000 +0000
+++ ./slpd/slpd_property.c 2006-11-16 16:19:30.000000000 +0000
@@ -65,6 +65,7 @@
/*=========================================================================*/
SLPDProperty G_SlpdProperty;
+FILE* G_SlpdConffileFP;
/*=========================================================================*/
/*=========================================================================*/
@@ -74,8 +75,18 @@ int SLPDPropertyInit(const char* conffil
char* myname = 0;
char* myinterfaces = 0;
char* myurl = 0;
+ const char* ifaces = 0;
+ extern int * SLPPropertyReadFileFP(FILE *);
- SLPPropertyReadFile(conffile);
+ if (conffile)
+ {
+ G_SlpdConffileFP = fopen(conffile, "r");
+ if (G_SlpdConffileFP)
+ {
+ SLPPropertySet("net.slp.OpenSLPConfigFile",conffile);
+ }
+ }
+ SLPPropertyReadFileFP(G_SlpdConffileFP);
memset(&G_SlpdProperty,0,sizeof(G_SlpdProperty));
@@ -125,9 +136,14 @@ int SLPDPropertyInit(const char* conffil
/*-------------------------------------*/
/* Set the net.slp.interfaces property */
/*-------------------------------------*/
- if(SLPIfaceGetInfo(SLPPropertyGet("net.slp.interfaces"),&G_SlpdProperty.ifaceInfo) == 0)
+ ifaces = SLPPropertyGet("net.slp.interfaces");
+ if (!ifaces || !*ifaces)
{
- if(SLPPropertyGet("net.slp.interfaces"))
+ G_SlpdProperty.updateIfaces = 1;
+ }
+ if(SLPIfaceGetInfo(ifaces, &G_SlpdProperty.ifaceInfo) == 0)
+ {
+ if(ifaces)
{
if(SLPIfaceSockaddrsToString(G_SlpdProperty.ifaceInfo.iface_addr,
G_SlpdProperty.ifaceInfo.iface_count,
@@ -137,39 +153,73 @@ int SLPDPropertyInit(const char* conffil
{
SLPPropertySet("net.slp.interfaces", myinterfaces);
xfree(myinterfaces);
+ ifaces = SLPPropertyGet("net.slp.interfaces");
}
}
}
- G_SlpdProperty.interfaces = SLPPropertyGet("net.slp.interfaces");
}
- G_SlpdProperty.interfacesLen = strlen(G_SlpdProperty.interfaces);
-
+ else
+ {
+ G_SlpdProperty.ifaceInfo.iface_count = SLP_MAX_IFACES;
+ if (SLPIfaceStringToSockaddrs(ifaces, G_SlpdProperty.ifaceInfo.iface_addr, &G_SlpdProperty.ifaceInfo.iface_count) != 0)
+ {
+ G_SlpdProperty.ifaceInfo.iface_count = 0;
+ }
+ }
+ G_SlpdProperty.interfaces = ifaces;
+ G_SlpdProperty.interfacesLen = ifaces ? strlen(ifaces) : 0;
+ /*----------------------------*/
+ /* Get out canonical hostname */
+ /*----------------------------*/
+ if(SLPNetGetThisHostname(&myname,0) == 0)
+ {
+ if (!myname && !G_SlpdProperty.myHostnameLen)
+ myname = xstrdup("127.0.0.1");
+ if (myname)
+ {
+ SLPPropertySet("net.slp.myHostname",myname);
+ xfree(myname);
+ G_SlpdProperty.myHostname = SLPPropertyGet("net.slp.myHostname");
+ G_SlpdProperty.myHostnameLen = strlen(G_SlpdProperty.myHostname);
+ }
+ }
+
/*---------------------------------------------------------*/
/* Set the value used internally as the url for this agent */
/*---------------------------------------------------------*/
/* 27 is the size of "service:directory-agent://(NULL)" */
if(SLPNetGetThisHostname(&myname,1) == 0)
{
- myurl = (char*)xmalloc(27 + strlen(myname));
- if(G_SlpdProperty.isDA)
- {
- strcpy(myurl,SLP_DA_SERVICE_TYPE);
- }
- else
- {
- strcpy(myurl,SLP_SA_SERVICE_TYPE);
- }
- strcat(myurl,"://");
- strcat(myurl,myname);
-
- SLPPropertySet("net.slp.agentUrl",myurl);
+ if (!myname && !G_SlpdProperty.myUrlLen)
+ myname = xstrdup("127.0.0.1");
+ if (myname)
+ {
+ if (!strncmp(myname, "127.", 4))
+ {
+ /* cannot run as DA if hostname is loopback */
+ G_SlpdProperty.isDA = 0;
+ }
+ myurl = (char*)xmalloc(27 + strlen(myname));
+ if(G_SlpdProperty.isDA)
+ {
+ strcpy(myurl,SLP_DA_SERVICE_TYPE);
+ }
+ else
+ {
+ strcpy(myurl,SLP_SA_SERVICE_TYPE);
+ }
+ strcat(myurl,"://");
+ strcat(myurl,myname);
+
+ SLPPropertySet("net.slp.agentUrl",myurl);
- G_SlpdProperty.myUrl = SLPPropertyGet("net.slp.agentUrl");
- G_SlpdProperty.myUrlLen = strlen(G_SlpdProperty.myUrl);
+ G_SlpdProperty.myUrl = SLPPropertyGet("net.slp.agentUrl");
+ G_SlpdProperty.myUrlLen = strlen(G_SlpdProperty.myUrl);
- xfree(myurl);
- xfree(myname);
+ xfree(myurl);
+ xfree(myname);
+ }
}
/*----------------------------------*/
--- ./slpd/slpd_property.h.orig 2002-06-11 17:25:40.000000000 +0000
+++ ./slpd/slpd_property.h 2006-11-16 16:19:30.000000000 +0000
@@ -61,6 +61,8 @@ typedef struct _SLPDProperty
{
int myUrlLen;
const char* myUrl;
+ int myHostnameLen;
+ const char* myHostname;
int useScopesLen;
const char* useScopes;
int DAAddressesLen;
@@ -69,6 +71,7 @@ typedef struct _SLPDProperty
SLPIfaceInfo ifaceInfo;
int interfacesLen;
const char* interfaces;
+ int updateIfaces;
int localeLen;
const char* locale;
int isBroadcastOnly;
--- ./slpd/slpd_regfile.c.orig 2002-03-19 23:52:15.000000000 +0000
+++ ./slpd/slpd_regfile.c 2006-11-16 16:19:30.000000000 +0000
@@ -153,6 +153,7 @@ int SLPDRegFileReadSrvReg(FILE* fd,
{
char* slider1;
char* slider2;
+ char* p;
char line[4096];
struct sockaddr_in peer;
@@ -175,6 +176,8 @@ int SLPDRegFileReadSrvReg(FILE* fd,
unsigned char* attrauth = 0;
int attrauthlen = 0;
#endif
+ int watchport = 0;
+ int watchflags = 0;
/*-------------------------------------------*/
@@ -212,6 +215,17 @@ int SLPDRegFileReadSrvReg(FILE* fd,
result = SLP_ERROR_INTERNAL_ERROR;
goto CLEANUP;
}
+
+ /* replace "$HOSTNAME" string in url */
+ while ((p = strchr(url, '$')) && !strncmp(p, "$HOSTNAME", 9))
+ {
+ char *_url = (char*)malloc(strlen(url) - 9 + G_SlpdProperty.myHostnameLen + 1);
+ strncpy(_url, url, p - url);
+ strncpy(_url + (p - url), G_SlpdProperty.myHostname, G_SlpdProperty.myHostnameLen);
+ strcpy(_url + (p - url) + G_SlpdProperty.myHostnameLen, url + (p - url) + 9);
+ free(url);
+ url = _url;
+ }
urllen = strlen(url);
/* derive srvtype from srvurl */
@@ -349,6 +363,22 @@ int SLPDRegFileReadSrvReg(FILE* fd,
}
}
}
+ else if(strncasecmp(slider1,"tcp-port",8) == 0 || strncasecmp(slider1,"watch-port-tcp",14) == 0)
+ {
+ slider2 = strchr(slider1,'=');
+ if (slider2) {
+ watchport = atoi(slider2 + 1);
+ watchflags |= SLP_REG_WATCH_TCP;
+ }
+ }
+ else if(strncasecmp(slider1,"watch-port-udp",14) == 0)
+ {
+ slider2 = strchr(slider1,'=');
+ if (slider2) {
+ watchport = atoi(slider2 + 1);
+ watchflags |= SLP_REG_WATCH_UDP;
+ }
+ }
else
{
/* line contains an attribute (slow but it works)*/
@@ -554,6 +584,8 @@ int SLPDRegFileReadSrvReg(FILE* fd,
peer.sin_addr.s_addr = htonl(LOOPBACK_ADDRESS);
result = SLPMessageParseBuffer(&peer,*buf,*msg);
(*msg)->body.srvreg.source = SLP_REG_SOURCE_STATIC;
+ (*msg)->body.srvreg.watchflags = watchflags ? (watchflags | SLP_REG_WATCH_DEAD) : 0;
+ (*msg)->body.srvreg.watchport = watchport;
CLEANUP:
--- ./slpd/slpd_socket.c.orig 2006-11-16 16:19:17.000000000 +0000
+++ ./slpd/slpd_socket.c 2006-11-16 16:19:30.000000000 +0000
@@ -412,6 +412,8 @@ SLPDSocket* SLPDSocketCreateBoundDatagra
sock->fd = socket(PF_INET, SOCK_DGRAM, 0);
if(sock->fd >=0)
{
+ if(myaddr != NULL)
+ sock->ifaddr.sin_addr = *myaddr;
if(BindSocketToInetAddr(sock->fd, bindaddr) == 0)
{
if(peeraddr != NULL)
@@ -479,6 +481,8 @@ SLPDSocket* SLPDSocketCreateListen(struc
sock->fd = socket(PF_INET, SOCK_STREAM, 0);
if(sock->fd >= 0)
{
+ if(peeraddr != NULL)
+ sock->ifaddr.sin_addr = *peeraddr;
if(BindSocketToInetAddr(sock->fd, peeraddr) >= 0)
{
if(listen(sock->fd,5) == 0)
--- ./slpd/slpd_socket.h.orig 2002-12-03 21:04:54.000000000 +0000
+++ ./slpd/slpd_socket.h 2006-11-16 16:19:30.000000000 +0000
@@ -97,6 +97,7 @@ typedef struct _SLPDSocket
int fd;
time_t age; /* in seconds */
int state;
+ struct sockaddr_in ifaddr; /* address of interface */
struct sockaddr_in peeraddr;
/* Incoming socket stuff */
--- ./slpd/slpd_spi.c.orig 2001-04-16 22:17:31.000000000 +0000
+++ ./slpd/slpd_spi.c 2006-11-16 16:19:30.000000000 +0000
@@ -68,6 +68,8 @@ int SLPDSpiInit(const char* spifile)
}
G_SlpdSpiHandle = SLPSpiOpen(spifile,1);
+ if (G_SlpdSpiHandle)
+ SLPSpiFill(G_SlpdSpiHandle);
return (G_SlpdSpiHandle == 0);
}
--- ./slptool/slptool.c.orig 2003-04-21 11:19:19.000000000 +0000
+++ ./slptool/slptool.c 2006-11-16 16:47:44.000000000 +0000
@@ -329,6 +329,20 @@ SLPBoolean mySrvUrlCallback( SLPHandle h
{
if(errcode == SLP_OK)
{
+ SLPToolCommandLine* cmdline = cookie;
+ if (cmdline->peerinfo)
+ {
+ char *peer = SLPGetPeer(hslp, srvurl);
+ if (peer)
+ {
+ printf("%s\t", peer);
+ SLPFree(peer);
+ }
+ else
+ {
+ printf("?\t");
+ }
+ }
printf("%s,%i\n",srvurl,lifetime);
}
@@ -350,7 +364,7 @@ void FindSrvs(SLPToolCommandLine* cmdlin
cmdline->scopes,
cmdline->cmdparam2,
mySrvUrlCallback,
- 0);
+ cmdline);
if(result != SLP_OK)
{
printf("errorcode: %i\n",result);
@@ -382,7 +396,7 @@ void FindSrvsUsingIFList(SLPToolCommandL
cmdline->scopes,
cmdline->cmdparam2,
mySrvUrlCallback,
- 0);
+ cmdline);
if(result != SLP_OK)
{
printf("errorcode: %i\n",result);
@@ -414,7 +428,7 @@ void UnicastFindSrvs(SLPToolCommandLine*
cmdline->scopes,
cmdline->cmdparam2,
mySrvUrlCallback,
- 0);
+ cmdline);
if(result != SLP_OK)
{
printf("errorcode: %i\n",result);
@@ -599,6 +613,11 @@ int ParseCommandLine(int argc,char* argv
return 1;
}
}
+ else if( strcasecmp(argv[i],"-p") == 0 ||
+ strcasecmp(argv[i],"--peerinfo") == 0 )
+ {
+ cmdline->peerinfo = SLP_TRUE;
+ }
else if(strcasecmp(argv[i],"findsrvs") == 0)
{
cmdline->cmd = FINDSRVS;
--- ./slptool/slptool.h.orig 2003-04-21 11:17:58.000000000 +0000
+++ ./slptool/slptool.h 2006-11-16 16:19:30.000000000 +0000
@@ -40,6 +40,8 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
/*=========================================================================*/
typedef enum _SLPToolCommand
@@ -78,6 +80,7 @@ typedef struct _SLPToolCommandLine
const char* cmdparam1;
const char* cmdparam2;
const char* cmdparam3;
+ SLPBoolean peerinfo;
}SLPToolCommandLine;