--- ./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 + +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 +#include +#include +#define ETIMEDOUT 110 +#define ENOTCONN 107 +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include + +#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   + * 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; isock_count; i++) + { + FD_SET(sockets->sock[i],&readfds); + if(sockets->sock[i] > highfd) + highfd = sockets->sock[i]; + } + for (i=0; isock_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; isock_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; isock_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 /*=========================================================================*/ 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 #include #include +#include +#include /*=========================================================================*/ typedef enum _SLPToolCommand @@ -78,6 +80,7 @@ typedef struct _SLPToolCommandLine const char* cmdparam1; const char* cmdparam2; const char* cmdparam3; + SLPBoolean peerinfo; }SLPToolCommandLine;