--- ./common/slp_property.c.orig 2011-01-18 11:03:59.000000000 +0000 +++ ./common/slp_property.c 2011-01-18 13:05:43.000000000 +0000 @@ -217,6 +217,7 @@ int SetDefaultValues() result |= SLPPropertySet("net.slp.isDABackup","false"); result |= SLPPropertySet("net.slp.DABackupInterval","900"); result |= SLPPropertySet("net.slp.DABackupLocalReg","false"); + result |= SLPPropertySet("net.slp.hardMTU","false"); return result; } --- ./etc/slp.conf.orig 2011-01-18 10:54:51.000000000 +0000 +++ ./etc/slp.conf 2011-01-18 13:05:02.000000000 +0000 @@ -156,6 +156,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 + # A list of IP address of network interfaces on which the DA/SA should listen # for slp requests. By default, slpd will use all interfaces. ;net.slp.interfaces = 1.2.3.4,1.2.3.5,1.2.3.6 --- ./slpd/slpd_incoming.c.orig 2011-01-18 13:12:40.000000000 +0000 +++ ./slpd/slpd_incoming.c 2011-01-18 13:14:09.000000000 +0000 @@ -94,6 +94,8 @@ void IncomingDatagramRead(SLPList* sockl truncate = SLP_MAX_DATAGRAM_SIZE; if (G_SlpdProperty.oversizedUDP) truncate = 0; + if (G_SlpdProperty.hardMTU) + truncate = SLP_MAX_DATAGRAM_SIZE - 28; switch (SLPDProcessMessage(&sock->peeraddr, sock->recvbuf, &(sock->sendbuf), --- ./slpd/slpd_process.c.orig 2011-01-18 11:49:46.000000000 +0000 +++ ./slpd/slpd_process.c 2011-01-18 13:05:19.000000000 +0000 @@ -313,6 +313,7 @@ int ProcessSrvRqst(SLPMessage message, SLPUrlEntry* urlentry; SLPDDatabaseSrvRqstResult* db = 0; int size = 0; + int truncated = 0; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ @@ -444,14 +445,18 @@ int ProcessSrvRqst(SLPMessage message, { for (i=0;iurlcount;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]; - if (urlentry->opaque == 0) + if (urlentry->opaque == 0) { size += urlentry->urllen + 6; /* 1 byte for reserved */ /* 2 bytes for lifetime */ @@ -462,6 +467,12 @@ int ProcessSrvRqst(SLPMessage message, { size += urlentry->opaquelen; } + if (G_SlpdProperty.hardMTU && truncate && size > truncate) + { + size = oldsize; + truncated = 1; + break; + } } } @@ -486,7 +497,7 @@ int ProcessSrvRqst(SLPMessage message, ToUINT24(result->start + 2, size); /*flags*/ ToUINT16(result->start + 5, - (size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0)); + (size > SLP_MAX_DATAGRAM_SIZE || truncated ? SLP_FLAG_OVERFLOW : 0)); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ @@ -514,8 +525,12 @@ int ProcessSrvRqst(SLPMessage message, for (i=0;iurlcount;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 */ + ToUINT16(result->start + 14 + message->header.langtaglen + 2, i); break; + } /* urlentry is the url from the db result */ urlentry = db->urlarray[i]; @@ -818,11 +833,14 @@ int ProcessSrvAck(SLPMessage message, /*-------------------------------------------------------------------------*/ int ProcessAttrRqst(SLPMessage message, SLPBuffer* sendbuf, - int errorcode) + int errorcode, + int truncate) /*-------------------------------------------------------------------------*/ { SLPDDatabaseAttrRqstResult* db = 0; int size = 0; + int truncated = 0; + int attrlistlen = 0; SLPBuffer result = *sendbuf; #ifdef ENABLE_SLPv2_SECURITY @@ -995,6 +1013,16 @@ int ProcessAttrRqst(SLPMessage message, size += opaqueauthlen; } #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; + } } /*-------------------*/ @@ -1018,7 +1046,7 @@ int ProcessAttrRqst(SLPMessage message, ToUINT24(result->start + 2,size); /*flags*/ ToUINT16(result->start + 5, - (size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0)); + (size > SLP_MAX_DATAGRAM_SIZE || truncated ? SLP_FLAG_OVERFLOW : 0)); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ @@ -1040,13 +1068,13 @@ int ProcessAttrRqst(SLPMessage message, if (errorcode == 0) { /* attr-list len */ - ToUINT16(result->curpos, db->attrlistlen); + ToUINT16(result->curpos, attrlistlen); result->curpos = result->curpos + 2; - if (db->attrlistlen) + if (attrlistlen) { - memcpy(result->curpos, db->attrlist, db->attrlistlen); + memcpy(result->curpos, db->attrlist, attrlistlen); } - result->curpos = result->curpos + db->attrlistlen; + result->curpos = result->curpos + attrlistlen; /* authentication block */ #ifdef ENABLE_SLPv2_SECURITY @@ -1157,10 +1185,13 @@ int ProcessDAAdvert(SLPMessage message, /*-------------------------------------------------------------------------*/ int ProcessSrvTypeRqst(SLPMessage message, SLPBuffer* sendbuf, - int errorcode) + int errorcode, + int truncate) /*-------------------------------------------------------------------------*/ { int size = 0; + int truncated = 0; + int typelistlen = 0; SLPDDatabaseSrvTypeRqstResult* db = 0; SLPBuffer result = *sendbuf; @@ -1230,6 +1261,15 @@ int ProcessSrvTypeRqst(SLPMessage messag 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; + } } @@ -1254,7 +1294,7 @@ int ProcessSrvTypeRqst(SLPMessage messag ToUINT24(result->start + 2,size); /*flags*/ ToUINT16(result->start + 5, - (size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0)); + (size > SLP_MAX_DATAGRAM_SIZE || truncated ? SLP_FLAG_OVERFLOW : 0)); /*ext offset*/ ToUINT24(result->start + 7,0); /*xid*/ @@ -1278,12 +1318,13 @@ int ProcessSrvTypeRqst(SLPMessage messag if (errorcode == 0) { /* length of srvtype-list */ - ToUINT16(result->curpos, db->srvtypelistlen); + ToUINT16(result->curpos, typelistlen); result->curpos += 2; - memcpy(result->curpos, - db->srvtypelist, - db->srvtypelistlen); - result->curpos += db->srvtypelistlen; + if (typelistlen) + memcpy(result->curpos, + db->srvtypelist, + typelistlen); + result->curpos += typelistlen; } @@ -1413,7 +1454,7 @@ int SLPDProcessMessage(struct sockaddr_i break; case SLP_FUNCT_ATTRRQST: - errorcode = ProcessAttrRqst(message,sendbuf, errorcode); + errorcode = ProcessAttrRqst(message,sendbuf, errorcode, truncate); break; case SLP_FUNCT_DAADVERT: @@ -1424,7 +1465,7 @@ int SLPDProcessMessage(struct sockaddr_i 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 2011-01-18 11:02:36.000000000 +0000 +++ ./slpd/slpd_property.c 2011-01-18 13:05:29.000000000 +0000 @@ -237,6 +237,7 @@ int SLPDPropertyInit(const char* conffil G_SlpdProperty.isDABackup = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.isDABackup")); G_SlpdProperty.DABackupInterval = SLPPropertyAsInteger(SLPPropertyGet("net.slp.DABackupInterval")); G_SlpdProperty.DABackupLocalReg = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.DABackupLocalReg")); + G_SlpdProperty.hardMTU = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.hardMTU")); return 0; } --- ./slpd/slpd_property.h.orig 2011-01-18 11:02:09.000000000 +0000 +++ ./slpd/slpd_property.h 2011-01-18 13:05:39.000000000 +0000 @@ -100,6 +100,7 @@ typedef struct _SLPDProperty int isDABackup; int DABackupInterval; int DABackupLocalReg; + int hardMTU; }SLPDProperty;