--- ./common/slp_property.c.orig 2014-02-18 17:14:52.119092941 +0000 +++ ./common/slp_property.c 2014-02-18 17:15:01.462092925 +0000 @@ -181,6 +181,8 @@ static int SetDefaultValues(void) {"net.slp.isDABackup", "false", 0}, {"net.slp.DABackupInterval", "900", 0}, {"net.slp.DABackupLocalReg", "false", 0}, + + {"net.slp.hardMTU", "false", 0}, }; int i; --- ./etc/slp.conf.orig 2014-02-18 17:14:52.109092941 +0000 +++ ./etc/slp.conf 2014-02-18 17:15:01.463092925 +0000 @@ -168,6 +168,12 @@ # A integer giving the network packet MTU in bytes. (Default is 1400) ;net.slp.MTU = 1400 +# make sure that UDP packets really are smaller than the MTU. Normally +# openslp will truncate packets so that they are a bit bigger than +# the MTU, as a workaround for bugs in old openslp implementations. +# (Default is false) +;net.slp.hardMTU = false + # # If operating as an SA or DA, this specifies the maximum number of interfaces # that can be active. (Default is 100) --- ./slpd/slpd_incoming.c.orig 2014-02-18 17:14:52.103092941 +0000 +++ ./slpd/slpd_incoming.c 2014-02-18 17:15:01.464092925 +0000 @@ -89,6 +89,8 @@ static void IncomingDatagramRead(SLPList truncate = G_SlpdProperty.MTU; if (G_SlpdProperty.oversizedUDP) truncate = 0; + if (G_SlpdProperty.hardMTU) + truncate = G_SlpdProperty.MTU - 28; if (!sock->sendbuf) /* Some of the error handling code expects a sendbuf to be available --- ./slpd/slpd_process.c.orig 2014-02-18 17:14:52.104092941 +0000 +++ ./slpd/slpd_process.c 2014-02-18 17:19:11.508092482 +0000 @@ -406,6 +406,7 @@ static int ProcessSrvRqst(SLPMessage * m SLPUrlEntry * urlentry; SLPDDatabaseSrvRqstResult * db = 0; size_t size = 0; + int truncated = 0; SLPBuffer result = *sendbuf; /* If errorcode is set, we can not be sure that message is good @@ -509,9 +510,14 @@ RESPOND: { for (i = 0; i < db->urlcount; i++) { + int oldsize = size; + /* check size limitation */ if (truncate && size > truncate) + { + truncated = 1; break; + } /* urlentry is the url from the db result */ urlentry = db->urlarray[i]; @@ -529,6 +535,12 @@ RESPOND: { size += urlentry->opaquelen; } + if (G_SlpdProperty.hardMTU && truncate && size > truncate) + { + size = oldsize; + truncated = 1; + break; + } } } @@ -552,7 +564,7 @@ RESPOND: PutUINT24(&result->curpos, size); /* flags */ - PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU? + PutUINT16(&result->curpos, (truncated || size > (size_t)G_SlpdProperty.MTU? SLP_FLAG_OVERFLOW: 0)); /* ext offset */ @@ -580,8 +592,12 @@ RESPOND: for (i = 0; i < db->urlcount; i++) { /* check size limitation */ - if (truncate && result->curpos - result->start > truncate) + if (result->curpos - result->start >= size) + { + /* reached size limit due to truncation. fix up url count */ + TO_UINT16(result->start + 14 + message->header.langtaglen + 2, i); break; + } /* urlentry is the url from the db result */ urlentry = db->urlarray[i]; @@ -880,10 +896,12 @@ static int ProcessSrvAck(SLPMessage * me * @internal */ static int ProcessAttrRqst(SLPMessage * message, SLPBuffer * sendbuf, - int errorcode) + int errorcode, int truncate) { SLPDDatabaseAttrRqstResult * db = 0; size_t size = 0; + int truncated = 1; + size_t attrlistlen = 0; SLPBuffer result = *sendbuf; #ifdef ENABLE_SLPv2_SECURITY @@ -1032,6 +1050,15 @@ RESPOND: } #endif + /* truncate if needed */ + attrlistlen = db->attrlistlen; + if (truncate && size > truncate && G_SlpdProperty.hardMTU) + { + attrlistlen = 0; + opaqueauth = 0; + size = message->header.langtaglen + 19; /* 14 bytes for header */ + truncated = 1; + } } /* alloc the buffer */ @@ -1054,7 +1081,7 @@ RESPOND: PutUINT24(&result->curpos, size); /* flags */ - PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU? + PutUINT16(&result->curpos, (truncated || size > (size_t)G_SlpdProperty.MTU? SLP_FLAG_OVERFLOW: 0)); /* ext offset */ @@ -1078,10 +1105,10 @@ RESPOND: if (errorcode == 0) { /* attr-list len */ - PutUINT16(&result->curpos, db->attrlistlen); - if (db->attrlistlen) - memcpy(result->curpos, db->attrlist, db->attrlistlen); - result->curpos += db->attrlistlen; + PutUINT16(&result->curpos, attrlistlen); + if (attrlistlen) + memcpy(result->curpos, db->attrlist, attrlistlen); + result->curpos += attrlistlen; /* authentication block */ #ifdef ENABLE_SLPv2_SECURITY @@ -1187,9 +1214,11 @@ RESPOND: * @internal */ static int ProcessSrvTypeRqst(SLPMessage * message, SLPBuffer * sendbuf, - int errorcode) + int errorcode, int truncate) { size_t size = 0; + int truncated = 0; + size_t typelistlen = 0; SLPDDatabaseSrvTypeRqstResult * db = 0; SLPBuffer result = *sendbuf; @@ -1233,7 +1262,18 @@ RESPOND: /* 2 bytes for error code */ /* 2 bytes for srvtype len */ if (errorcode == 0) + { size += db->srvtypelistlen; + typelistlen = db->srvtypelistlen; + + /* truncate result if needed */ + if (truncate && size > truncate && G_SlpdProperty.hardMTU) + { + typelistlen = 0; + size -= db->srvtypelistlen; + truncated = 1; + } + } /* Reallocate the result buffer */ result = SLPBufferRealloc(result, size); @@ -1255,7 +1295,7 @@ RESPOND: PutUINT24(&result->curpos, size); /* flags */ - PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU? + PutUINT16(&result->curpos, (truncated || size > (size_t)G_SlpdProperty.MTU? SLP_FLAG_OVERFLOW: 0)); /* ext offset */ @@ -1279,9 +1319,10 @@ RESPOND: if (errorcode == 0) { /* length of srvtype-list */ - PutUINT16(&result->curpos, db->srvtypelistlen); - memcpy(result->curpos, db->srvtypelist, db->srvtypelistlen); - result->curpos += db->srvtypelistlen; + PutUINT16(&result->curpos, typelistlen); + if (typelistlen) + memcpy(result->curpos, db->srvtypelist, typelistlen); + result->curpos += typelistlen; } FINISHED: @@ -1412,7 +1453,7 @@ int SLPDProcessMessage(struct sockaddr_s break; case SLP_FUNCT_ATTRRQST: - errorcode = ProcessAttrRqst(message, sendbuf, errorcode); + errorcode = ProcessAttrRqst(message, sendbuf, errorcode, truncate); break; case SLP_FUNCT_DAADVERT: @@ -1421,7 +1462,7 @@ int SLPDProcessMessage(struct sockaddr_s break; case SLP_FUNCT_SRVTYPERQST: - errorcode = ProcessSrvTypeRqst(message, sendbuf, errorcode); + errorcode = ProcessSrvTypeRqst(message, sendbuf, errorcode, truncate); break; case SLP_FUNCT_SAADVERT: --- ./slpd/slpd_property.c.orig 2014-02-18 17:14:52.112092941 +0000 +++ ./slpd/slpd_property.c 2014-02-18 17:15:01.465092925 +0000 @@ -250,6 +250,8 @@ void SLPDPropertyReinit(void) G_SlpdProperty.myHostname = SLPDGetCanonHostname(); G_SlpdProperty.myHostnameLen = strlen(G_SlpdProperty.myHostname); + G_SlpdProperty.hardMTU = SLPPropertyAsBoolean("net.slp.hardMTU"); + G_SlpdProperty.DASyncReg = SLPPropertyAsBoolean("net.slp.DASyncReg"); G_SlpdProperty.isDABackup = SLPPropertyAsBoolean("net.slp.isDABackup"); G_SlpdProperty.DABackupInterval = SLPPropertyAsInteger("net.slp.DABackupInterval"); --- ./slpd/slpd_property.h.orig 2014-02-18 17:14:52.113092941 +0000 +++ ./slpd/slpd_property.h 2014-02-18 17:15:01.465092925 +0000 @@ -117,6 +117,7 @@ typedef struct _SLPDProperty int MTU; int useDHCP; int oversizedUDP; + int hardMTU; int DASyncReg; int isDABackup;