add proper 2.6.25 support
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10865 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
bdd7f3c7ba
commit
127d15a775
|
@ -25,6 +25,9 @@ endif
|
|||
ifeq ($(LINUX_VERSION),2.6.24.2)
|
||||
LINUX_KERNEL_MD5SUM:=dd573a2fae55624ed92fa49c17583964
|
||||
endif
|
||||
ifeq ($(LINUX_VERSION),2.6.25)
|
||||
LINUX_KERNEL_MD5SUM:=db95a49a656a3247d4995a797d333153
|
||||
endif
|
||||
|
||||
# disable the md5sum check for unknown kernel versions
|
||||
LINUX_KERNEL_MD5SUM?=x
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,786 @@
|
|||
Index: linux-2.6.23/include/linux/LzmaDecode.h
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23/include/linux/LzmaDecode.h 2007-10-10 13:51:27.000000000 +0800
|
||||
@@ -0,0 +1,100 @@
|
||||
+/*
|
||||
+ LzmaDecode.h
|
||||
+ LZMA Decoder interface
|
||||
+
|
||||
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
|
||||
+ http://www.7-zip.org/
|
||||
+
|
||||
+ LZMA SDK is licensed under two licenses:
|
||||
+ 1) GNU Lesser General Public License (GNU LGPL)
|
||||
+ 2) Common Public License (CPL)
|
||||
+ It means that you can select one of these two licenses and
|
||||
+ follow rules of that license.
|
||||
+
|
||||
+ SPECIAL EXCEPTION:
|
||||
+ Igor Pavlov, as the author of this code, expressly permits you to
|
||||
+ statically or dynamically link your code (or bind by name) to the
|
||||
+ interfaces of this file without subjecting your linked code to the
|
||||
+ terms of the CPL or GNU LGPL. Any modifications or additions
|
||||
+ to this file, however, are subject to the LGPL or CPL terms.
|
||||
+*/
|
||||
+
|
||||
+#ifndef __LZMADECODE_H
|
||||
+#define __LZMADECODE_H
|
||||
+
|
||||
+/* #define _LZMA_IN_CB */
|
||||
+/* Use callback for input data */
|
||||
+
|
||||
+/* #define _LZMA_OUT_READ */
|
||||
+/* Use read function for output data */
|
||||
+
|
||||
+/* #define _LZMA_PROB32 */
|
||||
+/* It can increase speed on some 32-bit CPUs,
|
||||
+ but memory usage will be doubled in that case */
|
||||
+
|
||||
+/* #define _LZMA_LOC_OPT */
|
||||
+/* Enable local speed optimizations inside code */
|
||||
+
|
||||
+#ifndef UInt32
|
||||
+#ifdef _LZMA_UINT32_IS_ULONG
|
||||
+#define UInt32 unsigned long
|
||||
+#else
|
||||
+#define UInt32 unsigned int
|
||||
+#endif
|
||||
+#endif
|
||||
+
|
||||
+#ifdef _LZMA_PROB32
|
||||
+#define CProb UInt32
|
||||
+#else
|
||||
+#define CProb unsigned short
|
||||
+#endif
|
||||
+
|
||||
+#define LZMA_RESULT_OK 0
|
||||
+#define LZMA_RESULT_DATA_ERROR 1
|
||||
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
|
||||
+
|
||||
+#ifdef _LZMA_IN_CB
|
||||
+typedef struct _ILzmaInCallback
|
||||
+{
|
||||
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
|
||||
+} ILzmaInCallback;
|
||||
+#endif
|
||||
+
|
||||
+#define LZMA_BASE_SIZE 1846
|
||||
+#define LZMA_LIT_SIZE 768
|
||||
+
|
||||
+/*
|
||||
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
|
||||
+bufferSize += 100 in case of _LZMA_OUT_READ
|
||||
+by default CProb is unsigned short,
|
||||
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
|
||||
+*/
|
||||
+
|
||||
+#ifdef _LZMA_OUT_READ
|
||||
+int LzmaDecoderInit(
|
||||
+ unsigned char *buffer, UInt32 bufferSize,
|
||||
+ int lc, int lp, int pb,
|
||||
+ unsigned char *dictionary, UInt32 dictionarySize,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ ILzmaInCallback *inCallback
|
||||
+ #else
|
||||
+ unsigned char *inStream, UInt32 inSize
|
||||
+ #endif
|
||||
+);
|
||||
+#endif
|
||||
+
|
||||
+int LzmaDecode(
|
||||
+ unsigned char *buffer,
|
||||
+ #ifndef _LZMA_OUT_READ
|
||||
+ UInt32 bufferSize,
|
||||
+ int lc, int lp, int pb,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ ILzmaInCallback *inCallback,
|
||||
+ #else
|
||||
+ unsigned char *inStream, UInt32 inSize,
|
||||
+ #endif
|
||||
+ #endif
|
||||
+ unsigned char *outStream, UInt32 outSize,
|
||||
+ UInt32 *outSizeProcessed);
|
||||
+
|
||||
+#endif
|
||||
Index: linux-2.6.23/lib/LzmaDecode.c
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23/lib/LzmaDecode.c 2007-10-10 13:51:27.000000000 +0800
|
||||
@@ -0,0 +1,663 @@
|
||||
+/*
|
||||
+ LzmaDecode.c
|
||||
+ LZMA Decoder
|
||||
+
|
||||
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
|
||||
+ http://www.7-zip.org/
|
||||
+
|
||||
+ LZMA SDK is licensed under two licenses:
|
||||
+ 1) GNU Lesser General Public License (GNU LGPL)
|
||||
+ 2) Common Public License (CPL)
|
||||
+ It means that you can select one of these two licenses and
|
||||
+ follow rules of that license.
|
||||
+
|
||||
+ SPECIAL EXCEPTION:
|
||||
+ Igor Pavlov, as the author of this code, expressly permits you to
|
||||
+ statically or dynamically link your code (or bind by name) to the
|
||||
+ interfaces of this file without subjecting your linked code to the
|
||||
+ terms of the CPL or GNU LGPL. Any modifications or additions
|
||||
+ to this file, however, are subject to the LGPL or CPL terms.
|
||||
+*/
|
||||
+
|
||||
+#include <linux/LzmaDecode.h>
|
||||
+
|
||||
+#ifndef Byte
|
||||
+#define Byte unsigned char
|
||||
+#endif
|
||||
+
|
||||
+#define kNumTopBits 24
|
||||
+#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||
+
|
||||
+#define kNumBitModelTotalBits 11
|
||||
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
+#define kNumMoveBits 5
|
||||
+
|
||||
+typedef struct _CRangeDecoder
|
||||
+{
|
||||
+ Byte *Buffer;
|
||||
+ Byte *BufferLim;
|
||||
+ UInt32 Range;
|
||||
+ UInt32 Code;
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ ILzmaInCallback *InCallback;
|
||||
+ int Result;
|
||||
+ #endif
|
||||
+ int ExtraBytes;
|
||||
+} CRangeDecoder;
|
||||
+
|
||||
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
|
||||
+{
|
||||
+ if (rd->Buffer == rd->BufferLim)
|
||||
+ {
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ UInt32 size;
|
||||
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
|
||||
+ rd->BufferLim = rd->Buffer + size;
|
||||
+ if (size == 0)
|
||||
+ #endif
|
||||
+ {
|
||||
+ rd->ExtraBytes = 1;
|
||||
+ return 0xFF;
|
||||
+ }
|
||||
+ }
|
||||
+ return (*rd->Buffer++);
|
||||
+}
|
||||
+
|
||||
+/* #define ReadByte (*rd->Buffer++) */
|
||||
+#define ReadByte (RangeDecoderReadByte(rd))
|
||||
+
|
||||
+void RangeDecoderInit(CRangeDecoder *rd,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ ILzmaInCallback *inCallback
|
||||
+ #else
|
||||
+ Byte *stream, UInt32 bufferSize
|
||||
+ #endif
|
||||
+ )
|
||||
+{
|
||||
+ int i;
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ rd->InCallback = inCallback;
|
||||
+ rd->Buffer = rd->BufferLim = 0;
|
||||
+ #else
|
||||
+ rd->Buffer = stream;
|
||||
+ rd->BufferLim = stream + bufferSize;
|
||||
+ #endif
|
||||
+ rd->ExtraBytes = 0;
|
||||
+ rd->Code = 0;
|
||||
+ rd->Range = (0xFFFFFFFF);
|
||||
+ for(i = 0; i < 5; i++)
|
||||
+ rd->Code = (rd->Code << 8) | ReadByte;
|
||||
+}
|
||||
+
|
||||
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
|
||||
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
|
||||
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
|
||||
+
|
||||
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
|
||||
+{
|
||||
+ RC_INIT_VAR
|
||||
+ UInt32 result = 0;
|
||||
+ int i;
|
||||
+ for (i = numTotalBits; i > 0; i--)
|
||||
+ {
|
||||
+ /* UInt32 t; */
|
||||
+ range >>= 1;
|
||||
+
|
||||
+ result <<= 1;
|
||||
+ if (code >= range)
|
||||
+ {
|
||||
+ code -= range;
|
||||
+ result |= 1;
|
||||
+ }
|
||||
+ /*
|
||||
+ t = (code - range) >> 31;
|
||||
+ t &= 1;
|
||||
+ code -= range & (t - 1);
|
||||
+ result = (result + result) | (1 - t);
|
||||
+ */
|
||||
+ RC_NORMALIZE
|
||||
+ }
|
||||
+ RC_FLUSH_VAR
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
|
||||
+{
|
||||
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
|
||||
+ if (rd->Code < bound)
|
||||
+ {
|
||||
+ rd->Range = bound;
|
||||
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
|
||||
+ if (rd->Range < kTopValue)
|
||||
+ {
|
||||
+ rd->Code = (rd->Code << 8) | ReadByte;
|
||||
+ rd->Range <<= 8;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ rd->Range -= bound;
|
||||
+ rd->Code -= bound;
|
||||
+ *prob -= (*prob) >> kNumMoveBits;
|
||||
+ if (rd->Range < kTopValue)
|
||||
+ {
|
||||
+ rd->Code = (rd->Code << 8) | ReadByte;
|
||||
+ rd->Range <<= 8;
|
||||
+ }
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#define RC_GET_BIT2(prob, mi, A0, A1) \
|
||||
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
|
||||
+ if (code < bound) \
|
||||
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
|
||||
+ else \
|
||||
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
|
||||
+ RC_NORMALIZE
|
||||
+
|
||||
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
|
||||
+
|
||||
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
||||
+{
|
||||
+ int mi = 1;
|
||||
+ int i;
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_INIT_VAR
|
||||
+ #endif
|
||||
+ for(i = numLevels; i > 0; i--)
|
||||
+ {
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ CProb *prob = probs + mi;
|
||||
+ RC_GET_BIT(prob, mi)
|
||||
+ #else
|
||||
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
|
||||
+ #endif
|
||||
+ }
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_FLUSH_VAR
|
||||
+ #endif
|
||||
+ return mi - (1 << numLevels);
|
||||
+}
|
||||
+
|
||||
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
||||
+{
|
||||
+ int mi = 1;
|
||||
+ int i;
|
||||
+ int symbol = 0;
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_INIT_VAR
|
||||
+ #endif
|
||||
+ for(i = 0; i < numLevels; i++)
|
||||
+ {
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ CProb *prob = probs + mi;
|
||||
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
|
||||
+ #else
|
||||
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
|
||||
+ mi = mi + mi + bit;
|
||||
+ symbol |= (bit << i);
|
||||
+ #endif
|
||||
+ }
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_FLUSH_VAR
|
||||
+ #endif
|
||||
+ return symbol;
|
||||
+}
|
||||
+
|
||||
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
|
||||
+{
|
||||
+ int symbol = 1;
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_INIT_VAR
|
||||
+ #endif
|
||||
+ do
|
||||
+ {
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ CProb *prob = probs + symbol;
|
||||
+ RC_GET_BIT(prob, symbol)
|
||||
+ #else
|
||||
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
||||
+ #endif
|
||||
+ }
|
||||
+ while (symbol < 0x100);
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_FLUSH_VAR
|
||||
+ #endif
|
||||
+ return symbol;
|
||||
+}
|
||||
+
|
||||
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
|
||||
+{
|
||||
+ int symbol = 1;
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_INIT_VAR
|
||||
+ #endif
|
||||
+ do
|
||||
+ {
|
||||
+ int bit;
|
||||
+ int matchBit = (matchByte >> 7) & 1;
|
||||
+ matchByte <<= 1;
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ {
|
||||
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
|
||||
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
|
||||
+ }
|
||||
+ #else
|
||||
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
|
||||
+ symbol = (symbol << 1) | bit;
|
||||
+ #endif
|
||||
+ if (matchBit != bit)
|
||||
+ {
|
||||
+ while (symbol < 0x100)
|
||||
+ {
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ CProb *prob = probs + symbol;
|
||||
+ RC_GET_BIT(prob, symbol)
|
||||
+ #else
|
||||
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
||||
+ #endif
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ while (symbol < 0x100);
|
||||
+ #ifdef _LZMA_LOC_OPT
|
||||
+ RC_FLUSH_VAR
|
||||
+ #endif
|
||||
+ return symbol;
|
||||
+}
|
||||
+
|
||||
+#define kNumPosBitsMax 4
|
||||
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
||||
+
|
||||
+#define kLenNumLowBits 3
|
||||
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
||||
+#define kLenNumMidBits 3
|
||||
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
||||
+#define kLenNumHighBits 8
|
||||
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
||||
+
|
||||
+#define LenChoice 0
|
||||
+#define LenChoice2 (LenChoice + 1)
|
||||
+#define LenLow (LenChoice2 + 1)
|
||||
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
||||
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
||||
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
||||
+
|
||||
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
|
||||
+{
|
||||
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
|
||||
+ return RangeDecoderBitTreeDecode(p + LenLow +
|
||||
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
|
||||
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
|
||||
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
|
||||
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
|
||||
+ return kLenNumLowSymbols + kLenNumMidSymbols +
|
||||
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
|
||||
+}
|
||||
+
|
||||
+#define kNumStates 12
|
||||
+
|
||||
+#define kStartPosModelIndex 4
|
||||
+#define kEndPosModelIndex 14
|
||||
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
||||
+
|
||||
+#define kNumPosSlotBits 6
|
||||
+#define kNumLenToPosStates 4
|
||||
+
|
||||
+#define kNumAlignBits 4
|
||||
+#define kAlignTableSize (1 << kNumAlignBits)
|
||||
+
|
||||
+#define kMatchMinLen 2
|
||||
+
|
||||
+#define IsMatch 0
|
||||
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
||||
+#define IsRepG0 (IsRep + kNumStates)
|
||||
+#define IsRepG1 (IsRepG0 + kNumStates)
|
||||
+#define IsRepG2 (IsRepG1 + kNumStates)
|
||||
+#define IsRep0Long (IsRepG2 + kNumStates)
|
||||
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
||||
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
||||
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
||||
+#define LenCoder (Align + kAlignTableSize)
|
||||
+#define RepLenCoder (LenCoder + kNumLenProbs)
|
||||
+#define Literal (RepLenCoder + kNumLenProbs)
|
||||
+
|
||||
+#if Literal != LZMA_BASE_SIZE
|
||||
+StopCompilingDueBUG
|
||||
+#endif
|
||||
+
|
||||
+#ifdef _LZMA_OUT_READ
|
||||
+
|
||||
+typedef struct _LzmaVarState
|
||||
+{
|
||||
+ CRangeDecoder RangeDecoder;
|
||||
+ Byte *Dictionary;
|
||||
+ UInt32 DictionarySize;
|
||||
+ UInt32 DictionaryPos;
|
||||
+ UInt32 GlobalPos;
|
||||
+ UInt32 Reps[4];
|
||||
+ int lc;
|
||||
+ int lp;
|
||||
+ int pb;
|
||||
+ int State;
|
||||
+ int PreviousIsMatch;
|
||||
+ int RemainLen;
|
||||
+} LzmaVarState;
|
||||
+
|
||||
+int LzmaDecoderInit(
|
||||
+ unsigned char *buffer, UInt32 bufferSize,
|
||||
+ int lc, int lp, int pb,
|
||||
+ unsigned char *dictionary, UInt32 dictionarySize,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ ILzmaInCallback *inCallback
|
||||
+ #else
|
||||
+ unsigned char *inStream, UInt32 inSize
|
||||
+ #endif
|
||||
+ )
|
||||
+{
|
||||
+ LzmaVarState *vs = (LzmaVarState *)buffer;
|
||||
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
|
||||
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
|
||||
+ UInt32 i;
|
||||
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
|
||||
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
|
||||
+ vs->Dictionary = dictionary;
|
||||
+ vs->DictionarySize = dictionarySize;
|
||||
+ vs->DictionaryPos = 0;
|
||||
+ vs->GlobalPos = 0;
|
||||
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
|
||||
+ vs->lc = lc;
|
||||
+ vs->lp = lp;
|
||||
+ vs->pb = pb;
|
||||
+ vs->State = 0;
|
||||
+ vs->PreviousIsMatch = 0;
|
||||
+ vs->RemainLen = 0;
|
||||
+ dictionary[dictionarySize - 1] = 0;
|
||||
+ for (i = 0; i < numProbs; i++)
|
||||
+ p[i] = kBitModelTotal >> 1;
|
||||
+ RangeDecoderInit(&vs->RangeDecoder,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ inCallback
|
||||
+ #else
|
||||
+ inStream, inSize
|
||||
+ #endif
|
||||
+ );
|
||||
+ return LZMA_RESULT_OK;
|
||||
+}
|
||||
+
|
||||
+int LzmaDecode(unsigned char *buffer,
|
||||
+ unsigned char *outStream, UInt32 outSize,
|
||||
+ UInt32 *outSizeProcessed)
|
||||
+{
|
||||
+ LzmaVarState *vs = (LzmaVarState *)buffer;
|
||||
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
|
||||
+ CRangeDecoder rd = vs->RangeDecoder;
|
||||
+ int state = vs->State;
|
||||
+ int previousIsMatch = vs->PreviousIsMatch;
|
||||
+ Byte previousByte;
|
||||
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
||||
+ UInt32 nowPos = 0;
|
||||
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
|
||||
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
|
||||
+ int lc = vs->lc;
|
||||
+ int len = vs->RemainLen;
|
||||
+ UInt32 globalPos = vs->GlobalPos;
|
||||
+
|
||||
+ Byte *dictionary = vs->Dictionary;
|
||||
+ UInt32 dictionarySize = vs->DictionarySize;
|
||||
+ UInt32 dictionaryPos = vs->DictionaryPos;
|
||||
+
|
||||
+ if (len == -1)
|
||||
+ {
|
||||
+ *outSizeProcessed = 0;
|
||||
+ return LZMA_RESULT_OK;
|
||||
+ }
|
||||
+
|
||||
+ while(len > 0 && nowPos < outSize)
|
||||
+ {
|
||||
+ UInt32 pos = dictionaryPos - rep0;
|
||||
+ if (pos >= dictionarySize)
|
||||
+ pos += dictionarySize;
|
||||
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
||||
+ if (++dictionaryPos == dictionarySize)
|
||||
+ dictionaryPos = 0;
|
||||
+ len--;
|
||||
+ }
|
||||
+ if (dictionaryPos == 0)
|
||||
+ previousByte = dictionary[dictionarySize - 1];
|
||||
+ else
|
||||
+ previousByte = dictionary[dictionaryPos - 1];
|
||||
+#else
|
||||
+
|
||||
+int LzmaDecode(
|
||||
+ Byte *buffer, UInt32 bufferSize,
|
||||
+ int lc, int lp, int pb,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ ILzmaInCallback *inCallback,
|
||||
+ #else
|
||||
+ unsigned char *inStream, UInt32 inSize,
|
||||
+ #endif
|
||||
+ unsigned char *outStream, UInt32 outSize,
|
||||
+ UInt32 *outSizeProcessed)
|
||||
+{
|
||||
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
|
||||
+ CProb *p = (CProb *)buffer;
|
||||
+ CRangeDecoder rd;
|
||||
+ UInt32 i;
|
||||
+ int state = 0;
|
||||
+ int previousIsMatch = 0;
|
||||
+ Byte previousByte = 0;
|
||||
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
||||
+ UInt32 nowPos = 0;
|
||||
+ UInt32 posStateMask = (1 << pb) - 1;
|
||||
+ UInt32 literalPosMask = (1 << lp) - 1;
|
||||
+ int len = 0;
|
||||
+ if (bufferSize < numProbs * sizeof(CProb))
|
||||
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
|
||||
+ for (i = 0; i < numProbs; i++)
|
||||
+ p[i] = kBitModelTotal >> 1;
|
||||
+ RangeDecoderInit(&rd,
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ inCallback
|
||||
+ #else
|
||||
+ inStream, inSize
|
||||
+ #endif
|
||||
+ );
|
||||
+#endif
|
||||
+
|
||||
+ *outSizeProcessed = 0;
|
||||
+ while(nowPos < outSize)
|
||||
+ {
|
||||
+ int posState = (int)(
|
||||
+ (nowPos
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ + globalPos
|
||||
+ #endif
|
||||
+ )
|
||||
+ & posStateMask);
|
||||
+ #ifdef _LZMA_IN_CB
|
||||
+ if (rd.Result != LZMA_RESULT_OK)
|
||||
+ return rd.Result;
|
||||
+ #endif
|
||||
+ if (rd.ExtraBytes != 0)
|
||||
+ return LZMA_RESULT_DATA_ERROR;
|
||||
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
||||
+ {
|
||||
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
|
||||
+ (((
|
||||
+ (nowPos
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ + globalPos
|
||||
+ #endif
|
||||
+ )
|
||||
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
||||
+
|
||||
+ if (state < 4) state = 0;
|
||||
+ else if (state < 10) state -= 3;
|
||||
+ else state -= 6;
|
||||
+ if (previousIsMatch)
|
||||
+ {
|
||||
+ Byte matchByte;
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ UInt32 pos = dictionaryPos - rep0;
|
||||
+ if (pos >= dictionarySize)
|
||||
+ pos += dictionarySize;
|
||||
+ matchByte = dictionary[pos];
|
||||
+ #else
|
||||
+ matchByte = outStream[nowPos - rep0];
|
||||
+ #endif
|
||||
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
|
||||
+ previousIsMatch = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ previousByte = LzmaLiteralDecode(probs, &rd);
|
||||
+ outStream[nowPos++] = previousByte;
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ dictionary[dictionaryPos] = previousByte;
|
||||
+ if (++dictionaryPos == dictionarySize)
|
||||
+ dictionaryPos = 0;
|
||||
+ #endif
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ previousIsMatch = 1;
|
||||
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
|
||||
+ {
|
||||
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
|
||||
+ {
|
||||
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
||||
+ {
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ UInt32 pos;
|
||||
+ #endif
|
||||
+ if (
|
||||
+ (nowPos
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ + globalPos
|
||||
+ #endif
|
||||
+ )
|
||||
+ == 0)
|
||||
+ return LZMA_RESULT_DATA_ERROR;
|
||||
+ state = state < 7 ? 9 : 11;
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ pos = dictionaryPos - rep0;
|
||||
+ if (pos >= dictionarySize)
|
||||
+ pos += dictionarySize;
|
||||
+ previousByte = dictionary[pos];
|
||||
+ dictionary[dictionaryPos] = previousByte;
|
||||
+ if (++dictionaryPos == dictionarySize)
|
||||
+ dictionaryPos = 0;
|
||||
+ #else
|
||||
+ previousByte = outStream[nowPos - rep0];
|
||||
+ #endif
|
||||
+ outStream[nowPos++] = previousByte;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ UInt32 distance;
|
||||
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
|
||||
+ distance = rep1;
|
||||
+ else
|
||||
+ {
|
||||
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
|
||||
+ distance = rep2;
|
||||
+ else
|
||||
+ {
|
||||
+ distance = rep3;
|
||||
+ rep3 = rep2;
|
||||
+ }
|
||||
+ rep2 = rep1;
|
||||
+ }
|
||||
+ rep1 = rep0;
|
||||
+ rep0 = distance;
|
||||
+ }
|
||||
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
|
||||
+ state = state < 7 ? 8 : 11;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ int posSlot;
|
||||
+ rep3 = rep2;
|
||||
+ rep2 = rep1;
|
||||
+ rep1 = rep0;
|
||||
+ state = state < 7 ? 7 : 10;
|
||||
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
|
||||
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
|
||||
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
||||
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
|
||||
+ if (posSlot >= kStartPosModelIndex)
|
||||
+ {
|
||||
+ int numDirectBits = ((posSlot >> 1) - 1);
|
||||
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
|
||||
+ if (posSlot < kEndPosModelIndex)
|
||||
+ {
|
||||
+ rep0 += RangeDecoderReverseBitTreeDecode(
|
||||
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
|
||||
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
|
||||
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ rep0 = posSlot;
|
||||
+ rep0++;
|
||||
+ }
|
||||
+ if (rep0 == (UInt32)(0))
|
||||
+ {
|
||||
+ /* it's for stream version */
|
||||
+ len = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (rep0 > nowPos
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ + globalPos
|
||||
+ #endif
|
||||
+ )
|
||||
+ {
|
||||
+ return LZMA_RESULT_DATA_ERROR;
|
||||
+ }
|
||||
+ len += kMatchMinLen;
|
||||
+ do
|
||||
+ {
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ UInt32 pos = dictionaryPos - rep0;
|
||||
+ if (pos >= dictionarySize)
|
||||
+ pos += dictionarySize;
|
||||
+ previousByte = dictionary[pos];
|
||||
+ dictionary[dictionaryPos] = previousByte;
|
||||
+ if (++dictionaryPos == dictionarySize)
|
||||
+ dictionaryPos = 0;
|
||||
+ #else
|
||||
+ previousByte = outStream[nowPos - rep0];
|
||||
+ #endif
|
||||
+ outStream[nowPos++] = previousByte;
|
||||
+ len--;
|
||||
+ }
|
||||
+ while(len > 0 && nowPos < outSize);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ #ifdef _LZMA_OUT_READ
|
||||
+ vs->RangeDecoder = rd;
|
||||
+ vs->DictionaryPos = dictionaryPos;
|
||||
+ vs->GlobalPos = globalPos + nowPos;
|
||||
+ vs->Reps[0] = rep0;
|
||||
+ vs->Reps[1] = rep1;
|
||||
+ vs->Reps[2] = rep2;
|
||||
+ vs->Reps[3] = rep3;
|
||||
+ vs->State = state;
|
||||
+ vs->PreviousIsMatch = previousIsMatch;
|
||||
+ vs->RemainLen = len;
|
||||
+ #endif
|
||||
+
|
||||
+ *outSizeProcessed = nowPos;
|
||||
+ return LZMA_RESULT_OK;
|
||||
+}
|
||||
Index: linux-2.6.23/lib/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/lib/Makefile 2007-10-10 13:50:24.000000000 +0800
|
||||
+++ linux-2.6.23/lib/Makefile 2007-10-10 13:51:53.000000000 +0800
|
||||
@@ -13,7 +13,7 @@
|
||||
lib-y += kobject.o kref.o kobject_uevent.o klist.o
|
||||
|
||||
obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
|
||||
- bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
|
||||
+ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o LzmaDecode.o
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
|
||||
CFLAGS_kobject.o += -DDEBUG
|
|
@ -0,0 +1,109 @@
|
|||
Index: linux-2.6.23-rc6/fs/squashfs/inode.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/squashfs/inode.c 2007-09-21 16:23:55.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/squashfs/inode.c 2007-09-21 16:23:56.000000000 +0800
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006
|
||||
* Phillip Lougher <phillip@lougher.org.uk>
|
||||
*
|
||||
+ * LZMA decompressor support added by Oleg I. Vdovikin
|
||||
+ * Copyright (c) 2005 Oleg I.Vdovikin <oleg@cs.msu.su>
|
||||
+ *
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2,
|
||||
@@ -21,6 +24,7 @@
|
||||
* inode.c
|
||||
*/
|
||||
|
||||
+#define SQUASHFS_LZMA
|
||||
#include <linux/types.h>
|
||||
#include <linux/squashfs_fs.h>
|
||||
#include <linux/module.h>
|
||||
@@ -44,6 +48,19 @@
|
||||
|
||||
#include "squashfs.h"
|
||||
|
||||
+#ifdef SQUASHFS_LZMA
|
||||
+#include <linux/LzmaDecode.h>
|
||||
+
|
||||
+/* default LZMA settings, should be in sync with mksquashfs */
|
||||
+#define LZMA_LC 3
|
||||
+#define LZMA_LP 0
|
||||
+#define LZMA_PB 2
|
||||
+
|
||||
+#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \
|
||||
+ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb))
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
static void squashfs_put_super(struct super_block *);
|
||||
static int squashfs_statfs(struct dentry *, struct kstatfs *);
|
||||
static int squashfs_symlink_readpage(struct file *file, struct page *page);
|
||||
@@ -64,7 +81,11 @@
|
||||
const char *, void *, struct vfsmount *);
|
||||
|
||||
|
||||
+#ifdef SQUASHFS_LZMA
|
||||
+static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE];
|
||||
+#else
|
||||
static z_stream stream;
|
||||
+#endif
|
||||
|
||||
static struct file_system_type squashfs_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -249,6 +270,15 @@
|
||||
if (compressed) {
|
||||
int zlib_err;
|
||||
|
||||
+#ifdef SQUASHFS_LZMA
|
||||
+ if ((zlib_err = LzmaDecode(lzma_workspace,
|
||||
+ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB,
|
||||
+ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK)
|
||||
+ {
|
||||
+ ERROR("lzma returned unexpected result 0x%x\n", zlib_err);
|
||||
+ bytes = 0;
|
||||
+ }
|
||||
+#else
|
||||
stream.next_in = c_buffer;
|
||||
stream.avail_in = c_byte;
|
||||
stream.next_out = buffer;
|
||||
@@ -263,7 +293,7 @@
|
||||
bytes = 0;
|
||||
} else
|
||||
bytes = stream.total_out;
|
||||
-
|
||||
+#endif
|
||||
up(&msblk->read_data_mutex);
|
||||
}
|
||||
|
||||
@@ -2045,15 +2075,19 @@
|
||||
printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
|
||||
"Phillip Lougher\n");
|
||||
|
||||
+#ifndef SQUASHFS_LZMA
|
||||
if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
|
||||
ERROR("Failed to allocate zlib workspace\n");
|
||||
destroy_inodecache();
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
+#endif
|
||||
|
||||
if ((err = register_filesystem(&squashfs_fs_type))) {
|
||||
+#ifndef SQUASHFS_LZMA
|
||||
vfree(stream.workspace);
|
||||
+#endif
|
||||
destroy_inodecache();
|
||||
}
|
||||
|
||||
@@ -2064,7 +2098,9 @@
|
||||
|
||||
static void __exit exit_squashfs_fs(void)
|
||||
{
|
||||
+#ifndef SQUASHFS_LZMA
|
||||
vfree(stream.workspace);
|
||||
+#endif
|
||||
unregister_filesystem(&squashfs_fs_type);
|
||||
destroy_inodecache();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
Index: linux-2.6.23-rc6/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/Makefile 2007-09-21 16:23:55.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/Makefile 2007-09-21 16:23:56.000000000 +0800
|
||||
@@ -508,6 +508,9 @@
|
||||
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
|
||||
CHECKFLAGS += $(NOSTDINC_FLAGS)
|
||||
|
||||
+# improve gcc optimization
|
||||
+CFLAGS += $(call cc-option,-funit-at-a-time,)
|
||||
+
|
||||
# warn about C99 declaration after statement
|
||||
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
--- linux-2.6.24/fs/squashfs/inode.c 2008-01-28 23:38:13.000000000 +0100
|
||||
+++ linux-2.6.24-owrt/fs/squashfs/inode.c 2008-01-28 23:43:18.000000000 +0100
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/exportfs.h>
|
||||
#include <linux/squashfs_fs_sb.h>
|
||||
#include <linux/squashfs_fs_i.h>
|
||||
#include <linux/buffer_head.h>
|
||||
@@ -2089,7 +2090,7 @@
|
||||
}
|
||||
|
||||
|
||||
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
|
||||
+static void init_once(struct kmem_cache * cachep, void *foo)
|
||||
{
|
||||
struct squashfs_inode_info *ei = foo;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
Index: linux-2.6.23/include/asm-mips/system.h
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/include/asm-mips/system.h 2007-10-10 04:31:38.000000000 +0800
|
||||
+++ linux-2.6.23/include/asm-mips/system.h 2007-10-10 13:52:24.000000000 +0800
|
||||
@@ -181,7 +181,7 @@
|
||||
if something tries to do an invalid xchg(). */
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||
+static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 4:
|
|
@ -0,0 +1,38 @@
|
|||
Index: linux-2.6.23-rc6/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/chips/cfi_cmdset_0002.c 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/chips/cfi_cmdset_0002.c 2007-09-21 16:23:57.000000000 +0800
|
||||
@@ -51,6 +51,7 @@
|
||||
#define SST49LF040B 0x0050
|
||||
#define SST49LF008A 0x005a
|
||||
#define AT49BV6416 0x00d6
|
||||
+#define MANUFACTURER_SAMSUNG 0x00ec
|
||||
|
||||
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
||||
@@ -294,12 +295,19 @@
|
||||
|
||||
if (extp->MajorVersion != '1' ||
|
||||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
|
||||
- printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||
- "version %c.%c.\n", extp->MajorVersion,
|
||||
- extp->MinorVersion);
|
||||
- kfree(extp);
|
||||
- kfree(mtd);
|
||||
- return NULL;
|
||||
+ if (cfi->mfr == MANUFACTURER_SAMSUNG &&
|
||||
+ (extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
|
||||
+ printk(KERN_NOTICE " Newer Samsung flash detected, "
|
||||
+ "should be compatibile with Amd/Fujitsu.\n");
|
||||
+ }
|
||||
+ else {
|
||||
+ printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||
+ "version %c.%c.\n", extp->MajorVersion,
|
||||
+ extp->MinorVersion);
|
||||
+ kfree(extp);
|
||||
+ kfree(mtd);
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Install our own private info structure */
|
|
@ -0,0 +1,171 @@
|
|||
Index: linux-2.6.23-rc6/drivers/mtd/chips/cfi_cmdset_0001.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/chips/cfi_cmdset_0001.c 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/chips/cfi_cmdset_0001.c 2007-09-21 16:23:57.000000000 +0800
|
||||
@@ -933,7 +933,7 @@
|
||||
|
||||
static int __xipram xip_wait_for_operation(
|
||||
struct map_info *map, struct flchip *chip,
|
||||
- unsigned long adr, unsigned int chip_op_time )
|
||||
+ unsigned long adr, int *chip_op_time )
|
||||
{
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
|
||||
@@ -942,7 +942,7 @@
|
||||
flstate_t oldstate, newstate;
|
||||
|
||||
start = xip_currtime();
|
||||
- usec = chip_op_time * 8;
|
||||
+ usec = *chip_op_time * 8;
|
||||
if (usec == 0)
|
||||
usec = 500000;
|
||||
done = 0;
|
||||
@@ -1052,8 +1052,8 @@
|
||||
#define XIP_INVAL_CACHED_RANGE(map, from, size) \
|
||||
INVALIDATE_CACHED_RANGE(map, from, size)
|
||||
|
||||
-#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
|
||||
- xip_wait_for_operation(map, chip, cmd_adr, usec)
|
||||
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
|
||||
+ xip_wait_for_operation(map, chip, cmd_adr, p_usec)
|
||||
|
||||
#else
|
||||
|
||||
@@ -1065,65 +1065,65 @@
|
||||
static int inval_cache_and_wait_for_operation(
|
||||
struct map_info *map, struct flchip *chip,
|
||||
unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
|
||||
- unsigned int chip_op_time)
|
||||
+ int *chip_op_time )
|
||||
{
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
map_word status, status_OK = CMD(0x80);
|
||||
- int chip_state = chip->state;
|
||||
- unsigned int timeo, sleep_time;
|
||||
+ int z, chip_state = chip->state;
|
||||
+ unsigned long timeo;
|
||||
|
||||
spin_unlock(chip->mutex);
|
||||
if (inval_len)
|
||||
INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
|
||||
+ if (*chip_op_time)
|
||||
+ cfi_udelay(*chip_op_time);
|
||||
spin_lock(chip->mutex);
|
||||
|
||||
- /* set our timeout to 8 times the expected delay */
|
||||
- timeo = chip_op_time * 8;
|
||||
- if (!timeo)
|
||||
- timeo = 500000;
|
||||
- sleep_time = chip_op_time / 2;
|
||||
+ timeo = *chip_op_time * 8 * HZ / 1000000;
|
||||
+ if (timeo < HZ/2)
|
||||
+ timeo = HZ/2;
|
||||
+ timeo += jiffies;
|
||||
|
||||
+ z = 0;
|
||||
for (;;) {
|
||||
+ if (chip->state != chip_state) {
|
||||
+ /* Someone's suspended the operation: sleep */
|
||||
+ DECLARE_WAITQUEUE(wait, current);
|
||||
+
|
||||
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
+ add_wait_queue(&chip->wq, &wait);
|
||||
+ spin_unlock(chip->mutex);
|
||||
+ schedule();
|
||||
+ remove_wait_queue(&chip->wq, &wait);
|
||||
+ timeo = jiffies + (HZ / 2); /* FIXME */
|
||||
+ spin_lock(chip->mutex);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
status = map_read(map, cmd_adr);
|
||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||
break;
|
||||
|
||||
- if (!timeo) {
|
||||
+ /* OK Still waiting */
|
||||
+ if (time_after(jiffies, timeo)) {
|
||||
map_write(map, CMD(0x70), cmd_adr);
|
||||
chip->state = FL_STATUS;
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
- /* OK Still waiting. Drop the lock, wait a while and retry. */
|
||||
+ /* Latency issues. Drop the lock, wait a while and retry */
|
||||
+ z++;
|
||||
spin_unlock(chip->mutex);
|
||||
- if (sleep_time >= 1000000/HZ) {
|
||||
- /*
|
||||
- * Half of the normal delay still remaining
|
||||
- * can be performed with a sleeping delay instead
|
||||
- * of busy waiting.
|
||||
- */
|
||||
- msleep(sleep_time/1000);
|
||||
- timeo -= sleep_time;
|
||||
- sleep_time = 1000000/HZ;
|
||||
- } else {
|
||||
- udelay(1);
|
||||
- cond_resched();
|
||||
- timeo--;
|
||||
- }
|
||||
+ cfi_udelay(1);
|
||||
spin_lock(chip->mutex);
|
||||
-
|
||||
- while (chip->state != chip_state) {
|
||||
- /* Someone's suspended the operation: sleep */
|
||||
- DECLARE_WAITQUEUE(wait, current);
|
||||
- set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
- add_wait_queue(&chip->wq, &wait);
|
||||
- spin_unlock(chip->mutex);
|
||||
- schedule();
|
||||
- remove_wait_queue(&chip->wq, &wait);
|
||||
- spin_lock(chip->mutex);
|
||||
- }
|
||||
}
|
||||
|
||||
+ if (!z) {
|
||||
+ if (!--(*chip_op_time))
|
||||
+ *chip_op_time = 1;
|
||||
+ } else if (z > 1)
|
||||
+ ++(*chip_op_time);
|
||||
+
|
||||
/* Done and happy. */
|
||||
chip->state = FL_STATUS;
|
||||
return 0;
|
||||
@@ -1132,7 +1132,8 @@
|
||||
#endif
|
||||
|
||||
#define WAIT_TIMEOUT(map, chip, adr, udelay) \
|
||||
- INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
|
||||
+ ({ int __udelay = (udelay); \
|
||||
+ INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
|
||||
|
||||
|
||||
static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
|
||||
@@ -1356,7 +1357,7 @@
|
||||
|
||||
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
|
||||
adr, map_bankwidth(map),
|
||||
- chip->word_write_time);
|
||||
+ &chip->word_write_time);
|
||||
if (ret) {
|
||||
xip_enable(map, chip, adr);
|
||||
printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
|
||||
@@ -1593,7 +1594,7 @@
|
||||
|
||||
ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
|
||||
initial_adr, initial_len,
|
||||
- chip->buffer_write_time);
|
||||
+ &chip->buffer_write_time);
|
||||
if (ret) {
|
||||
map_write(map, CMD(0x70), cmd_adr);
|
||||
chip->state = FL_STATUS;
|
||||
@@ -1728,7 +1729,7 @@
|
||||
|
||||
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
|
||||
adr, len,
|
||||
- chip->erase_time);
|
||||
+ &chip->erase_time);
|
||||
if (ret) {
|
||||
map_write(map, CMD(0x70), adr);
|
||||
chip->state = FL_STATUS;
|
|
@ -0,0 +1,23 @@
|
|||
Index: linux-2.6.23-rc6/fs/squashfs/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/squashfs/Makefile 2007-09-21 16:23:55.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/squashfs/Makefile 2007-09-21 16:23:58.000000000 +0800
|
||||
@@ -4,4 +4,3 @@
|
||||
|
||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
||||
squashfs-y += inode.o
|
||||
-squashfs-y += squashfs2_0.o
|
||||
Index: linux-2.6.23-rc6/fs/squashfs/squashfs.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/squashfs/squashfs.h 2007-09-21 16:23:55.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/squashfs/squashfs.h 2007-09-21 16:23:58.000000000 +0800
|
||||
@@ -24,6 +24,9 @@
|
||||
#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
|
||||
#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
|
||||
#endif
|
||||
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
|
||||
+#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY
|
||||
+#endif
|
||||
|
||||
#ifdef SQUASHFS_TRACE
|
||||
#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
|
|
@ -0,0 +1,13 @@
|
|||
Index: linux-2.6.23-rc6/arch/mips/kernel/head.S
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/arch/mips/kernel/head.S 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/arch/mips/kernel/head.S 2007-09-21 16:23:58.000000000 +0800
|
||||
@@ -130,6 +130,8 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
+ j kernel_entry
|
||||
+ nop
|
||||
#ifndef CONFIG_NO_EXCEPT_FILL
|
||||
/*
|
||||
* Reserved space for exception handlers.
|
|
@ -0,0 +1,114 @@
|
|||
Index: linux-2.6.23-rc6/drivers/mtd/devices/block2mtd.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/devices/block2mtd.c 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/devices/block2mtd.c 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mount.h>
|
||||
@@ -237,10 +238,11 @@
|
||||
|
||||
|
||||
/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
|
||||
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
struct block2mtd_dev *dev;
|
||||
+ struct mtd_partition *part;
|
||||
|
||||
if (!devname)
|
||||
return NULL;
|
||||
@@ -279,14 +281,18 @@
|
||||
|
||||
/* Setup the MTD structure */
|
||||
/* make the name contain the block device in */
|
||||
- dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
|
||||
- GFP_KERNEL);
|
||||
+
|
||||
+ if (!mtdname)
|
||||
+ mtdname = devname;
|
||||
+
|
||||
+ dev->mtd.name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
|
||||
+
|
||||
if (!dev->mtd.name)
|
||||
goto devinit_err;
|
||||
+
|
||||
+ strcpy(dev->mtd.name, mtdname);
|
||||
|
||||
- sprintf(dev->mtd.name, "block2mtd: %s", devname);
|
||||
-
|
||||
- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
|
||||
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
|
||||
dev->mtd.erasesize = erase_size;
|
||||
dev->mtd.writesize = 1;
|
||||
dev->mtd.type = MTD_RAM;
|
||||
@@ -298,15 +304,18 @@
|
||||
dev->mtd.read = block2mtd_read;
|
||||
dev->mtd.priv = dev;
|
||||
dev->mtd.owner = THIS_MODULE;
|
||||
-
|
||||
- if (add_mtd_device(&dev->mtd)) {
|
||||
+
|
||||
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
||||
+ part->name = dev->mtd.name;
|
||||
+ part->offset = 0;
|
||||
+ part->size = dev->mtd.size;
|
||||
+ if (add_mtd_partitions(&dev->mtd, part, 1)) {
|
||||
/* Device didnt get added, so free the entry */
|
||||
goto devinit_err;
|
||||
}
|
||||
list_add(&dev->list, &blkmtd_device_list);
|
||||
INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
|
||||
- dev->mtd.name + strlen("blkmtd: "),
|
||||
- dev->mtd.erasesize >> 10, dev->mtd.erasesize);
|
||||
+ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
|
||||
return dev;
|
||||
|
||||
devinit_err:
|
||||
@@ -379,9 +388,9 @@
|
||||
|
||||
static int block2mtd_setup2(const char *val)
|
||||
{
|
||||
- char buf[80 + 12]; /* 80 for device, 12 for erase size */
|
||||
+ char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
|
||||
char *str = buf;
|
||||
- char *token[2];
|
||||
+ char *token[3];
|
||||
char *name;
|
||||
size_t erase_size = PAGE_SIZE;
|
||||
int i, ret;
|
||||
@@ -392,7 +401,7 @@
|
||||
strcpy(str, val);
|
||||
kill_final_newline(str);
|
||||
|
||||
- for (i = 0; i < 2; i++)
|
||||
+ for (i = 0; i < 3; i++)
|
||||
token[i] = strsep(&str, ",");
|
||||
|
||||
if (str)
|
||||
@@ -412,8 +421,10 @@
|
||||
parse_err("illegal erase size");
|
||||
}
|
||||
}
|
||||
+ if (token[2] && (strlen(token[2]) + 1 > 80))
|
||||
+ parse_err("mtd device name too long");
|
||||
|
||||
- add_device(name, erase_size);
|
||||
+ add_device(name, erase_size, token[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -447,7 +458,7 @@
|
||||
|
||||
|
||||
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
|
||||
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
|
||||
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
|
||||
|
||||
static int __init block2mtd_init(void)
|
||||
{
|
|
@ -0,0 +1,965 @@
|
|||
Index: linux-2.6.23-rc6/drivers/mtd/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/Kconfig 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/Kconfig 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -47,6 +47,16 @@
|
||||
devices. Partitioning on NFTL 'devices' is a different - that's the
|
||||
'normal' form of partitioning used on a block device.
|
||||
|
||||
+config MTD_ROOTFS_ROOT_DEV
|
||||
+ bool "Automatically set 'rootfs' partition to be root filesystem"
|
||||
+ depends on MTD_PARTITIONS
|
||||
+ default y
|
||||
+
|
||||
+config MTD_ROOTFS_SPLIT
|
||||
+ bool "Automatically split 'rootfs' partition for squashfs"
|
||||
+ depends on MTD_PARTITIONS
|
||||
+ default y
|
||||
+
|
||||
config MTD_REDBOOT_PARTS
|
||||
tristate "RedBoot partition table parsing"
|
||||
depends on MTD_PARTITIONS
|
||||
Index: linux-2.6.23-rc6/drivers/mtd/mtdpart.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/mtdpart.c 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/mtdpart.c 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/compatmac.h>
|
||||
+#include <linux/squashfs_fs.h>
|
||||
+#include <linux/root_dev.h>
|
||||
|
||||
/* Our partition linked list */
|
||||
static LIST_HEAD(mtd_partitions);
|
||||
@@ -39,7 +41,7 @@
|
||||
* the pointer to that structure with this macro.
|
||||
*/
|
||||
#define PART(x) ((struct mtd_part *)(x))
|
||||
-
|
||||
+#define IS_PART(mtd) (mtd->read == part_read)
|
||||
|
||||
/*
|
||||
* MTD methods which simply translate the effective address and pass through
|
||||
@@ -322,6 +324,316 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static u_int32_t cur_offset = 0;
|
||||
+static int add_one_partition(struct mtd_info *master, const struct mtd_partition *part,
|
||||
+ int i, struct mtd_part **slp)
|
||||
+{
|
||||
+ struct mtd_part *slave;
|
||||
+
|
||||
+ /* allocate the partition structure */
|
||||
+ slave = kzalloc (sizeof(*slave), GFP_KERNEL);
|
||||
+ if (!slave) {
|
||||
+ printk ("memory allocation error while creating partitions for \"%s\"\n",
|
||||
+ master->name);
|
||||
+ del_mtd_partitions(master);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ list_add(&slave->list, &mtd_partitions);
|
||||
+
|
||||
+ /* set up the MTD object for this partition */
|
||||
+ slave->mtd.type = master->type;
|
||||
+ slave->mtd.flags = master->flags & ~part->mask_flags;
|
||||
+ slave->mtd.size = part->size;
|
||||
+ slave->mtd.writesize = master->writesize;
|
||||
+ slave->mtd.oobsize = master->oobsize;
|
||||
+ slave->mtd.oobavail = master->oobavail;
|
||||
+ slave->mtd.subpage_sft = master->subpage_sft;
|
||||
+
|
||||
+ slave->mtd.name = part->name;
|
||||
+ slave->mtd.owner = master->owner;
|
||||
+
|
||||
+ slave->mtd.read = part_read;
|
||||
+ slave->mtd.write = part_write;
|
||||
+
|
||||
+ if (master->panic_write)
|
||||
+ slave->mtd.panic_write = part_panic_write;
|
||||
+
|
||||
+ slave->mtd.refresh_device = part->refresh_partition;
|
||||
+
|
||||
+ if(master->point && master->unpoint){
|
||||
+ slave->mtd.point = part_point;
|
||||
+ slave->mtd.unpoint = part_unpoint;
|
||||
+ }
|
||||
+
|
||||
+ if (master->read_oob)
|
||||
+ slave->mtd.read_oob = part_read_oob;
|
||||
+ if (master->write_oob)
|
||||
+ slave->mtd.write_oob = part_write_oob;
|
||||
+ if(master->read_user_prot_reg)
|
||||
+ slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
|
||||
+ if(master->read_fact_prot_reg)
|
||||
+ slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
|
||||
+ if(master->write_user_prot_reg)
|
||||
+ slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
|
||||
+ if(master->lock_user_prot_reg)
|
||||
+ slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
|
||||
+ if(master->get_user_prot_info)
|
||||
+ slave->mtd.get_user_prot_info = part_get_user_prot_info;
|
||||
+ if(master->get_fact_prot_info)
|
||||
+ slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
|
||||
+ if (master->sync)
|
||||
+ slave->mtd.sync = part_sync;
|
||||
+ if (!i && master->suspend && master->resume) {
|
||||
+ slave->mtd.suspend = part_suspend;
|
||||
+ slave->mtd.resume = part_resume;
|
||||
+ }
|
||||
+ if (master->writev)
|
||||
+ slave->mtd.writev = part_writev;
|
||||
+ if (master->lock)
|
||||
+ slave->mtd.lock = part_lock;
|
||||
+ if (master->unlock)
|
||||
+ slave->mtd.unlock = part_unlock;
|
||||
+ if (master->block_isbad)
|
||||
+ slave->mtd.block_isbad = part_block_isbad;
|
||||
+ if (master->block_markbad)
|
||||
+ slave->mtd.block_markbad = part_block_markbad;
|
||||
+ slave->mtd.erase = part_erase;
|
||||
+ slave->master = master;
|
||||
+ slave->offset = part->offset;
|
||||
+ slave->index = i;
|
||||
+
|
||||
+ if (slave->offset == MTDPART_OFS_APPEND)
|
||||
+ slave->offset = cur_offset;
|
||||
+ if (slave->offset == MTDPART_OFS_NXTBLK) {
|
||||
+ slave->offset = cur_offset;
|
||||
+ if ((cur_offset % master->erasesize) != 0) {
|
||||
+ /* Round up to next erasesize */
|
||||
+ slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
|
||||
+ printk(KERN_NOTICE "Moving partition %d: "
|
||||
+ "0x%08x -> 0x%08x\n", i,
|
||||
+ cur_offset, slave->offset);
|
||||
+ }
|
||||
+ }
|
||||
+ if (slave->mtd.size == MTDPART_SIZ_FULL)
|
||||
+ slave->mtd.size = master->size - slave->offset;
|
||||
+ cur_offset = slave->offset + slave->mtd.size;
|
||||
+
|
||||
+ printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
|
||||
+ slave->offset + slave->mtd.size, slave->mtd.name);
|
||||
+
|
||||
+ /* let's do some sanity checks */
|
||||
+ if (slave->offset >= master->size) {
|
||||
+ /* let's register it anyway to preserve ordering */
|
||||
+ slave->offset = 0;
|
||||
+ slave->mtd.size = 0;
|
||||
+ printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
+ if (slave->offset + slave->mtd.size > master->size) {
|
||||
+ slave->mtd.size = master->size - slave->offset;
|
||||
+ printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
|
||||
+ part->name, master->name, slave->mtd.size);
|
||||
+ }
|
||||
+ if (master->numeraseregions>1) {
|
||||
+ /* Deal with variable erase size stuff */
|
||||
+ int i;
|
||||
+ struct mtd_erase_region_info *regions = master->eraseregions;
|
||||
+
|
||||
+ /* Find the first erase regions which is part of this partition. */
|
||||
+ for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
|
||||
+ ;
|
||||
+
|
||||
+ for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
|
||||
+ if (slave->mtd.erasesize < regions[i].erasesize) {
|
||||
+ slave->mtd.erasesize = regions[i].erasesize;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Single erase size */
|
||||
+ slave->mtd.erasesize = master->erasesize;
|
||||
+ }
|
||||
+
|
||||
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
+ (slave->offset % slave->mtd.erasesize)) {
|
||||
+ /* Doesn't start on a boundary of major erase size */
|
||||
+ /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
|
||||
+ slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
+ printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
+ (slave->mtd.size % slave->mtd.erasesize)) {
|
||||
+ slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
+ printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
+
|
||||
+ slave->mtd.ecclayout = master->ecclayout;
|
||||
+ if (master->block_isbad) {
|
||||
+ uint32_t offs = 0;
|
||||
+
|
||||
+ while(offs < slave->mtd.size) {
|
||||
+ if (master->block_isbad(master,
|
||||
+ offs + slave->offset))
|
||||
+ slave->mtd.ecc_stats.badblocks++;
|
||||
+ offs += slave->mtd.erasesize;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if(part->mtdp)
|
||||
+ { /* store the object pointer (caller may or may not register it */
|
||||
+ *part->mtdp = &slave->mtd;
|
||||
+ slave->registered = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* register our partition */
|
||||
+ add_mtd_device(&slave->mtd);
|
||||
+ slave->registered = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (slp)
|
||||
+ *slp = slave;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
||||
+#define ROOTFS_SPLIT_NAME "rootfs_data"
|
||||
+#define ROOTFS_REMOVED_NAME "<removed>"
|
||||
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
|
||||
+{
|
||||
+ char buf[512];
|
||||
+ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
|
||||
+ int len, ret;
|
||||
+
|
||||
+ ret = master->read(master, offset, sizeof(*sb), &len, buf);
|
||||
+ if (ret || (len != sizeof(*sb))) {
|
||||
+ printk(KERN_ALERT "split_squashfs: error occured while reading "
|
||||
+ "from \"%s\"\n", master->name);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (*((u32 *) buf) != SQUASHFS_MAGIC) {
|
||||
+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
|
||||
+ master->name);
|
||||
+ *split_offset = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (sb->bytes_used <= 0) {
|
||||
+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
|
||||
+ master->name);
|
||||
+ *split_offset = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ len = (u32) sb->bytes_used;
|
||||
+ len += (offset & 0x000fffff);
|
||||
+ len += (master->erasesize - 1);
|
||||
+ len &= ~(master->erasesize - 1);
|
||||
+ len -= (offset & 0x000fffff);
|
||||
+ *split_offset = offset + len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, struct mtd_partition *part,
|
||||
+ int index)
|
||||
+{
|
||||
+ struct mtd_partition *dpart;
|
||||
+ struct mtd_part *slave = NULL;
|
||||
+ int split_offset = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = split_squashfs(master, part->offset, &split_offset);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (split_offset <= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
|
||||
+ if (dpart == NULL) {
|
||||
+ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
|
||||
+ ROOTFS_SPLIT_NAME);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(dpart, part, sizeof(*part));
|
||||
+ dpart->name = (unsigned char *)&dpart[1];
|
||||
+ strcpy(dpart->name, ROOTFS_SPLIT_NAME);
|
||||
+
|
||||
+ dpart->size -= split_offset - dpart->offset;
|
||||
+ dpart->offset = split_offset;
|
||||
+
|
||||
+ if (dpart == NULL)
|
||||
+ return 1;
|
||||
+
|
||||
+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n",
|
||||
+ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
|
||||
+
|
||||
+ ret = add_one_partition(master, dpart, index, &slave);
|
||||
+ if (ret)
|
||||
+ kfree(dpart);
|
||||
+ else if (slave)
|
||||
+ rpart->split = &slave->mtd;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int refresh_rootfs_split(struct mtd_info *mtd)
|
||||
+{
|
||||
+ struct mtd_partition tpart;
|
||||
+ struct mtd_part *part;
|
||||
+ int index = 0;
|
||||
+ int offset, size;
|
||||
+ int ret;
|
||||
+
|
||||
+ part = PART(mtd);
|
||||
+
|
||||
+ /* check for the new squashfs offset first */
|
||||
+ ret = split_squashfs(part->master, part->offset, &offset);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if ((offset > 0) && !mtd->split) {
|
||||
+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
|
||||
+ /* if we don't have a rootfs split partition, create a new one */
|
||||
+ tpart.name = mtd->name;
|
||||
+ tpart.size = mtd->size;
|
||||
+ tpart.offset = part->offset;
|
||||
+
|
||||
+ /* find the index of the last partition */
|
||||
+ if (!list_empty(&mtd_partitions))
|
||||
+ index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1;
|
||||
+
|
||||
+ return split_rootfs_data(part->master, &part->mtd, &tpart, index);
|
||||
+ } else if ((offset > 0) && mtd->split) {
|
||||
+ /* update the offsets of the existing partition */
|
||||
+ size = mtd->size + part->offset - offset;
|
||||
+
|
||||
+ part = PART(mtd->split);
|
||||
+ part->offset = offset;
|
||||
+ part->mtd.size = size;
|
||||
+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
|
||||
+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
|
||||
+ part->offset, part->mtd.size);
|
||||
+ strcpy(part->mtd.name, ROOTFS_SPLIT_NAME);
|
||||
+ } else if ((offset <= 0) && mtd->split) {
|
||||
+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
|
||||
+
|
||||
+ /* mark existing partition as removed */
|
||||
+ part = PART(mtd->split);
|
||||
+ strcpy(part->mtd.name, ROOTFS_REMOVED_NAME);
|
||||
+ part->offset = 0;
|
||||
+ part->mtd.size = 0;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
|
||||
+
|
||||
/*
|
||||
* This function, given a master MTD object and a partition table, creates
|
||||
* and registers slave MTD objects which are bound to the master according to
|
||||
@@ -334,171 +646,31 @@
|
||||
int nbparts)
|
||||
{
|
||||
struct mtd_part *slave;
|
||||
- u_int32_t cur_offset = 0;
|
||||
- int i;
|
||||
+ struct mtd_partition *part;
|
||||
+ int i, j, ret = 0;
|
||||
|
||||
printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
|
||||
|
||||
- for (i = 0; i < nbparts; i++) {
|
||||
-
|
||||
- /* allocate the partition structure */
|
||||
- slave = kzalloc (sizeof(*slave), GFP_KERNEL);
|
||||
- if (!slave) {
|
||||
- printk ("memory allocation error while creating partitions for \"%s\"\n",
|
||||
- master->name);
|
||||
- del_mtd_partitions(master);
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
- list_add(&slave->list, &mtd_partitions);
|
||||
-
|
||||
- /* set up the MTD object for this partition */
|
||||
- slave->mtd.type = master->type;
|
||||
- slave->mtd.flags = master->flags & ~parts[i].mask_flags;
|
||||
- slave->mtd.size = parts[i].size;
|
||||
- slave->mtd.writesize = master->writesize;
|
||||
- slave->mtd.oobsize = master->oobsize;
|
||||
- slave->mtd.oobavail = master->oobavail;
|
||||
- slave->mtd.subpage_sft = master->subpage_sft;
|
||||
-
|
||||
- slave->mtd.name = parts[i].name;
|
||||
- slave->mtd.owner = master->owner;
|
||||
-
|
||||
- slave->mtd.read = part_read;
|
||||
- slave->mtd.write = part_write;
|
||||
-
|
||||
- if (master->panic_write)
|
||||
- slave->mtd.panic_write = part_panic_write;
|
||||
-
|
||||
- if(master->point && master->unpoint){
|
||||
- slave->mtd.point = part_point;
|
||||
- slave->mtd.unpoint = part_unpoint;
|
||||
- }
|
||||
-
|
||||
- if (master->read_oob)
|
||||
- slave->mtd.read_oob = part_read_oob;
|
||||
- if (master->write_oob)
|
||||
- slave->mtd.write_oob = part_write_oob;
|
||||
- if(master->read_user_prot_reg)
|
||||
- slave->mtd.read_user_prot_reg = part_read_user_prot_reg;
|
||||
- if(master->read_fact_prot_reg)
|
||||
- slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;
|
||||
- if(master->write_user_prot_reg)
|
||||
- slave->mtd.write_user_prot_reg = part_write_user_prot_reg;
|
||||
- if(master->lock_user_prot_reg)
|
||||
- slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;
|
||||
- if(master->get_user_prot_info)
|
||||
- slave->mtd.get_user_prot_info = part_get_user_prot_info;
|
||||
- if(master->get_fact_prot_info)
|
||||
- slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
|
||||
- if (master->sync)
|
||||
- slave->mtd.sync = part_sync;
|
||||
- if (!i && master->suspend && master->resume) {
|
||||
- slave->mtd.suspend = part_suspend;
|
||||
- slave->mtd.resume = part_resume;
|
||||
- }
|
||||
- if (master->writev)
|
||||
- slave->mtd.writev = part_writev;
|
||||
- if (master->lock)
|
||||
- slave->mtd.lock = part_lock;
|
||||
- if (master->unlock)
|
||||
- slave->mtd.unlock = part_unlock;
|
||||
- if (master->block_isbad)
|
||||
- slave->mtd.block_isbad = part_block_isbad;
|
||||
- if (master->block_markbad)
|
||||
- slave->mtd.block_markbad = part_block_markbad;
|
||||
- slave->mtd.erase = part_erase;
|
||||
- slave->master = master;
|
||||
- slave->offset = parts[i].offset;
|
||||
- slave->index = i;
|
||||
-
|
||||
- if (slave->offset == MTDPART_OFS_APPEND)
|
||||
- slave->offset = cur_offset;
|
||||
- if (slave->offset == MTDPART_OFS_NXTBLK) {
|
||||
- slave->offset = cur_offset;
|
||||
- if ((cur_offset % master->erasesize) != 0) {
|
||||
- /* Round up to next erasesize */
|
||||
- slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
|
||||
- printk(KERN_NOTICE "Moving partition %d: "
|
||||
- "0x%08x -> 0x%08x\n", i,
|
||||
- cur_offset, slave->offset);
|
||||
- }
|
||||
- }
|
||||
- if (slave->mtd.size == MTDPART_SIZ_FULL)
|
||||
- slave->mtd.size = master->size - slave->offset;
|
||||
- cur_offset = slave->offset + slave->mtd.size;
|
||||
-
|
||||
- printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
|
||||
- slave->offset + slave->mtd.size, slave->mtd.name);
|
||||
-
|
||||
- /* let's do some sanity checks */
|
||||
- if (slave->offset >= master->size) {
|
||||
- /* let's register it anyway to preserve ordering */
|
||||
- slave->offset = 0;
|
||||
- slave->mtd.size = 0;
|
||||
- printk ("mtd: partition \"%s\" is out of reach -- disabled\n",
|
||||
- parts[i].name);
|
||||
- }
|
||||
- if (slave->offset + slave->mtd.size > master->size) {
|
||||
- slave->mtd.size = master->size - slave->offset;
|
||||
- printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
|
||||
- parts[i].name, master->name, slave->mtd.size);
|
||||
- }
|
||||
- if (master->numeraseregions>1) {
|
||||
- /* Deal with variable erase size stuff */
|
||||
- int i;
|
||||
- struct mtd_erase_region_info *regions = master->eraseregions;
|
||||
-
|
||||
- /* Find the first erase regions which is part of this partition. */
|
||||
- for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
|
||||
- ;
|
||||
-
|
||||
- for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {
|
||||
- if (slave->mtd.erasesize < regions[i].erasesize) {
|
||||
- slave->mtd.erasesize = regions[i].erasesize;
|
||||
- }
|
||||
+ for (i = 0, j = 0; i < nbparts; i++) {
|
||||
+ part = (struct mtd_partition *) &parts[i];
|
||||
+ ret = add_one_partition(master, part, j, &slave);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ j++;
|
||||
+
|
||||
+ if (strcmp(part->name, "rootfs") == 0 && slave->registered) {
|
||||
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
|
||||
+ if (ROOT_DEV == 0) {
|
||||
+ printk(KERN_NOTICE "mtd: partition \"rootfs\" "
|
||||
+ "set to be root filesystem\n");
|
||||
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
|
||||
}
|
||||
- } else {
|
||||
- /* Single erase size */
|
||||
- slave->mtd.erasesize = master->erasesize;
|
||||
- }
|
||||
-
|
||||
- if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
- (slave->offset % slave->mtd.erasesize)) {
|
||||
- /* Doesn't start on a boundary of major erase size */
|
||||
- /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
|
||||
- slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
- printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
|
||||
- parts[i].name);
|
||||
- }
|
||||
- if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
- (slave->mtd.size % slave->mtd.erasesize)) {
|
||||
- slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
- printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
|
||||
- parts[i].name);
|
||||
- }
|
||||
-
|
||||
- slave->mtd.ecclayout = master->ecclayout;
|
||||
- if (master->block_isbad) {
|
||||
- uint32_t offs = 0;
|
||||
-
|
||||
- while(offs < slave->mtd.size) {
|
||||
- if (master->block_isbad(master,
|
||||
- offs + slave->offset))
|
||||
- slave->mtd.ecc_stats.badblocks++;
|
||||
- offs += slave->mtd.erasesize;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if(parts[i].mtdp)
|
||||
- { /* store the object pointer (caller may or may not register it */
|
||||
- *parts[i].mtdp = &slave->mtd;
|
||||
- slave->registered = 0;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* register our partition */
|
||||
- add_mtd_device(&slave->mtd);
|
||||
- slave->registered = 1;
|
||||
+#endif
|
||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
||||
+ ret = split_rootfs_data(master, &slave->mtd, part, j);
|
||||
+ if (ret == 0)
|
||||
+ j++;
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,6 +746,32 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int refresh_mtd_partitions(struct mtd_info *mtd)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (IS_PART(mtd)) {
|
||||
+ struct mtd_part *part;
|
||||
+ struct mtd_info *master;
|
||||
+
|
||||
+ part = PART(mtd);
|
||||
+ master = part->master;
|
||||
+ if (master->refresh_device)
|
||||
+ ret = master->refresh_device(master);
|
||||
+ }
|
||||
+
|
||||
+ if (!ret && mtd->refresh_device)
|
||||
+ ret = mtd->refresh_device(mtd);
|
||||
+
|
||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
||||
+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
|
||||
+ refresh_rootfs_split(mtd);
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
EXPORT_SYMBOL_GPL(parse_mtd_partitions);
|
||||
+EXPORT_SYMBOL_GPL(refresh_mtd_partitions);
|
||||
EXPORT_SYMBOL_GPL(register_mtd_parser);
|
||||
EXPORT_SYMBOL_GPL(deregister_mtd_parser);
|
||||
Index: linux-2.6.23-rc6/drivers/mtd/devices/block2mtd.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/devices/block2mtd.c 2007-09-21 16:23:59.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/devices/block2mtd.c 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -34,6 +34,8 @@
|
||||
struct block_device *blkdev;
|
||||
struct mtd_info mtd;
|
||||
struct mutex write_mutex;
|
||||
+ rwlock_t bdev_mutex;
|
||||
+ char devname[0];
|
||||
};
|
||||
|
||||
|
||||
@@ -86,6 +88,12 @@
|
||||
size_t len = instr->len;
|
||||
int err;
|
||||
|
||||
+ read_lock(&dev->bdev_mutex);
|
||||
+ if (!dev->blkdev) {
|
||||
+ err = -EINVAL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
instr->state = MTD_ERASING;
|
||||
mutex_lock(&dev->write_mutex);
|
||||
err = _block2mtd_erase(dev, from, len);
|
||||
@@ -98,6 +106,10 @@
|
||||
|
||||
instr->state = MTD_ERASE_DONE;
|
||||
mtd_erase_callback(instr);
|
||||
+
|
||||
+done:
|
||||
+ read_unlock(&dev->bdev_mutex);
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -109,10 +121,14 @@
|
||||
struct page *page;
|
||||
int index = from >> PAGE_SHIFT;
|
||||
int offset = from & (PAGE_SIZE-1);
|
||||
- int cpylen;
|
||||
+ int cpylen, err = 0;
|
||||
+
|
||||
+ read_lock(&dev->bdev_mutex);
|
||||
+ if (!dev->blkdev || (from > mtd->size)) {
|
||||
+ err = -EINVAL;
|
||||
+ goto done;
|
||||
+ }
|
||||
|
||||
- if (from > mtd->size)
|
||||
- return -EINVAL;
|
||||
if (from + len > mtd->size)
|
||||
len = mtd->size - from;
|
||||
|
||||
@@ -127,10 +143,14 @@
|
||||
len = len - cpylen;
|
||||
|
||||
page = page_read(dev->blkdev->bd_inode->i_mapping, index);
|
||||
- if (!page)
|
||||
- return -ENOMEM;
|
||||
- if (IS_ERR(page))
|
||||
- return PTR_ERR(page);
|
||||
+ if (!page) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ if (IS_ERR(page)) {
|
||||
+ err = PTR_ERR(page);
|
||||
+ goto done;
|
||||
+ }
|
||||
|
||||
memcpy(buf, page_address(page) + offset, cpylen);
|
||||
page_cache_release(page);
|
||||
@@ -141,7 +161,10 @@
|
||||
offset = 0;
|
||||
index++;
|
||||
}
|
||||
- return 0;
|
||||
+
|
||||
+done:
|
||||
+ read_unlock(&dev->bdev_mutex);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,12 +216,22 @@
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct block2mtd_dev *dev = mtd->priv;
|
||||
- int err;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ read_lock(&dev->bdev_mutex);
|
||||
+ if (!dev->blkdev) {
|
||||
+ err = -EINVAL;
|
||||
+ goto done;
|
||||
+ }
|
||||
|
||||
if (!len)
|
||||
- return 0;
|
||||
- if (to >= mtd->size)
|
||||
- return -ENOSPC;
|
||||
+ goto done;
|
||||
+
|
||||
+ if (to >= mtd->size) {
|
||||
+ err = -ENOSPC;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
if (to + len > mtd->size)
|
||||
len = mtd->size - to;
|
||||
|
||||
@@ -207,6 +240,9 @@
|
||||
mutex_unlock(&dev->write_mutex);
|
||||
if (err > 0)
|
||||
err = 0;
|
||||
+
|
||||
+done:
|
||||
+ read_unlock(&dev->bdev_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -215,51 +251,29 @@
|
||||
static void block2mtd_sync(struct mtd_info *mtd)
|
||||
{
|
||||
struct block2mtd_dev *dev = mtd->priv;
|
||||
- sync_blockdev(dev->blkdev);
|
||||
- return;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void block2mtd_free_device(struct block2mtd_dev *dev)
|
||||
-{
|
||||
- if (!dev)
|
||||
- return;
|
||||
-
|
||||
- kfree(dev->mtd.name);
|
||||
|
||||
- if (dev->blkdev) {
|
||||
- invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
|
||||
- 0, -1);
|
||||
- close_bdev_excl(dev->blkdev);
|
||||
- }
|
||||
+ read_lock(&dev->bdev_mutex);
|
||||
+ if (dev->blkdev)
|
||||
+ sync_blockdev(dev->blkdev);
|
||||
+ read_unlock(&dev->bdev_mutex);
|
||||
|
||||
- kfree(dev);
|
||||
+ return;
|
||||
}
|
||||
|
||||
|
||||
-/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||
-static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
|
||||
+static int _open_bdev(struct block2mtd_dev *dev)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
- struct block2mtd_dev *dev;
|
||||
- struct mtd_partition *part;
|
||||
-
|
||||
- if (!devname)
|
||||
- return NULL;
|
||||
-
|
||||
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
|
||||
- if (!dev)
|
||||
- return NULL;
|
||||
|
||||
/* Get a handle on the device */
|
||||
- bdev = open_bdev_excl(devname, O_RDWR, NULL);
|
||||
+ bdev = open_bdev_excl(dev->devname, O_RDWR, NULL);
|
||||
#ifndef MODULE
|
||||
if (IS_ERR(bdev)) {
|
||||
|
||||
/* We might not have rootfs mounted at this point. Try
|
||||
to resolve the device name by other means. */
|
||||
|
||||
- dev_t devt = name_to_dev_t(devname);
|
||||
+ dev_t devt = name_to_dev_t(dev->devname);
|
||||
if (devt) {
|
||||
bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
||||
}
|
||||
@@ -267,17 +281,96 @@
|
||||
#endif
|
||||
|
||||
if (IS_ERR(bdev)) {
|
||||
- ERROR("error: cannot open device %s", devname);
|
||||
- goto devinit_err;
|
||||
+ ERROR("error: cannot open device %s", dev->devname);
|
||||
+ return 1;
|
||||
}
|
||||
dev->blkdev = bdev;
|
||||
|
||||
if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
|
||||
ERROR("attempting to use an MTD device as a block device");
|
||||
- goto devinit_err;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void _close_bdev(struct block2mtd_dev *dev)
|
||||
+{
|
||||
+ struct block_device *bdev;
|
||||
+
|
||||
+ if (!dev->blkdev)
|
||||
+ return;
|
||||
+
|
||||
+ bdev = dev->blkdev;
|
||||
+ invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
|
||||
+ close_bdev_excl(dev->blkdev);
|
||||
+ dev->blkdev = NULL;
|
||||
+}
|
||||
+
|
||||
+static void block2mtd_free_device(struct block2mtd_dev *dev)
|
||||
+{
|
||||
+ if (!dev)
|
||||
+ return;
|
||||
+
|
||||
+ kfree(dev->mtd.name);
|
||||
+ _close_bdev(dev);
|
||||
+ kfree(dev);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int block2mtd_refresh(struct mtd_info *mtd)
|
||||
+{
|
||||
+ struct block2mtd_dev *dev = mtd->priv;
|
||||
+ struct block_device *bdev;
|
||||
+ dev_t devt;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ /* no other mtd function can run at this point */
|
||||
+ write_lock(&dev->bdev_mutex);
|
||||
+
|
||||
+ /* get the device number for the whole disk */
|
||||
+ devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
|
||||
+
|
||||
+ /* close the old block device */
|
||||
+ _close_bdev(dev);
|
||||
+
|
||||
+ /* open the whole disk, issue a partition rescan, then */
|
||||
+ bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
||||
+ if (!bdev || !bdev->bd_disk)
|
||||
+ err = -EINVAL;
|
||||
+ else {
|
||||
+ err = rescan_partitions(bdev->bd_disk, bdev);
|
||||
+ }
|
||||
+ if (bdev)
|
||||
+ close_bdev_excl(bdev);
|
||||
+
|
||||
+ /* try to open the partition block device again */
|
||||
+ _open_bdev(dev);
|
||||
+ write_unlock(&dev->bdev_mutex);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
|
||||
+{
|
||||
+ struct block2mtd_dev *dev;
|
||||
+ struct mtd_partition *part;
|
||||
+
|
||||
+ if (!devname)
|
||||
+ return NULL;
|
||||
+
|
||||
+ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
|
||||
+ if (!dev)
|
||||
+ return NULL;
|
||||
+
|
||||
+ strcpy(dev->devname, devname);
|
||||
+
|
||||
+ if (_open_bdev(dev))
|
||||
+ goto devinit_err;
|
||||
+
|
||||
mutex_init(&dev->write_mutex);
|
||||
+ rwlock_init(&dev->bdev_mutex);
|
||||
|
||||
/* Setup the MTD structure */
|
||||
/* make the name contain the block device in */
|
||||
@@ -304,6 +397,7 @@
|
||||
dev->mtd.read = block2mtd_read;
|
||||
dev->mtd.priv = dev;
|
||||
dev->mtd.owner = THIS_MODULE;
|
||||
+ dev->mtd.refresh_device = block2mtd_refresh;
|
||||
|
||||
part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
||||
part->name = dev->mtd.name;
|
||||
Index: linux-2.6.23-rc6/drivers/mtd/mtdchar.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/mtd/mtdchar.c 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/mtd/mtdchar.c 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/compatmac.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -753,6 +754,13 @@
|
||||
file->f_pos = 0;
|
||||
break;
|
||||
}
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+ case MTDREFRESH:
|
||||
+ {
|
||||
+ ret = refresh_mtd_partitions(mtd);
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
Index: linux-2.6.23-rc6/include/linux/mtd/mtd.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/include/linux/mtd/mtd.h 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/include/linux/mtd/mtd.h 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -98,6 +98,7 @@
|
||||
uint8_t *oobbuf;
|
||||
};
|
||||
|
||||
+struct mtd_info;
|
||||
struct mtd_info {
|
||||
u_char type;
|
||||
u_int32_t flags;
|
||||
@@ -195,6 +196,9 @@
|
||||
struct module *owner;
|
||||
int usecount;
|
||||
|
||||
+ int (*refresh_device)(struct mtd_info *mtd);
|
||||
+ struct mtd_info *split;
|
||||
+
|
||||
/* If the driver is something smart, like UBI, it may need to maintain
|
||||
* its own reference counting. The below functions are only for driver.
|
||||
* The driver may register its callbacks. These callbacks are not
|
||||
Index: linux-2.6.23-rc6/include/linux/mtd/partitions.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/include/linux/mtd/partitions.h 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/include/linux/mtd/partitions.h 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -36,6 +36,7 @@
|
||||
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
||||
*/
|
||||
|
||||
+struct mtd_partition;
|
||||
struct mtd_partition {
|
||||
char *name; /* identifier string */
|
||||
u_int32_t size; /* partition size */
|
||||
@@ -43,6 +44,7 @@
|
||||
u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
|
||||
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
|
||||
struct mtd_info **mtdp; /* pointer to store the MTD object */
|
||||
+ int (*refresh_partition)(struct mtd_info *);
|
||||
};
|
||||
|
||||
#define MTDPART_OFS_NXTBLK (-2)
|
||||
@@ -52,6 +54,7 @@
|
||||
|
||||
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
|
||||
int del_mtd_partitions(struct mtd_info *);
|
||||
+int refresh_mtd_partitions(struct mtd_info *);
|
||||
|
||||
/*
|
||||
* Functions dealing with the various ways of partitioning the space
|
||||
Index: linux-2.6.23-rc6/include/mtd/mtd-abi.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/include/mtd/mtd-abi.h 2007-09-21 16:23:54.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/include/mtd/mtd-abi.h 2007-09-21 16:23:59.000000000 +0800
|
||||
@@ -95,6 +95,7 @@
|
||||
#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
|
||||
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
|
||||
#define MTDFILEMODE _IO('M', 19)
|
||||
+#define MTDREFRESH _IO('M', 23)
|
||||
|
||||
/*
|
||||
* Obsolete legacy interface. Keep it in order not to break userspace
|
|
@ -0,0 +1,32 @@
|
|||
Index: linux-2.6.23.1/drivers/mtd/redboot.c
|
||||
===================================================================
|
||||
--- linux-2.6.23.1.orig/drivers/mtd/redboot.c 2008-01-26 01:43:10.742362738 +0100
|
||||
+++ linux-2.6.23.1/drivers/mtd/redboot.c 2008-01-26 01:47:24.432819736 +0100
|
||||
@@ -236,14 +236,21 @@
|
||||
#endif
|
||||
names += strlen(names)+1;
|
||||
|
||||
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
|
||||
- i++;
|
||||
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||
- parts[i].name = nullname;
|
||||
- }
|
||||
+ if (!strcmp(parts[i].name, "rootfs")) {
|
||||
+ parts[i].size = fl->next->img->flash_base;
|
||||
+ parts[i].size &= ~(master->erasesize - 1);
|
||||
+ parts[i].size -= parts[i].offset;
|
||||
+ }
|
||||
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
+ else {
|
||||
+ i++;
|
||||
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||
+ parts[i].name = nullname;
|
||||
+ }
|
||||
#endif
|
||||
+ }
|
||||
tmp_fl = fl;
|
||||
fl = fl->next;
|
||||
kfree(tmp_fl);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,113 @@
|
|||
Index: linux-2.6.24/include/linux/netfilter/xt_layer7.h
|
||||
===================================================================
|
||||
--- linux-2.6.24.orig/include/linux/netfilter/xt_layer7.h
|
||||
+++ linux-2.6.24/include/linux/netfilter/xt_layer7.h
|
||||
@@ -8,6 +8,7 @@ struct xt_layer7_info {
|
||||
char protocol[MAX_PROTOCOL_LEN];
|
||||
char pattern[MAX_PATTERN_LEN];
|
||||
u_int8_t invert;
|
||||
+ u_int8_t pkt;
|
||||
};
|
||||
|
||||
#endif /* _XT_LAYER7_H */
|
||||
Index: linux-2.6.24/net/netfilter/xt_layer7.c
|
||||
===================================================================
|
||||
--- linux-2.6.24.orig/net/netfilter/xt_layer7.c
|
||||
+++ linux-2.6.24/net/netfilter/xt_layer7.c
|
||||
@@ -297,34 +297,36 @@ static int match_no_append(struct nf_con
|
||||
}
|
||||
|
||||
/* add the new app data to the conntrack. Return number of bytes added. */
|
||||
-static int add_data(struct nf_conn * master_conntrack,
|
||||
- char * app_data, int appdatalen)
|
||||
+static int add_datastr(char *target, int offset, char *app_data, int len)
|
||||
{
|
||||
int length = 0, i;
|
||||
- int oldlength = master_conntrack->layer7.app_data_len;
|
||||
-
|
||||
- /* This is a fix for a race condition by Deti Fliegl. However, I'm not
|
||||
- clear on whether the race condition exists or whether this really
|
||||
- fixes it. I might just be being dense... Anyway, if it's not really
|
||||
- a fix, all it does is waste a very small amount of time. */
|
||||
- if(!master_conntrack->layer7.app_data) return 0;
|
||||
+
|
||||
+ if (!target) return 0;
|
||||
|
||||
/* Strip nulls. Make everything lower case (our regex lib doesn't
|
||||
do case insensitivity). Add it to the end of the current data. */
|
||||
- for(i = 0; i < maxdatalen-oldlength-1 &&
|
||||
- i < appdatalen; i++) {
|
||||
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
|
||||
if(app_data[i] != '\0') {
|
||||
/* the kernel version of tolower mungs 'upper ascii' */
|
||||
- master_conntrack->layer7.app_data[length+oldlength] =
|
||||
+ target[length+offset] =
|
||||
isascii(app_data[i])?
|
||||
tolower(app_data[i]) : app_data[i];
|
||||
length++;
|
||||
}
|
||||
}
|
||||
+ target[length+offset] = '\0';
|
||||
+
|
||||
+ return length;
|
||||
+}
|
||||
|
||||
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
|
||||
- master_conntrack->layer7.app_data_len = length + oldlength;
|
||||
+/* add the new app data to the conntrack. Return number of bytes added. */
|
||||
+static int add_data(struct nf_conn * master_conntrack,
|
||||
+ char * app_data, int appdatalen)
|
||||
+{
|
||||
+ int length;
|
||||
|
||||
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
|
||||
+ master_conntrack->layer7.app_data_len += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
@@ -411,7 +413,7 @@ match(const struct sk_buff *skbin,
|
||||
const struct xt_layer7_info * info = matchinfo;
|
||||
enum ip_conntrack_info master_ctinfo, ctinfo;
|
||||
struct nf_conn *master_conntrack, *conntrack;
|
||||
- unsigned char * app_data;
|
||||
+ unsigned char *app_data, *tmp_data;
|
||||
unsigned int pattern_result, appdatalen;
|
||||
regexp * comppattern;
|
||||
|
||||
@@ -439,8 +441,8 @@ match(const struct sk_buff *skbin,
|
||||
master_conntrack = master_ct(master_conntrack);
|
||||
|
||||
/* if we've classified it or seen too many packets */
|
||||
- if(TOTAL_PACKETS > num_packets ||
|
||||
- master_conntrack->layer7.app_proto) {
|
||||
+ if(!info->pkt && (TOTAL_PACKETS > num_packets ||
|
||||
+ master_conntrack->layer7.app_proto)) {
|
||||
|
||||
pattern_result = match_no_append(conntrack, master_conntrack,
|
||||
ctinfo, master_ctinfo, info);
|
||||
@@ -473,6 +475,25 @@ match(const struct sk_buff *skbin,
|
||||
/* the return value gets checked later, when we're ready to use it */
|
||||
comppattern = compile_and_cache(info->pattern, info->protocol);
|
||||
|
||||
+ if (info->pkt) {
|
||||
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
|
||||
+ if(!tmp_data){
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
|
||||
+ return info->invert;
|
||||
+ }
|
||||
+
|
||||
+ tmp_data[0] = '\0';
|
||||
+ add_datastr(tmp_data, 0, app_data, appdatalen);
|
||||
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
|
||||
+
|
||||
+ kfree(tmp_data);
|
||||
+ tmp_data = NULL;
|
||||
+ spin_unlock_bh(&l7_lock);
|
||||
+
|
||||
+ return (pattern_result ^ info->invert);
|
||||
+ }
|
||||
+
|
||||
/* On the first packet of a connection, allocate space for app data */
|
||||
if(TOTAL_PACKETS == 1 && !skb->cb[0] &&
|
||||
!master_conntrack->layer7.app_data){
|
|
@ -0,0 +1,927 @@
|
|||
Index: linux-2.6.23.1/include/linux/netfilter_ipv4/ipt_ipp2p.h
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23.1/include/linux/netfilter_ipv4/ipt_ipp2p.h 2007-11-19 18:22:19.000000000 -0600
|
||||
@@ -0,0 +1,31 @@
|
||||
+#ifndef __IPT_IPP2P_H
|
||||
+#define __IPT_IPP2P_H
|
||||
+#define IPP2P_VERSION "0.8.1_rc1"
|
||||
+
|
||||
+struct ipt_p2p_info {
|
||||
+ int cmd;
|
||||
+ int debug;
|
||||
+};
|
||||
+
|
||||
+#endif //__IPT_IPP2P_H
|
||||
+
|
||||
+#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
|
||||
+//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
|
||||
+#define SHORT_HAND_NONE 5 /* no short hand*/
|
||||
+
|
||||
+#define IPP2P_EDK (1 << 1)
|
||||
+#define IPP2P_DATA_KAZAA (1 << 2)
|
||||
+#define IPP2P_DATA_EDK (1 << 3)
|
||||
+#define IPP2P_DATA_DC (1 << 4)
|
||||
+#define IPP2P_DC (1 << 5)
|
||||
+#define IPP2P_DATA_GNU (1 << 6)
|
||||
+#define IPP2P_GNU (1 << 7)
|
||||
+#define IPP2P_KAZAA (1 << 8)
|
||||
+#define IPP2P_BIT (1 << 9)
|
||||
+#define IPP2P_APPLE (1 << 10)
|
||||
+#define IPP2P_SOUL (1 << 11)
|
||||
+#define IPP2P_WINMX (1 << 12)
|
||||
+#define IPP2P_ARES (1 << 13)
|
||||
+#define IPP2P_MUTE (1 << 14)
|
||||
+#define IPP2P_WASTE (1 << 15)
|
||||
+#define IPP2P_XDCC (1 << 16)
|
||||
Index: linux-2.6.23.1/net/ipv4/netfilter/ipt_ipp2p.c
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23.1/net/ipv4/netfilter/ipt_ipp2p.c 2007-11-19 18:22:19.000000000 -0600
|
||||
@@ -0,0 +1,856 @@
|
||||
+#if defined(MODVERSIONS)
|
||||
+#include <linux/modversions.h>
|
||||
+#endif
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
+#include <linux/version.h>
|
||||
+#include <linux/netfilter_ipv4/ipt_ipp2p.h>
|
||||
+#include <net/tcp.h>
|
||||
+#include <net/udp.h>
|
||||
+
|
||||
+#define get_u8(X,O) (*(__u8 *)(X + O))
|
||||
+#define get_u16(X,O) (*(__u16 *)(X + O))
|
||||
+#define get_u32(X,O) (*(__u32 *)(X + O))
|
||||
+
|
||||
+MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
|
||||
+MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+
|
||||
+
|
||||
+/*Search for UDP eDonkey/eMule/Kad commands*/
|
||||
+int
|
||||
+udp_search_edk (unsigned char *haystack, int packet_len)
|
||||
+{
|
||||
+ unsigned char *t = haystack;
|
||||
+ t += 8;
|
||||
+
|
||||
+ switch (t[0]) {
|
||||
+ case 0xe3:
|
||||
+ { /*edonkey*/
|
||||
+ switch (t[1])
|
||||
+ {
|
||||
+ /* client -> server status request */
|
||||
+ case 0x96:
|
||||
+ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
|
||||
+ break;
|
||||
+ /* server -> client status request */
|
||||
+ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
|
||||
+ break;
|
||||
+ /* server description request */
|
||||
+ /* e3 2a ff f0 .. | size == 6 */
|
||||
+ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
|
||||
+ break;
|
||||
+ /* server description response */
|
||||
+ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
|
||||
+ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
|
||||
+ // break;
|
||||
+ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
|
||||
+ break;
|
||||
+
|
||||
+ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case 0xe4:
|
||||
+ {
|
||||
+ switch (t[1])
|
||||
+ {
|
||||
+ /* e4 20 .. | size == 43 */
|
||||
+ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
|
||||
+ break;
|
||||
+ /* e4 00 .. 00 | size == 35 ? */
|
||||
+ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
|
||||
+ break;
|
||||
+ /* e4 10 .. 00 | size == 35 ? */
|
||||
+ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
|
||||
+ break;
|
||||
+ /* e4 18 .. 00 | size == 35 ? */
|
||||
+ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
|
||||
+ break;
|
||||
+ /* e4 52 .. | size = 44 */
|
||||
+ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
|
||||
+ break;
|
||||
+ /* e4 58 .. | size == 6 */
|
||||
+ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
|
||||
+ break;
|
||||
+ /* e4 59 .. | size == 2 */
|
||||
+ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
|
||||
+ break;
|
||||
+ /* e4 28 .. | packet_len == 52,77,102,127... */
|
||||
+ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
|
||||
+ break;
|
||||
+ /* e4 50 xx xx | size == 4 */
|
||||
+ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
|
||||
+ break;
|
||||
+ /* e4 40 xx xx | size == 48 */
|
||||
+ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ } /* end of switch (t[0]) */
|
||||
+ return 0;
|
||||
+}/*udp_search_edk*/
|
||||
+
|
||||
+
|
||||
+/*Search for UDP Gnutella commands*/
|
||||
+int
|
||||
+udp_search_gnu (unsigned char *haystack, int packet_len)
|
||||
+{
|
||||
+ unsigned char *t = haystack;
|
||||
+ t += 8;
|
||||
+
|
||||
+ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
|
||||
+ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
|
||||
+ return 0;
|
||||
+}/*udp_search_gnu*/
|
||||
+
|
||||
+
|
||||
+/*Search for UDP KaZaA commands*/
|
||||
+int
|
||||
+udp_search_kazaa (unsigned char *haystack, int packet_len)
|
||||
+{
|
||||
+ unsigned char *t = haystack;
|
||||
+
|
||||
+ if (t[packet_len-1] == 0x00){
|
||||
+ t += (packet_len - 6);
|
||||
+ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}/*udp_search_kazaa*/
|
||||
+
|
||||
+/*Search for UDP DirectConnect commands*/
|
||||
+int
|
||||
+udp_search_directconnect (unsigned char *haystack, int packet_len)
|
||||
+{
|
||||
+ unsigned char *t = haystack;
|
||||
+ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
|
||||
+ t+=8;
|
||||
+ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
|
||||
+ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}/*udp_search_directconnect*/
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*Search for UDP BitTorrent commands*/
|
||||
+int
|
||||
+udp_search_bit (unsigned char *haystack, int packet_len)
|
||||
+{
|
||||
+ switch(packet_len)
|
||||
+ {
|
||||
+ case 24:
|
||||
+ /* ^ 00 00 04 17 27 10 19 80 */
|
||||
+ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
|
||||
+ return (IPP2P_BIT * 100 + 50);
|
||||
+ break;
|
||||
+ case 44:
|
||||
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
|
||||
+ return (IPP2P_BIT * 100 + 51);
|
||||
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
|
||||
+ return (IPP2P_BIT * 100 + 61);
|
||||
+ break;
|
||||
+ case 65:
|
||||
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
|
||||
+ return (IPP2P_BIT * 100 + 52);
|
||||
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
|
||||
+ return (IPP2P_BIT * 100 + 62);
|
||||
+ break;
|
||||
+ case 67:
|
||||
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
|
||||
+ return (IPP2P_BIT * 100 + 53);
|
||||
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
|
||||
+ return (IPP2P_BIT * 100 + 63);
|
||||
+ break;
|
||||
+ case 211:
|
||||
+ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
|
||||
+ return (IPP2P_BIT * 100 + 54);
|
||||
+ break;
|
||||
+ case 29:
|
||||
+ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
|
||||
+ return (IPP2P_BIT * 100 + 55);
|
||||
+ break;
|
||||
+ case 52:
|
||||
+ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
|
||||
+ get_u32(haystack,12) == __constant_htonl(0x37502950))
|
||||
+ return (IPP2P_BIT * 100 + 80);
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* this packet does not have a constant size */
|
||||
+ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
|
||||
+ return (IPP2P_BIT * 100 + 56);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* some extra-bitcomet rules:
|
||||
+ * "d1:" [a|r] "d2:id20:"
|
||||
+ */
|
||||
+ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
|
||||
+ {
|
||||
+ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
|
||||
+ {
|
||||
+ if (memcmp(haystack+12,"d2:id20:",8)==0)
|
||||
+ return (IPP2P_BIT * 100 + 57);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+#if 0
|
||||
+ /* bitlord rules */
|
||||
+ /* packetlen must be bigger than 40 */
|
||||
+ /* first 4 bytes are zero */
|
||||
+ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
|
||||
+ {
|
||||
+ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
|
||||
+ if (get_u32(haystack, 12) == 0x00000000 &&
|
||||
+ get_u32(haystack, 16) == 0x00010000 &&
|
||||
+ get_u32(haystack, 24) == 0x00000000 )
|
||||
+ return (IPP2P_BIT * 100 + 71);
|
||||
+
|
||||
+ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
|
||||
+ if (get_u32(haystack, 12) == 0x00000001 &&
|
||||
+ get_u32(haystack, 16) == 0x000d0000 &&
|
||||
+ get_u32(haystack, 24) == 0x00000000 )
|
||||
+ return (IPP2P_BIT * 100 + 71);
|
||||
+
|
||||
+
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}/*udp_search_bit*/
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*Search for Ares commands*/
|
||||
+//#define IPP2P_DEBUG_ARES
|
||||
+int
|
||||
+search_ares (const unsigned char *payload, const u16 plen)
|
||||
+//int search_ares (unsigned char *haystack, int packet_len, int head_len)
|
||||
+{
|
||||
+// const unsigned char *t = haystack + head_len;
|
||||
+
|
||||
+ /* all ares packets start with */
|
||||
+ if (payload[1] == 0 && (plen - payload[0]) == 3)
|
||||
+ {
|
||||
+ switch (payload[2])
|
||||
+ {
|
||||
+ case 0x5a:
|
||||
+ /* ares connect */
|
||||
+ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
|
||||
+ break;
|
||||
+ case 0x09:
|
||||
+ /* ares search, min 3 chars --> 14 bytes
|
||||
+ * lets define a search can be up to 30 chars --> max 34 bytes
|
||||
+ */
|
||||
+ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
|
||||
+ break;
|
||||
+#ifdef IPP2P_DEBUG_ARES
|
||||
+ default:
|
||||
+ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
|
||||
+#endif /* IPP2P_DEBUG_ARES */
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+#if 0
|
||||
+ /* found connect packet: 03 00 5a 04 03 05 */
|
||||
+ /* new version ares 1.8: 03 00 5a xx xx 05 */
|
||||
+ if ((plen) == 6){ /* possible connect command*/
|
||||
+ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
|
||||
+ return ((IPP2P_ARES * 100) + 1);
|
||||
+ }
|
||||
+ if ((plen) == 60){ /* possible download command*/
|
||||
+ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
|
||||
+ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
|
||||
+ return ((IPP2P_ARES * 100) + 2);
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+} /*search_ares*/
|
||||
+
|
||||
+/*Search for SoulSeek commands*/
|
||||
+int
|
||||
+search_soul (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+//#define IPP2P_DEBUG_SOUL
|
||||
+ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
|
||||
+ if (get_u32(payload, 0) == (plen - 4)){
|
||||
+ const __u32 m=get_u32(payload, 4);
|
||||
+ /* match 00 yy yy 00, yy can be everything */
|
||||
+ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 1);
|
||||
+ }
|
||||
+
|
||||
+ /* next match: 01 yy 00 00 | yy can be everything */
|
||||
+ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 2);
|
||||
+ }
|
||||
+
|
||||
+ /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
|
||||
+ /* try to do this in an intelligent way */
|
||||
+ /* get all small commandos */
|
||||
+ switch(m)
|
||||
+ {
|
||||
+ case 7:
|
||||
+ case 9:
|
||||
+ case 22:
|
||||
+ case 23:
|
||||
+ case 26:
|
||||
+ case 28:
|
||||
+ case 50:
|
||||
+ case 51:
|
||||
+ case 60:
|
||||
+ case 91:
|
||||
+ case 92:
|
||||
+ case 1001:
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 3);
|
||||
+ }
|
||||
+
|
||||
+ if (m > 0 && m < 6 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 4);
|
||||
+ }
|
||||
+ if (m > 12 && m < 19 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 5);
|
||||
+ }
|
||||
+
|
||||
+ if (m > 34 && m < 38 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 6);
|
||||
+ }
|
||||
+
|
||||
+ if (m > 39 && m < 47 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 7);
|
||||
+ }
|
||||
+
|
||||
+ if (m > 61 && m < 70 )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 8);
|
||||
+ }
|
||||
+
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ }
|
||||
+
|
||||
+ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
|
||||
+ /* without size at the beginning !!! */
|
||||
+ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
|
||||
+ {
|
||||
+ __u32 y=get_u32(payload, 5);
|
||||
+ /* we need 19 chars + string */
|
||||
+ if ( (y + 19) <= (plen) )
|
||||
+ {
|
||||
+ const unsigned char *w=payload+9+y;
|
||||
+ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
|
||||
+#ifdef IPP2P_DEBUG_SOUL
|
||||
+ printk(KERN_DEBUG "Soulssek special client command recognized\n");
|
||||
+#endif /* IPP2P_DEBUG_SOUL */
|
||||
+ return ((IPP2P_SOUL * 100) + 9);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*Search for WinMX commands*/
|
||||
+int
|
||||
+search_winmx (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+//#define IPP2P_DEBUG_WINMX
|
||||
+ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
|
||||
+ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
|
||||
+ //if (packet_len < (head_len + 10)) return 0;
|
||||
+ if (plen < 10) return 0;
|
||||
+
|
||||
+ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
|
||||
+ u16 c=4;
|
||||
+ const u16 end=plen-2;
|
||||
+ u8 count=0;
|
||||
+ while (c < end)
|
||||
+ {
|
||||
+ if (payload[c]== 0x20 && payload[c+1] == 0x22)
|
||||
+ {
|
||||
+ c++;
|
||||
+ count++;
|
||||
+ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
|
||||
+ }
|
||||
+ c++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ( plen == 149 && payload[0] == '8' )
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_WINMX
|
||||
+ printk(KERN_INFO "maybe WinMX\n");
|
||||
+#endif
|
||||
+ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
|
||||
+// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
|
||||
+// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
|
||||
+ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
|
||||
+
|
||||
+ {
|
||||
+#ifdef IPP2P_DEBUG_WINMX
|
||||
+ printk(KERN_INFO "got WinMX\n");
|
||||
+#endif
|
||||
+ return ((IPP2P_WINMX * 100) + 4);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+} /*search_winmx*/
|
||||
+
|
||||
+
|
||||
+/*Search for appleJuice commands*/
|
||||
+int
|
||||
+search_apple (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*Search for BitTorrent commands*/
|
||||
+int
|
||||
+search_bittorrent (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if (plen > 20)
|
||||
+ {
|
||||
+ /* test for match 0x13+"BitTorrent protocol" */
|
||||
+ if (payload[0] == 0x13)
|
||||
+ {
|
||||
+ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
|
||||
+ }
|
||||
+
|
||||
+ /* get tracker commandos, all starts with GET /
|
||||
+ * then it can follow: scrape| announce
|
||||
+ * and then ?hash_info=
|
||||
+ */
|
||||
+ if (memcmp(payload,"GET /",5) == 0)
|
||||
+ {
|
||||
+ /* message scrape */
|
||||
+ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
|
||||
+ /* message announce */
|
||||
+ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* bitcomet encryptes the first packet, so we have to detect another
|
||||
+ * one later in the flow */
|
||||
+ /* first try failed, too many missdetections */
|
||||
+ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
|
||||
+
|
||||
+ /* second try: block request packets */
|
||||
+ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*check for Kazaa get command*/
|
||||
+int
|
||||
+search_kazaa (const unsigned char *payload, const u16 plen)
|
||||
+
|
||||
+{
|
||||
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
|
||||
+ return (IPP2P_DATA_KAZAA * 100);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*check for gnutella get command*/
|
||||
+int
|
||||
+search_gnu (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
|
||||
+ {
|
||||
+ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
|
||||
+ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*check for gnutella get commands and other typical data*/
|
||||
+int
|
||||
+search_all_gnu (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+
|
||||
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
|
||||
+ {
|
||||
+
|
||||
+ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
|
||||
+ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
|
||||
+
|
||||
+
|
||||
+ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
|
||||
+ {
|
||||
+ u16 c=8;
|
||||
+ const u16 end=plen-22;
|
||||
+ while (c < end) {
|
||||
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
|
||||
+ return ((IPP2P_GNU * 100) + 3);
|
||||
+ c++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*check for KaZaA download commands and other typical data*/
|
||||
+int
|
||||
+search_all_kazaa (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
|
||||
+ {
|
||||
+
|
||||
+ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
|
||||
+
|
||||
+ if (memcmp(payload, "GET /", 5) == 0) {
|
||||
+ u16 c = 8;
|
||||
+ const u16 end=plen-22;
|
||||
+ while (c < end) {
|
||||
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
|
||||
+ return ((IPP2P_KAZAA * 100) + 2);
|
||||
+ c++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*fast check for edonkey file segment transfer command*/
|
||||
+int
|
||||
+search_edk (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if (payload[0] != 0xe3)
|
||||
+ return 0;
|
||||
+ else {
|
||||
+ if (payload[5] == 0x47)
|
||||
+ return (IPP2P_DATA_EDK * 100);
|
||||
+ else
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*intensive but slower search for some edonkey packets including size-check*/
|
||||
+int
|
||||
+search_all_edk (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if (payload[0] != 0xe3)
|
||||
+ return 0;
|
||||
+ else {
|
||||
+ //t += head_len;
|
||||
+ const u16 cmd = get_u16(payload, 1);
|
||||
+ if (cmd == (plen - 5)) {
|
||||
+ switch (payload[5]) {
|
||||
+ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
|
||||
+ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*fast check for Direct Connect send command*/
|
||||
+int
|
||||
+search_dc (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+
|
||||
+ if (payload[0] != 0x24 )
|
||||
+ return 0;
|
||||
+ else {
|
||||
+ if (memcmp(&payload[1], "Send|", 5) == 0)
|
||||
+ return (IPP2P_DATA_DC * 100);
|
||||
+ else
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*intensive but slower check for all direct connect packets*/
|
||||
+int
|
||||
+search_all_dc (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+// unsigned char *t = haystack;
|
||||
+
|
||||
+ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
|
||||
+ {
|
||||
+ const unsigned char *t=&payload[1];
|
||||
+ /* Client-Hub-Protocol */
|
||||
+ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
|
||||
+ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
|
||||
+ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*check for mute*/
|
||||
+int
|
||||
+search_mute (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
|
||||
+ {
|
||||
+ //printk(KERN_DEBUG "size hit: %u",size);
|
||||
+ if (memcmp(payload,"PublicKey: ",11) == 0 )
|
||||
+ {
|
||||
+ return ((IPP2P_MUTE * 100) + 0);
|
||||
+
|
||||
+/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
|
||||
+ {
|
||||
+ printk(KERN_DEBUG "end pubic key hit: %u",size);
|
||||
+
|
||||
+ }*/
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* check for xdcc */
|
||||
+int
|
||||
+search_xdcc (const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ /* search in small packets only */
|
||||
+ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
|
||||
+ {
|
||||
+
|
||||
+ u16 x=10;
|
||||
+ const u16 end=plen - 13;
|
||||
+
|
||||
+ /* is seems to be a irc private massage, chedck for xdcc command */
|
||||
+ while (x < end)
|
||||
+ {
|
||||
+ if (payload[x] == ':')
|
||||
+ {
|
||||
+ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
|
||||
+ return ((IPP2P_XDCC * 100) + 0);
|
||||
+ }
|
||||
+ x++;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* search for waste */
|
||||
+int search_waste(const unsigned char *payload, const u16 plen)
|
||||
+{
|
||||
+ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
|
||||
+ return ((IPP2P_WASTE * 100) + 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static struct {
|
||||
+ int command;
|
||||
+ __u8 short_hand; /*for fucntions included in short hands*/
|
||||
+ int packet_len;
|
||||
+ int (*function_name) (const unsigned char *, const u16);
|
||||
+} matchlist[] = {
|
||||
+ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
|
||||
+// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
|
||||
+// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
|
||||
+// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
|
||||
+ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
|
||||
+// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
|
||||
+ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
|
||||
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
|
||||
+ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
|
||||
+ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
|
||||
+ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
|
||||
+ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
|
||||
+ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
|
||||
+ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
|
||||
+ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
|
||||
+ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
|
||||
+ {0,0,0,NULL}
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static struct {
|
||||
+ int command;
|
||||
+ __u8 short_hand; /*for fucntions included in short hands*/
|
||||
+ int packet_len;
|
||||
+ int (*function_name) (unsigned char *, int);
|
||||
+} udp_list[] = {
|
||||
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
|
||||
+ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
|
||||
+ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
|
||||
+ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
|
||||
+ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
|
||||
+ {0,0,0,NULL}
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static bool
|
||||
+match(const struct sk_buff *skb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ const struct xt_match *match,
|
||||
+ const void *matchinfo,
|
||||
+ int offset,
|
||||
+ unsigned int protoff,
|
||||
+ bool *hotdrop)
|
||||
+{
|
||||
+ const struct ipt_p2p_info *info = matchinfo;
|
||||
+ unsigned char *haystack;
|
||||
+ struct iphdr *ip = ip_hdr(skb);
|
||||
+ int p2p_result = 0, i = 0;
|
||||
+// int head_len;
|
||||
+ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
|
||||
+
|
||||
+ /*must not be a fragment*/
|
||||
+ if (offset) {
|
||||
+ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /*make sure that skb is linear*/
|
||||
+ if(skb_is_nonlinear(skb)){
|
||||
+ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
|
||||
+
|
||||
+ switch (ip->protocol){
|
||||
+ case IPPROTO_TCP: /*what to do with a TCP packet*/
|
||||
+ {
|
||||
+ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
|
||||
+
|
||||
+ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
|
||||
+ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
|
||||
+ if (tcph->rst) return 0; /*if RST bit is set bail out*/
|
||||
+
|
||||
+ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
|
||||
+ hlen -= tcph->doff * 4;
|
||||
+ while (matchlist[i].command) {
|
||||
+ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
|
||||
+ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
|
||||
+ (hlen > matchlist[i].packet_len)) {
|
||||
+ p2p_result = matchlist[i].function_name(haystack, hlen);
|
||||
+ if (p2p_result)
|
||||
+ {
|
||||
+ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
|
||||
+ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
|
||||
+ return p2p_result;
|
||||
+ }
|
||||
+ }
|
||||
+ i++;
|
||||
+ }
|
||||
+ return p2p_result;
|
||||
+ }
|
||||
+
|
||||
+ case IPPROTO_UDP: /*what to do with an UDP packet*/
|
||||
+ {
|
||||
+ struct udphdr *udph = (void *) ip + ip->ihl * 4;
|
||||
+
|
||||
+ while (udp_list[i].command){
|
||||
+ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
|
||||
+ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
|
||||
+ (hlen > udp_list[i].packet_len)) {
|
||||
+ p2p_result = udp_list[i].function_name(haystack, hlen);
|
||||
+ if (p2p_result){
|
||||
+ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
|
||||
+ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
|
||||
+ return p2p_result;
|
||||
+ }
|
||||
+ }
|
||||
+ i++;
|
||||
+ }
|
||||
+ return p2p_result;
|
||||
+ }
|
||||
+
|
||||
+ default: return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+static bool
|
||||
+checkentry(const char *tablename,
|
||||
+ const void *ip,
|
||||
+ const struct xt_match *match,
|
||||
+ void *matchinfo,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ /* Must specify -p tcp */
|
||||
+/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
|
||||
+ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
|
||||
+ * return 0;
|
||||
+ * }*/
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+static struct ipt_match ipp2p_match = {
|
||||
+ .name = "ipp2p",
|
||||
+ .match = &match,
|
||||
+ .family = AF_INET,
|
||||
+ .matchsize = sizeof(struct ipt_p2p_info),
|
||||
+ .checkentry = &checkentry,
|
||||
+ .me = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
|
||||
+ return xt_register_match(&ipp2p_match);
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ xt_unregister_match(&ipp2p_match);
|
||||
+ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+
|
||||
+
|
||||
Index: linux-2.6.23.1/net/ipv4/netfilter/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23.1.orig/net/ipv4/netfilter/Kconfig 2007-11-19 18:21:55.000000000 -0600
|
||||
+++ linux-2.6.23.1/net/ipv4/netfilter/Kconfig 2007-11-19 18:22:19.000000000 -0600
|
||||
@@ -63,6 +63,12 @@
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
# The matches.
|
||||
+config IP_NF_MATCH_IPP2P
|
||||
+ tristate "IPP2P"
|
||||
+ depends on IP_NF_IPTABLES
|
||||
+ help
|
||||
+ Module for matching traffic of various Peer-to-Peer applications
|
||||
+
|
||||
config IP_NF_MATCH_RECENT
|
||||
tristate '"recent" match support'
|
||||
depends on IP_NF_IPTABLES
|
||||
Index: linux-2.6.23.1/net/ipv4/netfilter/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23.1.orig/net/ipv4/netfilter/Makefile 2007-11-19 18:21:55.000000000 -0600
|
||||
+++ linux-2.6.23.1/net/ipv4/netfilter/Makefile 2007-11-19 18:23:45.000000000 -0600
|
||||
@@ -50,6 +50,8 @@
|
||||
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
|
||||
obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
|
||||
|
||||
+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
|
||||
+
|
||||
# targets
|
||||
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,247 @@
|
|||
Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_time.h
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_time.h 2007-09-21 16:24:02.000000000 +0800
|
||||
@@ -0,0 +1,18 @@
|
||||
+#ifndef __ipt_time_h_included__
|
||||
+#define __ipt_time_h_included__
|
||||
+
|
||||
+
|
||||
+struct ipt_time_info {
|
||||
+ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
|
||||
+ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
|
||||
+ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
|
||||
+
|
||||
+ /* FIXME: Keep this one for userspace iptables binary compability: */
|
||||
+ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
|
||||
+
|
||||
+ time_t date_start;
|
||||
+ time_t date_stop;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+#endif /* __ipt_time_h_included__ */
|
||||
Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_time.c
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23-rc6/net/ipv4/netfilter/ipt_time.c 2007-09-21 16:24:02.000000000 +0800
|
||||
@@ -0,0 +1,180 @@
|
||||
+/*
|
||||
+ This is a module which is used for time matching
|
||||
+ It is using some modified code from dietlibc (localtime() function)
|
||||
+ that you can find at http://www.fefe.de/dietlibc/
|
||||
+ This file is distributed under the terms of the GNU General Public
|
||||
+ License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
|
||||
+ 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
|
||||
+ 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
|
||||
+ thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
|
||||
+ 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
|
||||
+ 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
|
||||
+ added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
|
||||
+ 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
|
||||
+*/
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
+#include <linux/netfilter_ipv4/ipt_time.h>
|
||||
+#include <linux/time.h>
|
||||
+
|
||||
+MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
|
||||
+MODULE_DESCRIPTION("Match arrival timestamp/date");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+
|
||||
+struct tm
|
||||
+{
|
||||
+ int tm_sec; /* Seconds. [0-60] (1 leap second) */
|
||||
+ int tm_min; /* Minutes. [0-59] */
|
||||
+ int tm_hour; /* Hours. [0-23] */
|
||||
+ int tm_mday; /* Day. [1-31] */
|
||||
+ int tm_mon; /* Month. [0-11] */
|
||||
+ int tm_year; /* Year - 1900. */
|
||||
+ int tm_wday; /* Day of week. [0-6] */
|
||||
+ int tm_yday; /* Days in year.[0-365] */
|
||||
+ int tm_isdst; /* DST. [-1/0/1]*/
|
||||
+
|
||||
+ long int tm_gmtoff; /* we don't care, we count from GMT */
|
||||
+ const char *tm_zone; /* we don't care, we count from GMT */
|
||||
+};
|
||||
+
|
||||
+void
|
||||
+localtime(const u32 time, struct tm *r);
|
||||
+
|
||||
+static bool
|
||||
+match(const struct sk_buff *skb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ const struct xt_match *match,
|
||||
+ const void *matchinfo,
|
||||
+ int offset,
|
||||
+ unsigned int protoff,
|
||||
+ bool *hotdrop)
|
||||
+{
|
||||
+ const struct ipt_time_info *info = matchinfo; /* match info for rule */
|
||||
+ struct timeval tv;
|
||||
+ struct tm currenttime; /* time human readable */
|
||||
+ u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
|
||||
+ u_int16_t packet_time;
|
||||
+
|
||||
+ /* We might not have a timestamp, get one */
|
||||
+ if (skb->tstamp.tv64 == 0)
|
||||
+ __net_timestamp((struct sk_buff *)skb);
|
||||
+
|
||||
+ skb_get_timestamp(skb, &tv);
|
||||
+ /* First we make sure we are in the date start-stop boundaries */
|
||||
+ if ((tv.tv_sec < info->date_start) || (tv.tv_sec > info->date_stop))
|
||||
+ return 0; /* We are outside the date boundaries */
|
||||
+
|
||||
+ /* Transform the timestamp of the packet, in a human readable form */
|
||||
+ localtime(tv.tv_sec, ¤ttime);
|
||||
+
|
||||
+ /* check if we match this timestamp, we start by the days... */
|
||||
+ if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
|
||||
+ return 0; /* the day doesn't match */
|
||||
+
|
||||
+ /* ... check the time now */
|
||||
+ packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
|
||||
+ if ((packet_time < info->time_start) || (packet_time > info->time_stop))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* here we match ! */
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static bool
|
||||
+checkentry(const char *tablename,
|
||||
+ const void *ip,
|
||||
+ const struct xt_match *match,
|
||||
+ void *matchinfo,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ struct ipt_time_info *info = matchinfo; /* match info for rule */
|
||||
+
|
||||
+ /* First, check that we are in the correct hooks */
|
||||
+ if (hook_mask
|
||||
+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
|
||||
+ {
|
||||
+ printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Now check the coherence of the data ... */
|
||||
+ if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
|
||||
+ (info->time_stop > 1439))
|
||||
+ {
|
||||
+ printk(KERN_WARNING "ipt_time: invalid argument\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static struct ipt_match time_match = {
|
||||
+ .name = "time",
|
||||
+ .match = &match,
|
||||
+ .matchsize = sizeof(struct ipt_time_info),
|
||||
+ .checkentry = &checkentry,
|
||||
+ .me = THIS_MODULE
|
||||
+};
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ printk("ipt_time loading\n");
|
||||
+ return xt_register_match(&time_match);
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ xt_unregister_match(&time_match);
|
||||
+ printk("ipt_time unloaded\n");
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+
|
||||
+
|
||||
+/* The part below is borowed and modified from dietlibc */
|
||||
+
|
||||
+/* seconds per day */
|
||||
+#define SPD 24*60*60
|
||||
+
|
||||
+void
|
||||
+localtime(const u32 time, struct tm *r) {
|
||||
+ u32 i, timep;
|
||||
+ extern struct timezone sys_tz;
|
||||
+ const unsigned int __spm[12] =
|
||||
+ { 0,
|
||||
+ (31),
|
||||
+ (31+28),
|
||||
+ (31+28+31),
|
||||
+ (31+28+31+30),
|
||||
+ (31+28+31+30+31),
|
||||
+ (31+28+31+30+31+30),
|
||||
+ (31+28+31+30+31+30+31),
|
||||
+ (31+28+31+30+31+30+31+31),
|
||||
+ (31+28+31+30+31+30+31+31+30),
|
||||
+ (31+28+31+30+31+30+31+31+30+31),
|
||||
+ (31+28+31+30+31+30+31+31+30+31+30),
|
||||
+ };
|
||||
+ register u32 work;
|
||||
+
|
||||
+ timep = time - (sys_tz.tz_minuteswest * 60);
|
||||
+ work=timep%(SPD);
|
||||
+ r->tm_sec=work%60; work/=60;
|
||||
+ r->tm_min=work%60; r->tm_hour=work/60;
|
||||
+ work=timep/(SPD);
|
||||
+ r->tm_wday=(4+work)%7;
|
||||
+ for (i=1970; ; ++i) {
|
||||
+ register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
|
||||
+ if (work>k)
|
||||
+ work-=k;
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+ r->tm_year=i-1900;
|
||||
+ for (i=11; i && __spm[i]>work; --i) ;
|
||||
+ r->tm_mon=i;
|
||||
+ r->tm_mday=work-__spm[i]+1;
|
||||
+}
|
||||
Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Kconfig 2007-09-21 16:24:01.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig 2007-09-21 16:24:02.000000000 +0800
|
||||
@@ -96,6 +96,22 @@
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
+
|
||||
+config IP_NF_MATCH_TIME
|
||||
+ tristate 'TIME match support'
|
||||
+ depends on IP_NF_IPTABLES
|
||||
+ help
|
||||
+ This option adds a `time' match, which allows you
|
||||
+ to match based on the packet arrival time/date
|
||||
+ (arrival time/date at the machine which netfilter is running on) or
|
||||
+ departure time/date (for locally generated packets).
|
||||
+
|
||||
+ If you say Y here, try iptables -m time --help for more information.
|
||||
+ If you want to compile it as a module, say M here and read
|
||||
+
|
||||
+ Documentation/modules.txt. If unsure, say `N'.
|
||||
+
|
||||
+
|
||||
config IP_NF_MATCH_RECENT
|
||||
tristate "recent match support"
|
||||
depends on IP_NF_IPTABLES
|
||||
Index: linux-2.6.23-rc6/net/ipv4/netfilter/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Makefile 2007-09-21 16:24:01.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/net/ipv4/netfilter/Makefile 2007-09-21 16:24:02.000000000 +0800
|
||||
@@ -50,6 +50,7 @@
|
||||
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
|
||||
obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
|
||||
obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
|
||||
+obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
|
||||
|
||||
obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
|
||||
|
|
@ -0,0 +1,870 @@
|
|||
diff -Naurw 2.6.24/drivers/net/imq.c 2.6.24.imq/drivers/net/imq.c
|
||||
--- 2.6.24/drivers/net/imq.c 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ 2.6.24.imq/drivers/net/imq.c 2008-01-26 14:52:43.000000000 -0300
|
||||
@@ -0,0 +1,409 @@
|
||||
+/*
|
||||
+ * Pseudo-driver for the intermediate queue device.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version
|
||||
+ * 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * Authors: Patrick McHardy, <kaber@trash.net>
|
||||
+ *
|
||||
+ * The first version was written by Martin Devera, <devik@cdi.cz>
|
||||
+ *
|
||||
+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
|
||||
+ * - Update patch to 2.4.21
|
||||
+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
|
||||
+ * - Fix "Dead-loop on netdevice imq"-issue
|
||||
+ * Marcel Sebek <sebek64@post.cz>
|
||||
+ * - Update to 2.6.2-rc1
|
||||
+ *
|
||||
+ * After some time of inactivity there is a group taking care
|
||||
+ * of IMQ again: http://www.linuximq.net
|
||||
+ *
|
||||
+ *
|
||||
+ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 including
|
||||
+ * the following changes:
|
||||
+ *
|
||||
+ * - Correction of ipv6 support "+"s issue (Hasso Tepper)
|
||||
+ * - Correction of imq_init_devs() issue that resulted in
|
||||
+ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
|
||||
+ * - Addition of functionality to choose number of IMQ devices
|
||||
+ * during kernel config (Andre Correa)
|
||||
+ * - Addition of functionality to choose how IMQ hooks on
|
||||
+ * PRE and POSTROUTING (after or before NAT) (Andre Correa)
|
||||
+ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
|
||||
+ *
|
||||
+ *
|
||||
+ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
|
||||
+ * released with almost no problems. 2.6.14-x was released
|
||||
+ * with some important changes: nfcache was removed; After
|
||||
+ * some weeks of trouble we figured out that some IMQ fields
|
||||
+ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
|
||||
+ * These functions are correctly patched by this new patch version.
|
||||
+ *
|
||||
+ * Thanks for all who helped to figure out all the problems with
|
||||
+ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
|
||||
+ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
|
||||
+ * I didn't forget anybody). I apologize again for my lack of time.
|
||||
+ *
|
||||
+ * More info at: http://www.linuximq.net/ (Andre Correa)
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/rtnetlink.h>
|
||||
+#include <linux/if_arp.h>
|
||||
+#include <linux/netfilter.h>
|
||||
+#include <linux/netfilter_ipv4.h>
|
||||
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||
+ #include <linux/netfilter_ipv6.h>
|
||||
+#endif
|
||||
+#include <linux/imq.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
+
|
||||
+extern int qdisc_restart1(struct net_device *dev);
|
||||
+
|
||||
+static nf_hookfn imq_nf_hook;
|
||||
+
|
||||
+static struct nf_hook_ops imq_ingress_ipv4 = {
|
||||
+ .hook = imq_nf_hook,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = PF_INET,
|
||||
+ .hooknum = NF_IP_PRE_ROUTING,
|
||||
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||
+ .priority = NF_IP_PRI_MANGLE + 1
|
||||
+#else
|
||||
+ .priority = NF_IP_PRI_NAT_DST + 1
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct nf_hook_ops imq_egress_ipv4 = {
|
||||
+ .hook = imq_nf_hook,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = PF_INET,
|
||||
+ .hooknum = NF_IP_POST_ROUTING,
|
||||
+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
|
||||
+ .priority = NF_IP_PRI_LAST
|
||||
+#else
|
||||
+ .priority = NF_IP_PRI_NAT_SRC - 1
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||
+static struct nf_hook_ops imq_ingress_ipv6 = {
|
||||
+ .hook = imq_nf_hook,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = PF_INET6,
|
||||
+ .hooknum = NF_IP6_PRE_ROUTING,
|
||||
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||
+ .priority = NF_IP6_PRI_MANGLE + 1
|
||||
+#else
|
||||
+ .priority = NF_IP6_PRI_NAT_DST + 1
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct nf_hook_ops imq_egress_ipv6 = {
|
||||
+ .hook = imq_nf_hook,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = PF_INET6,
|
||||
+ .hooknum = NF_IP6_POST_ROUTING,
|
||||
+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
|
||||
+ .priority = NF_IP6_PRI_LAST
|
||||
+#else
|
||||
+ .priority = NF_IP6_PRI_NAT_SRC - 1
|
||||
+#endif
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+#if defined(CONFIG_IMQ_NUM_DEVS)
|
||||
+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
|
||||
+#else
|
||||
+static unsigned int numdevs = 16;
|
||||
+#endif
|
||||
+
|
||||
+static struct net_device *imq_devs;
|
||||
+
|
||||
+static struct net_device_stats *imq_get_stats(struct net_device *dev)
|
||||
+{
|
||||
+ return (struct net_device_stats *)dev->priv;
|
||||
+}
|
||||
+
|
||||
+/* called for packets kfree'd in qdiscs at places other than enqueue */
|
||||
+static void imq_skb_destructor(struct sk_buff *skb)
|
||||
+{
|
||||
+ struct nf_info *info = skb->nf_info;
|
||||
+
|
||||
+ if (info) {
|
||||
+ if (info->indev)
|
||||
+ dev_put(info->indev);
|
||||
+ if (info->outdev)
|
||||
+ dev_put(info->outdev);
|
||||
+ kfree(info);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
+{
|
||||
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
|
||||
+
|
||||
+ stats->tx_bytes += skb->len;
|
||||
+ stats->tx_packets++;
|
||||
+
|
||||
+ skb->imq_flags = 0;
|
||||
+ skb->destructor = NULL;
|
||||
+
|
||||
+ dev->trans_start = jiffies;
|
||||
+ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info, unsigned queue_num, void *data)
|
||||
+{
|
||||
+ struct net_device *dev;
|
||||
+ struct net_device_stats *stats;
|
||||
+ struct sk_buff *skb2 = NULL;
|
||||
+ struct Qdisc *q;
|
||||
+ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (index > numdevs)
|
||||
+ return -1;
|
||||
+
|
||||
+ dev = imq_devs + index;
|
||||
+ if (!(dev->flags & IFF_UP)) {
|
||||
+ skb->imq_flags = 0;
|
||||
+ nf_reinject(skb, info, NF_ACCEPT);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ dev->last_rx = jiffies;
|
||||
+
|
||||
+ if (skb->destructor) {
|
||||
+ skb2 = skb;
|
||||
+ skb = skb_clone(skb, GFP_ATOMIC);
|
||||
+ if (!skb)
|
||||
+ return -1;
|
||||
+ }
|
||||
+ skb->nf_info = info;
|
||||
+
|
||||
+ stats = (struct net_device_stats *)dev->priv;
|
||||
+ stats->rx_bytes+= skb->len;
|
||||
+ stats->rx_packets++;
|
||||
+
|
||||
+ spin_lock_bh(&dev->queue_lock);
|
||||
+ q = dev->qdisc;
|
||||
+ if (q->enqueue) {
|
||||
+ q->enqueue(skb_get(skb), q);
|
||||
+ if (skb_shared(skb)) {
|
||||
+ skb->destructor = imq_skb_destructor;
|
||||
+ kfree_skb(skb);
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ if (spin_is_locked(&dev->_xmit_lock))
|
||||
+ netif_schedule(dev);
|
||||
+ else
|
||||
+ while (!netif_queue_stopped(dev) && qdisc_restart1(dev) < 0)
|
||||
+ /* NOTHING */;
|
||||
+
|
||||
+ spin_unlock_bh(&dev->queue_lock);
|
||||
+
|
||||
+ if (skb2)
|
||||
+ kfree_skb(ret ? skb : skb2);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static struct nf_queue_handler nfqh = {
|
||||
+ .name = "imq",
|
||||
+ .outfn = imq_nf_queue,
|
||||
+};
|
||||
+
|
||||
+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
|
||||
+ const struct net_device *indev,
|
||||
+ const struct net_device *outdev,
|
||||
+ int (*okfn)(struct sk_buff *))
|
||||
+{
|
||||
+ if (pskb->imq_flags & IMQ_F_ENQUEUE)
|
||||
+ return NF_QUEUE;
|
||||
+
|
||||
+ return NF_ACCEPT;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int __init imq_init_hooks(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = nf_register_queue_handler(PF_INET, &nfqh);
|
||||
+ if (err > 0)
|
||||
+ goto err1;
|
||||
+ if ((err = nf_register_hook(&imq_ingress_ipv4)))
|
||||
+ goto err2;
|
||||
+ if ((err = nf_register_hook(&imq_egress_ipv4)))
|
||||
+ goto err3;
|
||||
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||
+ if ((err = nf_register_queue_handler(PF_INET6, &nfqh)))
|
||||
+ goto err4;
|
||||
+ if ((err = nf_register_hook(&imq_ingress_ipv6)))
|
||||
+ goto err5;
|
||||
+ if ((err = nf_register_hook(&imq_egress_ipv6)))
|
||||
+ goto err6;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||
+err6:
|
||||
+ nf_unregister_hook(&imq_ingress_ipv6);
|
||||
+err5:
|
||||
+ nf_unregister_queue_handler(PF_INET6, &nfqh);
|
||||
+err4:
|
||||
+ nf_unregister_hook(&imq_egress_ipv4);
|
||||
+#endif
|
||||
+err3:
|
||||
+ nf_unregister_hook(&imq_ingress_ipv4);
|
||||
+err2:
|
||||
+ nf_unregister_queue_handler(PF_INET, &nfqh);
|
||||
+err1:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void __exit imq_unhook(void)
|
||||
+{
|
||||
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
|
||||
+ nf_unregister_hook(&imq_ingress_ipv6);
|
||||
+ nf_unregister_hook(&imq_egress_ipv6);
|
||||
+ nf_unregister_queue_handler(PF_INET6, &nfqh);
|
||||
+#endif
|
||||
+ nf_unregister_hook(&imq_ingress_ipv4);
|
||||
+ nf_unregister_hook(&imq_egress_ipv4);
|
||||
+ nf_unregister_queue_handler(PF_INET, &nfqh);
|
||||
+}
|
||||
+
|
||||
+static int __init imq_dev_init(struct net_device *dev)
|
||||
+{
|
||||
+ dev->hard_start_xmit = imq_dev_xmit;
|
||||
+ dev->type = ARPHRD_VOID;
|
||||
+ dev->mtu = 16000;
|
||||
+ dev->tx_queue_len = 11000;
|
||||
+ dev->flags = IFF_NOARP;
|
||||
+ dev->priv = kzalloc(sizeof(struct net_device_stats), GFP_KERNEL);
|
||||
+ if (dev->priv == NULL)
|
||||
+ return -ENOMEM;
|
||||
+ dev->get_stats = imq_get_stats;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void imq_dev_uninit(struct net_device *dev)
|
||||
+{
|
||||
+ kfree(dev->priv);
|
||||
+}
|
||||
+
|
||||
+static int __init imq_init_devs(struct net *net)
|
||||
+{
|
||||
+ struct net_device *dev;
|
||||
+ int i,j;
|
||||
+ j = numdevs;
|
||||
+
|
||||
+ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
|
||||
+ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
|
||||
+ IMQ_MAX_DEVS);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ imq_devs = kzalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
|
||||
+ if (!imq_devs)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* we start counting at zero */
|
||||
+ numdevs--;
|
||||
+
|
||||
+ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
|
||||
+ strcpy(dev->name, "imq%d");
|
||||
+ dev->init = imq_dev_init;
|
||||
+ dev->uninit = imq_dev_uninit;
|
||||
+ dev->nd_net = net;
|
||||
+
|
||||
+ if (register_netdev(dev) < 0)
|
||||
+ goto err_register;
|
||||
+ }
|
||||
+ printk(KERN_INFO "IMQ starting with %u devices...\n", j);
|
||||
+ return 0;
|
||||
+
|
||||
+err_register:
|
||||
+ for (; i; i--)
|
||||
+ unregister_netdev(--dev);
|
||||
+ kfree(imq_devs);
|
||||
+ return -EIO;
|
||||
+}
|
||||
+
|
||||
+static void imq_cleanup_devs(void)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct net_device *dev = imq_devs;
|
||||
+
|
||||
+ for (i = 0; i <= numdevs; i++)
|
||||
+ unregister_netdev(dev++);
|
||||
+
|
||||
+ kfree(imq_devs);
|
||||
+}
|
||||
+
|
||||
+static __net_init int imq_init_module(struct net *net)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ if ((err = imq_init_devs(net))) {
|
||||
+ printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ if ((err = imq_init_hooks())) {
|
||||
+ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
|
||||
+ imq_cleanup_devs();
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ printk(KERN_INFO "IMQ driver loaded successfully.\n");
|
||||
+
|
||||
+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||
+ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
|
||||
+#else
|
||||
+ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
|
||||
+#endif
|
||||
+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
|
||||
+ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
|
||||
+#else
|
||||
+ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static __net_exit void imq_exit_module(struct net *net)
|
||||
+{
|
||||
+ imq_unhook();
|
||||
+ imq_cleanup_devs();
|
||||
+ printk(KERN_INFO "IMQ driver unloaded successfully.\n");
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations __net_initdata imq_net_ops = {
|
||||
+ .init = imq_init_module,
|
||||
+ .exit = imq_exit_module,
|
||||
+};
|
||||
+
|
||||
+static int __init imq_init(void)
|
||||
+{
|
||||
+ return register_pernet_device(&imq_net_ops);
|
||||
+}
|
||||
+
|
||||
+module_init(imq_init);
|
||||
+//module_exit(imq_cleanup_module);
|
||||
+
|
||||
+module_param(numdevs, int, 0);
|
||||
+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
|
||||
+MODULE_AUTHOR("http://www.linuximq.net");
|
||||
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff -Naurw 2.6.24/drivers/net/Kconfig 2.6.24.imq/drivers/net/Kconfig
|
||||
--- 2.6.24/drivers/net/Kconfig 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/drivers/net/Kconfig 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -112,6 +112,129 @@
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called eql. If unsure, say N.
|
||||
|
||||
+config IMQ
|
||||
+ tristate "IMQ (intermediate queueing device) support"
|
||||
+ depends on NETDEVICES && NETFILTER
|
||||
+ ---help---
|
||||
+ The IMQ device(s) is used as placeholder for QoS queueing
|
||||
+ disciplines. Every packet entering/leaving the IP stack can be
|
||||
+ directed through the IMQ device where it's enqueued/dequeued to the
|
||||
+ attached qdisc. This allows you to treat network devices as classes
|
||||
+ and distribute bandwidth among them. Iptables is used to specify
|
||||
+ through which IMQ device, if any, packets travel.
|
||||
+
|
||||
+ More information at: http://www.linuximq.net/
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called imq. If unsure, say N.
|
||||
+
|
||||
+choice
|
||||
+ prompt "IMQ behavior (PRE/POSTROUTING)"
|
||||
+ depends on IMQ
|
||||
+ default IMQ_BEHAVIOR_BB
|
||||
+ help
|
||||
+
|
||||
+ This settings defines how IMQ behaves in respect to its
|
||||
+ hooking in PREROUTING and POSTROUTING.
|
||||
+
|
||||
+ IMQ can work in any of the following ways:
|
||||
+
|
||||
+ PREROUTING | POSTROUTING
|
||||
+ -----------------|-------------------
|
||||
+ #1 After NAT | After NAT
|
||||
+ #2 After NAT | Before NAT
|
||||
+ #3 Before NAT | After NAT
|
||||
+ #4 Before NAT | Before NAT
|
||||
+
|
||||
+ The default behavior is to hook before NAT on PREROUTING
|
||||
+ and after NAT on POSTROUTING (#3).
|
||||
+
|
||||
+ This settings are specially usefull when trying to use IMQ
|
||||
+ to shape NATed clients.
|
||||
+
|
||||
+ More information can be found at: www.linuximq.net
|
||||
+
|
||||
+ If not sure leave the default settings alone.
|
||||
+
|
||||
+config IMQ_BEHAVIOR_AA
|
||||
+ bool "IMQ AA"
|
||||
+ help
|
||||
+ This settings defines how IMQ behaves in respect to its
|
||||
+ hooking in PREROUTING and POSTROUTING.
|
||||
+
|
||||
+ Choosing this option will make IMQ hook like this:
|
||||
+
|
||||
+ PREROUTING: After NAT
|
||||
+ POSTROUTING: After NAT
|
||||
+
|
||||
+ More information can be found at: www.linuximq.net
|
||||
+
|
||||
+ If not sure leave the default settings alone.
|
||||
+
|
||||
+config IMQ_BEHAVIOR_AB
|
||||
+ bool "IMQ AB"
|
||||
+ help
|
||||
+ This settings defines how IMQ behaves in respect to its
|
||||
+ hooking in PREROUTING and POSTROUTING.
|
||||
+
|
||||
+ Choosing this option will make IMQ hook like this:
|
||||
+
|
||||
+ PREROUTING: After NAT
|
||||
+ POSTROUTING: Before NAT
|
||||
+
|
||||
+ More information can be found at: www.linuximq.net
|
||||
+
|
||||
+ If not sure leave the default settings alone.
|
||||
+
|
||||
+config IMQ_BEHAVIOR_BA
|
||||
+ bool "IMQ BA"
|
||||
+ help
|
||||
+ This settings defines how IMQ behaves in respect to its
|
||||
+ hooking in PREROUTING and POSTROUTING.
|
||||
+
|
||||
+ Choosing this option will make IMQ hook like this:
|
||||
+
|
||||
+ PREROUTING: Before NAT
|
||||
+ POSTROUTING: After NAT
|
||||
+
|
||||
+ More information can be found at: www.linuximq.net
|
||||
+
|
||||
+ If not sure leave the default settings alone.
|
||||
+
|
||||
+config IMQ_BEHAVIOR_BB
|
||||
+ bool "IMQ BB"
|
||||
+ help
|
||||
+ This settings defines how IMQ behaves in respect to its
|
||||
+ hooking in PREROUTING and POSTROUTING.
|
||||
+
|
||||
+ Choosing this option will make IMQ hook like this:
|
||||
+
|
||||
+ PREROUTING: Before NAT
|
||||
+ POSTROUTING: Before NAT
|
||||
+
|
||||
+ More information can be found at: www.linuximq.net
|
||||
+
|
||||
+ If not sure leave the default settings alone.
|
||||
+
|
||||
+endchoice
|
||||
+
|
||||
+config IMQ_NUM_DEVS
|
||||
+
|
||||
+ int "Number of IMQ devices"
|
||||
+ range 2 16
|
||||
+ depends on IMQ
|
||||
+ default "16"
|
||||
+ help
|
||||
+
|
||||
+ This settings defines how many IMQ devices will be
|
||||
+ created.
|
||||
+
|
||||
+ The default value is 16.
|
||||
+
|
||||
+ More information can be found at: www.linuximq.net
|
||||
+
|
||||
+ If not sure leave the default settings alone.
|
||||
+
|
||||
config TUN
|
||||
tristate "Universal TUN/TAP device driver support"
|
||||
select CRC32
|
||||
diff -Naurw 2.6.24/drivers/net/Makefile 2.6.24.imq/drivers/net/Makefile
|
||||
--- 2.6.24/drivers/net/Makefile 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/drivers/net/Makefile 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -139,6 +139,7 @@
|
||||
obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
|
||||
|
||||
obj-$(CONFIG_DUMMY) += dummy.o
|
||||
+obj-$(CONFIG_IMQ) += imq.o
|
||||
obj-$(CONFIG_IFB) += ifb.o
|
||||
obj-$(CONFIG_MACVLAN) += macvlan.o
|
||||
obj-$(CONFIG_DE600) += de600.o
|
||||
diff -Naurw 2.6.24/include/linux/imq.h 2.6.24.imq/include/linux/imq.h
|
||||
--- 2.6.24/include/linux/imq.h 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ 2.6.24.imq/include/linux/imq.h 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -0,0 +1,9 @@
|
||||
+#ifndef _IMQ_H
|
||||
+#define _IMQ_H
|
||||
+
|
||||
+#define IMQ_MAX_DEVS 16
|
||||
+
|
||||
+#define IMQ_F_IFMASK 0x7f
|
||||
+#define IMQ_F_ENQUEUE 0x80
|
||||
+
|
||||
+#endif /* _IMQ_H */
|
||||
diff -Naurw 2.6.24/include/linux/netfilter_ipv4/ipt_IMQ.h 2.6.24.imq/include/linux/netfilter_ipv4/ipt_IMQ.h
|
||||
--- 2.6.24/include/linux/netfilter_ipv4/ipt_IMQ.h 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ 2.6.24.imq/include/linux/netfilter_ipv4/ipt_IMQ.h 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef _IPT_IMQ_H
|
||||
+#define _IPT_IMQ_H
|
||||
+
|
||||
+struct ipt_imq_info {
|
||||
+ unsigned int todev; /* target imq device */
|
||||
+};
|
||||
+
|
||||
+#endif /* _IPT_IMQ_H */
|
||||
diff -Naurw 2.6.24/include/linux/netfilter_ipv6/ip6t_IMQ.h 2.6.24.imq/include/linux/netfilter_ipv6/ip6t_IMQ.h
|
||||
--- 2.6.24/include/linux/netfilter_ipv6/ip6t_IMQ.h 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ 2.6.24.imq/include/linux/netfilter_ipv6/ip6t_IMQ.h 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef _IP6T_IMQ_H
|
||||
+#define _IP6T_IMQ_H
|
||||
+
|
||||
+struct ip6t_imq_info {
|
||||
+ unsigned int todev; /* target imq device */
|
||||
+};
|
||||
+
|
||||
+#endif /* _IP6T_IMQ_H */
|
||||
diff -Naurw 2.6.24/include/linux/skbuff.h 2.6.24.imq/include/linux/skbuff.h
|
||||
--- 2.6.24/include/linux/skbuff.h 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/include/linux/skbuff.h 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -295,6 +295,10 @@
|
||||
struct nf_conntrack *nfct;
|
||||
struct sk_buff *nfct_reasm;
|
||||
#endif
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+ unsigned char imq_flags;
|
||||
+ struct nf_info *nf_info;
|
||||
+#endif
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
struct nf_bridge_info *nf_bridge;
|
||||
#endif
|
||||
@@ -1728,6 +1732,10 @@
|
||||
dst->nfct_reasm = src->nfct_reasm;
|
||||
nf_conntrack_get_reasm(src->nfct_reasm);
|
||||
#endif
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+ dst->imq_flags = src->imq_flags;
|
||||
+ dst->nf_info = src->nf_info;
|
||||
+#endif
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
dst->nf_bridge = src->nf_bridge;
|
||||
nf_bridge_get(src->nf_bridge);
|
||||
diff -Naurw 2.6.24/net/core/dev.c 2.6.24.imq/net/core/dev.c
|
||||
--- 2.6.24/net/core/dev.c 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/net/core/dev.c 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -95,6 +95,9 @@
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+#include <linux/imq.h>
|
||||
+#endif
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/stat.h>
|
||||
@@ -1533,7 +1536,11 @@
|
||||
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
if (likely(!skb->next)) {
|
||||
- if (!list_empty(&ptype_all))
|
||||
+ if (!list_empty(&ptype_all)
|
||||
+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
|
||||
+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
|
||||
+#endif
|
||||
+ )
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
|
||||
if (netif_needs_gso(dev, skb)) {
|
||||
diff -Naurw 2.6.24/net/ipv4/netfilter/ipt_IMQ.c 2.6.24.imq/net/ipv4/netfilter/ipt_IMQ.c
|
||||
--- 2.6.24/net/ipv4/netfilter/ipt_IMQ.c 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ 2.6.24.imq/net/ipv4/netfilter/ipt_IMQ.c 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * This target marks packets to be enqueued to an imq device
|
||||
+ */
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
+#include <linux/netfilter_ipv4/ipt_IMQ.h>
|
||||
+#include <linux/imq.h>
|
||||
+
|
||||
+static unsigned int imq_target(struct sk_buff *pskb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ unsigned int hooknum,
|
||||
+ const struct xt_target *target,
|
||||
+ const void *targinfo)
|
||||
+{
|
||||
+ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
|
||||
+
|
||||
+ pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE;
|
||||
+
|
||||
+ return XT_CONTINUE;
|
||||
+}
|
||||
+
|
||||
+static bool imq_checkentry(const char *tablename,
|
||||
+ const void *e,
|
||||
+ const struct xt_target *target,
|
||||
+ void *targinfo,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ struct ipt_imq_info *mr;
|
||||
+
|
||||
+ mr = (struct ipt_imq_info*)targinfo;
|
||||
+
|
||||
+ if (mr->todev > IMQ_MAX_DEVS) {
|
||||
+ printk(KERN_WARNING
|
||||
+ "IMQ: invalid device specified, highest is %u\n",
|
||||
+ IMQ_MAX_DEVS);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static struct xt_target ipt_imq_reg = {
|
||||
+ .name = "IMQ",
|
||||
+ .family = AF_INET,
|
||||
+ .target = imq_target,
|
||||
+ .targetsize = sizeof(struct ipt_imq_info),
|
||||
+ .checkentry = imq_checkentry,
|
||||
+ .me = THIS_MODULE,
|
||||
+ .table = "mangle"
|
||||
+};
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ return xt_register_target(&ipt_imq_reg);
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ xt_unregister_target(&ipt_imq_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+
|
||||
+MODULE_AUTHOR("http://www.linuximq.net");
|
||||
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff -Naurw 2.6.24/net/ipv4/netfilter/Kconfig 2.6.24.imq/net/ipv4/netfilter/Kconfig
|
||||
--- 2.6.24/net/ipv4/netfilter/Kconfig 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/net/ipv4/netfilter/Kconfig 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -311,6 +311,17 @@
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
+config IP_NF_TARGET_IMQ
|
||||
+ tristate "IMQ target support"
|
||||
+ depends on IP_NF_MANGLE
|
||||
+ help
|
||||
+ This option adds a `IMQ' target which is used to specify if and
|
||||
+ to which IMQ device packets should get enqueued/dequeued.
|
||||
+
|
||||
+ For more information visit: http://www.linuximq.net/
|
||||
+
|
||||
+ To compile it as a module, choose M here. If unsure, say N.
|
||||
+
|
||||
config IP_NF_TARGET_ECN
|
||||
tristate "ECN target support"
|
||||
depends on IP_NF_MANGLE
|
||||
diff -Naurw 2.6.24/net/ipv4/netfilter/Makefile 2.6.24.imq/net/ipv4/netfilter/Makefile
|
||||
--- 2.6.24/net/ipv4/netfilter/Makefile 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/net/ipv4/netfilter/Makefile 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -54,6 +54,7 @@
|
||||
obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
|
||||
+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
|
||||
diff -Naurw 2.6.24/net/ipv6/netfilter/ip6t_IMQ.c 2.6.24.imq/net/ipv6/netfilter/ip6t_IMQ.c
|
||||
--- 2.6.24/net/ipv6/netfilter/ip6t_IMQ.c 1969-12-31 21:00:00.000000000 -0300
|
||||
+++ 2.6.24.imq/net/ipv6/netfilter/ip6t_IMQ.c 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * This target marks packets to be enqueued to an imq device
|
||||
+ */
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
|
||||
+#include <linux/imq.h>
|
||||
+
|
||||
+static unsigned int imq_target(struct sk_buff *pskb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ unsigned int hooknum,
|
||||
+ const struct xt_target *target,
|
||||
+ const void *targinfo)
|
||||
+{
|
||||
+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
|
||||
+
|
||||
+ pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE;
|
||||
+
|
||||
+ return XT_CONTINUE;
|
||||
+}
|
||||
+
|
||||
+static bool imq_checkentry(const char *tablename,
|
||||
+ const void *entry,
|
||||
+ const struct xt_target *target,
|
||||
+ void *targinfo,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ struct ip6t_imq_info *mr;
|
||||
+
|
||||
+ mr = (struct ip6t_imq_info*)targinfo;
|
||||
+
|
||||
+ if (mr->todev > IMQ_MAX_DEVS) {
|
||||
+ printk(KERN_WARNING
|
||||
+ "IMQ: invalid device specified, highest is %u\n",
|
||||
+ IMQ_MAX_DEVS);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static struct xt_target ip6t_imq_reg = {
|
||||
+ .name = "IMQ",
|
||||
+ .family = AF_INET6,
|
||||
+ .target = imq_target,
|
||||
+ .targetsize = sizeof(struct ip6t_imq_info),
|
||||
+ .table = "mangle",
|
||||
+ .checkentry = imq_checkentry,
|
||||
+ .me = THIS_MODULE
|
||||
+};
|
||||
+
|
||||
+static int __init init(void)
|
||||
+{
|
||||
+ return xt_register_target(&ip6t_imq_reg);
|
||||
+}
|
||||
+
|
||||
+static void __exit fini(void)
|
||||
+{
|
||||
+ xt_unregister_target(&ip6t_imq_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(init);
|
||||
+module_exit(fini);
|
||||
+
|
||||
+MODULE_AUTHOR("http://www.linuximq.net");
|
||||
+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff -Naurw 2.6.24/net/ipv6/netfilter/Kconfig 2.6.24.imq/net/ipv6/netfilter/Kconfig
|
||||
--- 2.6.24/net/ipv6/netfilter/Kconfig 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/net/ipv6/netfilter/Kconfig 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -173,6 +173,15 @@
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
+config IP6_NF_TARGET_IMQ
|
||||
+ tristate "IMQ target support"
|
||||
+ depends on IP6_NF_MANGLE
|
||||
+ help
|
||||
+ This option adds a `IMQ' target which is used to specify if and
|
||||
+ to which imq device packets should get enqueued/dequeued.
|
||||
+
|
||||
+ To compile it as a module, choose M here. If unsure, say N.
|
||||
+
|
||||
config IP6_NF_TARGET_HL
|
||||
tristate 'HL (hoplimit) target support'
|
||||
depends on IP6_NF_MANGLE
|
||||
diff -Naurw 2.6.24/net/ipv6/netfilter/Makefile 2.6.24.imq/net/ipv6/netfilter/Makefile
|
||||
--- 2.6.24/net/ipv6/netfilter/Makefile 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/net/ipv6/netfilter/Makefile 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -6,6 +6,7 @@
|
||||
obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
|
||||
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
|
||||
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
|
||||
+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
|
||||
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
|
||||
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
|
||||
|
||||
diff -Naurw 2.6.24/net/sched/sch_generic.c 2.6.24.imq/net/sched/sch_generic.c
|
||||
--- 2.6.24/net/sched/sch_generic.c 2008-01-24 19:58:37.000000000 -0300
|
||||
+++ 2.6.24.imq/net/sched/sch_generic.c 2008-01-26 15:00:11.000000000 -0300
|
||||
@@ -176,6 +176,13 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int qdisc_restart1(struct net_device *dev)
|
||||
+{
|
||||
+ return qdisc_restart(dev);
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL(qdisc_restart1);
|
||||
+
|
||||
void __qdisc_run(struct net_device *dev)
|
||||
{
|
||||
do {
|
|
@ -0,0 +1,866 @@
|
|||
Index: linux-2.6.24/include/linux/netfilter/oot_conntrack.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/include/linux/netfilter/oot_conntrack.h
|
||||
@@ -0,0 +1,5 @@
|
||||
+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
|
||||
+# include <linux/netfilter_ipv4/ip_conntrack.h>
|
||||
+#else /* linux-2.6.20+ */
|
||||
+# include <net/netfilter/nf_nat_rule.h>
|
||||
+#endif
|
||||
Index: linux-2.6.24/include/linux/netfilter/oot_trans.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/include/linux/netfilter/oot_trans.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+/* Out of tree workarounds */
|
||||
+#include <linux/version.h>
|
||||
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
+# define HAVE_MATCHINFOSIZE 1
|
||||
+# define HAVE_TARGUSERINFO 1
|
||||
+# define HAVE_TARGINFOSIZE 1
|
||||
+#endif
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
|
||||
+# define nfmark mark
|
||||
+#endif
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
|
||||
+# define tcp_v4_check(tcph, tcph_sz, s, d, csp) \
|
||||
+ tcp_v4_check((tcph_sz), (s), (d), (csp))
|
||||
+#endif
|
||||
Index: linux-2.6.24/include/linux/netfilter/xt_CHAOS.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/include/linux/netfilter/xt_CHAOS.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+#ifndef _LINUX_NETFILTER_XT_CHAOS_H
|
||||
+#define _LINUX_NETFILTER_XT_CHAOS_H 1
|
||||
+
|
||||
+enum xt_chaos_target_variant {
|
||||
+ XTCHAOS_NORMAL,
|
||||
+ XTCHAOS_TARPIT,
|
||||
+ XTCHAOS_DELUDE,
|
||||
+};
|
||||
+
|
||||
+struct xt_chaos_target_info {
|
||||
+ uint8_t variant;
|
||||
+};
|
||||
+
|
||||
+#endif /* _LINUX_NETFILTER_XT_CHAOS_H */
|
||||
Index: linux-2.6.24/include/linux/netfilter/xt_portscan.h
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/include/linux/netfilter/xt_portscan.h
|
||||
@@ -0,0 +1,8 @@
|
||||
+#ifndef _LINUX_NETFILTER_XT_PORTSCAN_H
|
||||
+#define _LINUX_NETFILTER_XT_PORTSCAN_H 1
|
||||
+
|
||||
+struct xt_portscan_match_info {
|
||||
+ uint8_t match_stealth, match_syn, match_cn, match_gr;
|
||||
+};
|
||||
+
|
||||
+#endif /* _LINUX_NETFILTER_XT_PORTSCAN_H */
|
||||
Index: linux-2.6.24/net/netfilter/find_match.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/net/netfilter/find_match.c
|
||||
@@ -0,0 +1,39 @@
|
||||
+/*
|
||||
+ xt_request_find_match
|
||||
+ by Jan Engelhardt <jengelh [at] gmx de>, 2006 - 2007
|
||||
+
|
||||
+ Based upon linux-2.6.18.5/net/netfilter/x_tables.c:
|
||||
+ Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License version 2 as
|
||||
+ published by the Free Software Foundation.
|
||||
+*/
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/netfilter_arp.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <linux/netfilter/x_tables.h>
|
||||
+
|
||||
+/*
|
||||
+ * Yeah this code is sub-optimal, but the function is missing in
|
||||
+ * mainline so far. -jengelh
|
||||
+ */
|
||||
+static struct xt_match *xt_request_find_match_lo(int af, const char *name,
|
||||
+ u8 revision)
|
||||
+{
|
||||
+ static const char *const xt_prefix[] = {
|
||||
+ [AF_INET] = "ip",
|
||||
+ [AF_INET6] = "ip6",
|
||||
+ [NF_ARP] = "arp",
|
||||
+ };
|
||||
+ struct xt_match *match;
|
||||
+
|
||||
+ match = try_then_request_module(xt_find_match(af, name, revision),
|
||||
+ "%st_%s", xt_prefix[af], name);
|
||||
+ if (IS_ERR(match) || match == NULL)
|
||||
+ return NULL;
|
||||
+
|
||||
+ return match;
|
||||
+}
|
||||
+
|
||||
+/* In case it goes into mainline, let this out-of-tree package compile */
|
||||
+#define xt_request_find_match xt_request_find_match_lo
|
||||
Index: linux-2.6.24/net/netfilter/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.24.orig/net/netfilter/Kconfig
|
||||
+++ linux-2.6.24/net/netfilter/Kconfig
|
||||
@@ -265,6 +265,14 @@ config NETFILTER_XTABLES
|
||||
|
||||
# alphabetically ordered list of targets
|
||||
|
||||
+config NETFILTER_XT_TARGET_CHAOS
|
||||
+ tristate '"CHAOS" target support'
|
||||
+ depends on NETFILTER_XTABLES
|
||||
+ help
|
||||
+ This option adds a `CHAOS' target.
|
||||
+
|
||||
+ To compile it as a module, choose M here. If unsure, say N.
|
||||
+
|
||||
config NETFILTER_XT_TARGET_CLASSIFY
|
||||
tristate '"CLASSIFY" target support'
|
||||
depends on NETFILTER_XTABLES
|
||||
@@ -292,6 +300,14 @@ config NETFILTER_XT_TARGET_CONNMARK
|
||||
<file:Documentation/kbuild/modules.txt>. The module will be called
|
||||
ipt_CONNMARK.ko. If unsure, say `N'.
|
||||
|
||||
+config NETFILTER_XT_TARGET_DELUDE
|
||||
+ tristate '"DELUDE" target support'
|
||||
+ depends on NETFILTER_XTABLES
|
||||
+ help
|
||||
+ This option adds a `DELUDE' target.
|
||||
+
|
||||
+ To compile it as a module, choose M here. If unsure, say N.
|
||||
+
|
||||
config NETFILTER_XT_TARGET_DSCP
|
||||
tristate '"DSCP" target support'
|
||||
depends on NETFILTER_XTABLES
|
||||
@@ -556,6 +572,14 @@ config NETFILTER_XT_MATCH_POLICY
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
+config NETFILTER_XT_MATCH_PORTSCAN
|
||||
+ tristate '"portscan" match support'
|
||||
+ depends on NETFILTER_XTABLES
|
||||
+ help
|
||||
+ This option adds a 'portscan' match support.
|
||||
+
|
||||
+ To compile it as a module, choose M here. If unsure, say N.
|
||||
+
|
||||
config NETFILTER_XT_MATCH_MULTIPORT
|
||||
tristate "Multiple port match support"
|
||||
depends on NETFILTER_XTABLES
|
||||
Index: linux-2.6.24/net/netfilter/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.24.orig/net/netfilter/Makefile
|
||||
+++ linux-2.6.24/net/netfilter/Makefile
|
||||
@@ -49,6 +49,8 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
|
||||
+obj-$(CONFIG_NETFILTER_XT_TARGET_CHAOS) += xt_CHAOS.o
|
||||
+obj-$(CONFIG_NETFILTER_XT_TARGET_DELUDE) += xt_DELUDE.o
|
||||
|
||||
# matches
|
||||
obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
|
||||
@@ -79,3 +81,4 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STRING)
|
||||
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
|
||||
obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
|
||||
obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
|
||||
+obj-$(CONFIG_NETFILTER_XT_MATCH_PORTSCAN) += xt_portscan.o
|
||||
Index: linux-2.6.24/net/netfilter/xt_CHAOS.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/net/netfilter/xt_CHAOS.c
|
||||
@@ -0,0 +1,200 @@
|
||||
+/*
|
||||
+ * CHAOS target for netfilter
|
||||
+ * Copyright © CC Computer Consultants GmbH, 2006 - 2007
|
||||
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License; either version
|
||||
+ * 2 or 3 as published by the Free Software Foundation.
|
||||
+ */
|
||||
+#include <linux/icmp.h>
|
||||
+#include <linux/in.h>
|
||||
+#include <linux/ip.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/stat.h>
|
||||
+#include <linux/netfilter/x_tables.h>
|
||||
+#include <linux/netfilter/xt_tcpudp.h>
|
||||
+#include <linux/netfilter_ipv4/ipt_REJECT.h>
|
||||
+#include <net/ip.h>
|
||||
+#if defined(_LOCAL)
|
||||
+# include "xt_CHAOS.h"
|
||||
+# include "find_match.c"
|
||||
+#elif defined(CONFIG_NETFILTER_XT_TARGET_CHAOS) || \
|
||||
+ defined(CONFIG_NETFILTER_XT_TARGET_CHAOS_MODULE)
|
||||
+# include <linux/netfilter/xt_CHAOS.h>
|
||||
+# include "find_match.c"
|
||||
+#else
|
||||
+# include "xt_CHAOS.h"
|
||||
+# include "find_match.c"
|
||||
+#endif
|
||||
+#define PFX KBUILD_MODNAME ": "
|
||||
+
|
||||
+/* Module parameters */
|
||||
+static unsigned int reject_percentage = ~0U * .01;
|
||||
+static unsigned int delude_percentage = ~0U * .0101;
|
||||
+module_param(reject_percentage, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(delude_percentage, uint, S_IRUGO | S_IWUSR);
|
||||
+
|
||||
+/* References to other matches/targets */
|
||||
+static struct xt_match *xm_tcp;
|
||||
+static struct xt_target *xt_delude, *xt_reject, *xt_tarpit;
|
||||
+
|
||||
+static int have_delude, have_tarpit;
|
||||
+
|
||||
+/* Static data for other matches/targets */
|
||||
+static const struct ipt_reject_info reject_params = {
|
||||
+ .with = ICMP_HOST_UNREACH,
|
||||
+};
|
||||
+
|
||||
+static const struct xt_tcp tcp_params = {
|
||||
+ .spts = {0, ~0},
|
||||
+ .dpts = {0, ~0},
|
||||
+};
|
||||
+
|
||||
+/* CHAOS functions */
|
||||
+static void xt_chaos_total(const struct xt_chaos_target_info *info,
|
||||
+ struct sk_buff *skb, const struct net_device *in,
|
||||
+ const struct net_device *out, unsigned int hooknum)
|
||||
+{
|
||||
+ const struct iphdr *iph = ip_hdr(skb);
|
||||
+ const int protoff = 4 * iph->ihl;
|
||||
+ const int offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
+ const struct xt_target *destiny;
|
||||
+ bool hotdrop = false, ret;
|
||||
+
|
||||
+ ret = xm_tcp->match(skb, in, out, xm_tcp, &tcp_params,
|
||||
+ offset, protoff, &hotdrop);
|
||||
+ if (!ret || hotdrop || (unsigned int)net_random() > delude_percentage)
|
||||
+ return;
|
||||
+
|
||||
+ destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude;
|
||||
+ destiny->target(skb, in, out, hooknum, destiny, NULL);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static unsigned int chaos_tg(struct sk_buff *skb,
|
||||
+ const struct net_device *in, const struct net_device *out,
|
||||
+ unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
+{
|
||||
+ /*
|
||||
+ * Equivalent to:
|
||||
+ * -A chaos -m statistic --mode random --probability \
|
||||
+ * $reject_percentage -j REJECT --reject-with host-unreach;
|
||||
+ * -A chaos -p tcp -m statistic --mode random --probability \
|
||||
+ * $delude_percentage -j DELUDE;
|
||||
+ * -A chaos -j DROP;
|
||||
+ */
|
||||
+ const struct xt_chaos_target_info *info = targinfo;
|
||||
+ const struct iphdr *iph = ip_hdr(skb);
|
||||
+
|
||||
+ if ((unsigned int)net_random() <= reject_percentage)
|
||||
+ return xt_reject->target(skb, in, out, hooknum, target,
|
||||
+ &reject_params);
|
||||
+
|
||||
+ /* TARPIT/DELUDE may not be called from the OUTPUT chain */
|
||||
+ if (iph->protocol == IPPROTO_TCP &&
|
||||
+ info->variant != XTCHAOS_NORMAL && hooknum != NF_IP_LOCAL_OUT)
|
||||
+ xt_chaos_total(info, skb, in, out, hooknum);
|
||||
+
|
||||
+ return NF_DROP;
|
||||
+}
|
||||
+
|
||||
+static bool chaos_tg_check(const char *tablename, const void *entry,
|
||||
+ const struct xt_target *target, void *targinfo, unsigned int hook_mask)
|
||||
+{
|
||||
+ const struct xt_chaos_target_info *info = targinfo;
|
||||
+
|
||||
+ if (info->variant == XTCHAOS_DELUDE && !have_delude) {
|
||||
+ printk(KERN_WARNING PFX "Error: Cannot use --delude when "
|
||||
+ "DELUDE module not available\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (info->variant == XTCHAOS_TARPIT && !have_tarpit) {
|
||||
+ printk(KERN_WARNING PFX "Error: Cannot use --tarpit when "
|
||||
+ "TARPIT module not available\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static struct xt_target chaos_tg_reg = {
|
||||
+ .name = "CHAOS",
|
||||
+ .family = AF_INET,
|
||||
+ .table = "filter",
|
||||
+ .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) |
|
||||
+ (1 << NF_IP_LOCAL_OUT),
|
||||
+ .checkentry = chaos_tg_check,
|
||||
+ .target = chaos_tg,
|
||||
+ .targetsize = sizeof(struct xt_chaos_target_info),
|
||||
+ .me = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init chaos_tg_init(void)
|
||||
+{
|
||||
+ int ret = -EINVAL;
|
||||
+
|
||||
+ xm_tcp = xt_request_find_match(AF_INET, "tcp", 0);
|
||||
+ if (xm_tcp == NULL) {
|
||||
+ printk(KERN_WARNING PFX "Error: Could not find or load "
|
||||
+ "\"tcp\" match\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ xt_reject = xt_request_find_target(AF_INET, "REJECT", 0);
|
||||
+ if (xt_reject == NULL) {
|
||||
+ printk(KERN_WARNING PFX "Error: Could not find or load "
|
||||
+ "\"REJECT\" target\n");
|
||||
+ goto out2;
|
||||
+ }
|
||||
+
|
||||
+ xt_tarpit = xt_request_find_target(AF_INET, "TARPIT", 0);
|
||||
+ have_tarpit = xt_tarpit != NULL;
|
||||
+ if (!have_tarpit)
|
||||
+ printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
+ "\"TARPIT\" target\n");
|
||||
+
|
||||
+ xt_delude = xt_request_find_target(AF_INET, "DELUDE", 0);
|
||||
+ have_delude = xt_delude != NULL;
|
||||
+ if (!have_delude)
|
||||
+ printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
+ "\"DELUDE\" target\n");
|
||||
+
|
||||
+ if ((ret = xt_register_target(&chaos_tg_reg)) != 0) {
|
||||
+ printk(KERN_WARNING PFX "xt_register_target returned "
|
||||
+ "error %d\n", ret);
|
||||
+ goto out3;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ out3:
|
||||
+ if (have_delude)
|
||||
+ module_put(xt_delude->me);
|
||||
+ if (have_tarpit)
|
||||
+ module_put(xt_tarpit->me);
|
||||
+ module_put(xt_reject->me);
|
||||
+ out2:
|
||||
+ module_put(xm_tcp->me);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void __exit chaos_tg_exit(void)
|
||||
+{
|
||||
+ xt_unregister_target(&chaos_tg_reg);
|
||||
+ module_put(xm_tcp->me);
|
||||
+ module_put(xt_reject->me);
|
||||
+ if (have_delude)
|
||||
+ module_put(xt_delude->me);
|
||||
+ if (have_tarpit)
|
||||
+ module_put(xt_tarpit->me);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+module_init(chaos_tg_init);
|
||||
+module_exit(chaos_tg_exit);
|
||||
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
+MODULE_DESCRIPTION("netfilter \"CHAOS\" target");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("ipt_CHAOS");
|
||||
Index: linux-2.6.24/net/netfilter/xt_DELUDE.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/net/netfilter/xt_DELUDE.c
|
||||
@@ -0,0 +1,197 @@
|
||||
+/*
|
||||
+ * DELUDE target
|
||||
+ * Copyright © CC Computer Consultants GmbH, 2007
|
||||
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
|
||||
+ *
|
||||
+ * Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
|
||||
+ * (C) 1999-2001 Paul `Rusty' Russell
|
||||
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
|
||||
+ *
|
||||
+ * xt_DELUDE acts like REJECT, but does reply with SYN-ACK on SYN.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/ip.h>
|
||||
+#include <linux/tcp.h>
|
||||
+#include <linux/netfilter/x_tables.h>
|
||||
+#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
+# include <linux/netfilter_bridge.h>
|
||||
+#endif
|
||||
+#include <net/tcp.h>
|
||||
+#define PFX KBUILD_MODNAME ": "
|
||||
+
|
||||
+static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
+{
|
||||
+ struct tcphdr _otcph, *oth, *tcph;
|
||||
+ unsigned int addr_type;
|
||||
+ struct sk_buff *nskb;
|
||||
+ u_int16_t tmp_port;
|
||||
+ u_int32_t tmp_addr;
|
||||
+ struct iphdr *niph;
|
||||
+ bool needs_ack;
|
||||
+
|
||||
+ /* IP header checks: fragment. */
|
||||
+ if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
|
||||
+ return;
|
||||
+
|
||||
+ oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
|
||||
+ sizeof(_otcph), &_otcph);
|
||||
+ if (oth == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /* No RST for RST. */
|
||||
+ if (oth->rst)
|
||||
+ return;
|
||||
+
|
||||
+ /* Check checksum */
|
||||
+ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
|
||||
+ return;
|
||||
+
|
||||
+ /* We need a linear, writeable skb. We also need to expand
|
||||
+ headroom in case hh_len of incoming interface < hh_len of
|
||||
+ outgoing interface */
|
||||
+ nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb),
|
||||
+ GFP_ATOMIC);
|
||||
+ if (!nskb)
|
||||
+ return;
|
||||
+
|
||||
+ /* This packet will not be the same as the other: clear nf fields */
|
||||
+ nf_reset(nskb);
|
||||
+ nskb->mark = 0;
|
||||
+ skb_init_secmark(nskb);
|
||||
+
|
||||
+ skb_shinfo(nskb)->gso_size = 0;
|
||||
+ skb_shinfo(nskb)->gso_segs = 0;
|
||||
+ skb_shinfo(nskb)->gso_type = 0;
|
||||
+
|
||||
+ tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb));
|
||||
+
|
||||
+ /* Swap source and dest */
|
||||
+ niph = ip_hdr(nskb);
|
||||
+ tmp_addr = niph->saddr;
|
||||
+ niph->saddr = niph->daddr;
|
||||
+ niph->daddr = tmp_addr;
|
||||
+ tmp_port = tcph->source;
|
||||
+ tcph->source = tcph->dest;
|
||||
+ tcph->dest = tmp_port;
|
||||
+
|
||||
+ /* Truncate to length (no data) */
|
||||
+ tcph->doff = sizeof(struct tcphdr) / 4;
|
||||
+ skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
|
||||
+ niph->tot_len = htons(nskb->len);
|
||||
+
|
||||
+ if (oth->syn && !oth->ack && !oth->rst && !oth->fin) {
|
||||
+ /* DELUDE essential part */
|
||||
+ tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
|
||||
+ oldskb->len - ip_hdrlen(oldskb) -
|
||||
+ (oth->doff << 2));
|
||||
+ tcph->seq = false;
|
||||
+ tcph->ack = true;
|
||||
+ } else {
|
||||
+ if (!tcph->ack) {
|
||||
+ needs_ack = true;
|
||||
+ tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn +
|
||||
+ oth->fin + oldskb->len -
|
||||
+ ip_hdrlen(oldskb) - (oth->doff<<2));
|
||||
+ tcph->seq = false;
|
||||
+ } else {
|
||||
+ needs_ack = false;
|
||||
+ tcph->seq = oth->ack_seq;
|
||||
+ tcph->ack_seq = false;
|
||||
+ }
|
||||
+
|
||||
+ /* Reset flags */
|
||||
+ ((u_int8_t *)tcph)[13] = 0;
|
||||
+ tcph->rst = true;
|
||||
+ tcph->ack = needs_ack;
|
||||
+ }
|
||||
+
|
||||
+ tcph->window = 0;
|
||||
+ tcph->urg_ptr = 0;
|
||||
+
|
||||
+ /* Adjust TCP checksum */
|
||||
+ tcph->check = 0;
|
||||
+ tcph->check = tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
|
||||
+ niph->daddr, csum_partial((char *)tcph,
|
||||
+ sizeof(struct tcphdr), 0));
|
||||
+
|
||||
+ /* Set DF, id = 0 */
|
||||
+ niph->frag_off = htons(IP_DF);
|
||||
+ niph->id = 0;
|
||||
+
|
||||
+ addr_type = RTN_UNSPEC;
|
||||
+#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
+ if (hook != NF_IP_FORWARD || (nskb->nf_bridge != NULL &&
|
||||
+ nskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
+#else
|
||||
+ if (hook != NF_IP_FORWARD)
|
||||
+#endif
|
||||
+ addr_type = RTN_LOCAL;
|
||||
+
|
||||
+ if (ip_route_me_harder(nskb, addr_type))
|
||||
+ goto free_nskb;
|
||||
+
|
||||
+ nskb->ip_summed = CHECKSUM_NONE;
|
||||
+
|
||||
+ /* Adjust IP TTL */
|
||||
+ niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
|
||||
+
|
||||
+ /* Adjust IP checksum */
|
||||
+ niph->check = 0;
|
||||
+ niph->check = ip_fast_csum(skb_network_header(nskb), niph->ihl);
|
||||
+
|
||||
+ /* "Never happens" */
|
||||
+ if (nskb->len > dst_mtu(nskb->dst))
|
||||
+ goto free_nskb;
|
||||
+
|
||||
+ nf_ct_attach(nskb, oldskb);
|
||||
+
|
||||
+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
|
||||
+ dst_output);
|
||||
+ return;
|
||||
+
|
||||
+ free_nskb:
|
||||
+ kfree_skb(nskb);
|
||||
+}
|
||||
+
|
||||
+static unsigned int delude_tg(struct sk_buff *skb,
|
||||
+ const struct net_device *in, const struct net_device *out,
|
||||
+ unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
+{
|
||||
+ /* WARNING: This code causes reentry within iptables.
|
||||
+ This means that the iptables jump stack is now crap. We
|
||||
+ must return an absolute verdict. --RR */
|
||||
+ delude_send_reset(skb, hooknum);
|
||||
+ return NF_DROP;
|
||||
+}
|
||||
+
|
||||
+static struct xt_target delude_tg_reg = {
|
||||
+ .name = "DELUDE",
|
||||
+ .family = AF_INET,
|
||||
+ .table = "filter",
|
||||
+ .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD),
|
||||
+ .target = delude_tg,
|
||||
+ .proto = IPPROTO_TCP,
|
||||
+ .me = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init delude_tg_init(void)
|
||||
+{
|
||||
+ return xt_register_target(&delude_tg_reg);
|
||||
+}
|
||||
+
|
||||
+static void __exit delude_tg_exit(void)
|
||||
+{
|
||||
+ xt_unregister_target(&delude_tg_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(delude_tg_init);
|
||||
+module_exit(delude_tg_exit);
|
||||
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
+MODULE_DESCRIPTION("netfilter \"DELUDE\" target");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("ipt_DELUDE");
|
||||
Index: linux-2.6.24/net/netfilter/xt_portscan.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.24/net/netfilter/xt_portscan.c
|
||||
@@ -0,0 +1,269 @@
|
||||
+/*
|
||||
+ * portscan match for netfilter
|
||||
+ * Copyright © CC Computer Consultants GmbH, 2006 - 2007
|
||||
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License; either version
|
||||
+ * 2 or 3 as published by the Free Software Foundation.
|
||||
+ */
|
||||
+#include <linux/in.h>
|
||||
+#include <linux/ip.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/stat.h>
|
||||
+#include <linux/tcp.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/version.h>
|
||||
+#include <linux/netfilter/x_tables.h>
|
||||
+#include <linux/netfilter/xt_tcpudp.h>
|
||||
+#include <net/netfilter/nf_nat_rule.h>
|
||||
+#if defined(_LOCAL)
|
||||
+# include "xt_portscan.h"
|
||||
+#elif defined(CONFIG_NETFILTER_XT_MATCH_PORTSCAN) || \
|
||||
+ defined(CONFIG_NETFILTER_XT_MATCH_PORTSCAN_MODULE)
|
||||
+# include <linux/netfilter/xt_portscan.h>
|
||||
+#else
|
||||
+# include "xt_portscan.h"
|
||||
+#endif
|
||||
+#define PFX KBUILD_MODNAME ": "
|
||||
+
|
||||
+enum {
|
||||
+ TCP_FLAGS_ALL3 = TCP_FLAG_FIN | TCP_FLAG_RST | TCP_FLAG_SYN,
|
||||
+ TCP_FLAGS_ALL4 = TCP_FLAGS_ALL3 | TCP_FLAG_ACK,
|
||||
+ TCP_FLAGS_ALL6 = TCP_FLAGS_ALL4 | TCP_FLAG_PSH | TCP_FLAG_URG,
|
||||
+};
|
||||
+
|
||||
+/* Module parameters */
|
||||
+static unsigned int
|
||||
+ connmark_mask = ~0,
|
||||
+ packet_mask = ~0,
|
||||
+ mark_seen = 0x9,
|
||||
+ mark_synrcv = 0x1,
|
||||
+ mark_closed = 0x2,
|
||||
+ mark_synscan = 0x3,
|
||||
+ mark_estab1 = 0x4,
|
||||
+ mark_estab2 = 0x5,
|
||||
+ mark_cnscan = 0x6,
|
||||
+ mark_grscan = 0x7,
|
||||
+ mark_valid = 0x8;
|
||||
+
|
||||
+module_param(connmark_mask, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(packet_mask, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_seen, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_synrcv, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_closed, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_synscan, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_estab1, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_estab2, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_cnscan, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_grscan, uint, S_IRUGO | S_IWUSR);
|
||||
+module_param(mark_valid, uint, S_IRUGO | S_IWUSR);
|
||||
+MODULE_PARM_DESC(connmark_mask, "only set specified bits in connection mark");
|
||||
+MODULE_PARM_DESC(packet_mask, "only set specified bits in packet mark");
|
||||
+MODULE_PARM_DESC(mark_seen, "nfmark value for packet-seen state");
|
||||
+MODULE_PARM_DESC(mark_synrcv, "connmark value for SYN Received state");
|
||||
+MODULE_PARM_DESC(mark_closed, "connmark value for closed state");
|
||||
+MODULE_PARM_DESC(mark_synscan, "connmark value for SYN Scan state");
|
||||
+MODULE_PARM_DESC(mark_estab1, "connmark value for Established-1 state");
|
||||
+MODULE_PARM_DESC(mark_estab2, "connmark value for Established-2 state");
|
||||
+MODULE_PARM_DESC(mark_cnscan, "connmark value for Connect Scan state");
|
||||
+MODULE_PARM_DESC(mark_grscan, "connmark value for Grab Scan state");
|
||||
+MODULE_PARM_DESC(mark_valid, "connmark value for Valid state");
|
||||
+
|
||||
+/* TCP flag functions */
|
||||
+static inline bool tflg_ack4(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) == TCP_FLAG_ACK;
|
||||
+}
|
||||
+
|
||||
+static inline bool tflg_ack6(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL6) == TCP_FLAG_ACK;
|
||||
+}
|
||||
+
|
||||
+static inline bool tflg_fin(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL3) == TCP_FLAG_FIN;
|
||||
+}
|
||||
+
|
||||
+static inline bool tflg_rst(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL3) == TCP_FLAG_RST;
|
||||
+}
|
||||
+
|
||||
+static inline bool tflg_rstack(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) ==
|
||||
+ (TCP_FLAG_ACK | TCP_FLAG_RST);
|
||||
+}
|
||||
+
|
||||
+static inline bool tflg_syn(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) == TCP_FLAG_SYN;
|
||||
+}
|
||||
+
|
||||
+static inline bool tflg_synack(const struct tcphdr *th)
|
||||
+{
|
||||
+ return (tcp_flag_word(th) & TCP_FLAGS_ALL4) ==
|
||||
+ (TCP_FLAG_SYN | TCP_FLAG_ACK);
|
||||
+}
|
||||
+
|
||||
+/* portscan functions */
|
||||
+static inline bool portscan_mt_stealth(const struct tcphdr *th)
|
||||
+{
|
||||
+ /*
|
||||
+ * "Connection refused" replies to our own probes must not be matched.
|
||||
+ */
|
||||
+ if (tflg_rstack(th))
|
||||
+ return false;
|
||||
+
|
||||
+ if (tflg_rst(th) && printk_ratelimit()) {
|
||||
+ printk(KERN_WARNING PFX "Warning: Pure RST received\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * -p tcp ! --syn -m conntrack --ctstate INVALID: Looking for non-start
|
||||
+ * packets that are not associated with any connection -- this will
|
||||
+ * match most scan types (NULL, XMAS, FIN) and ridiculous flag
|
||||
+ * combinations (SYN-RST, SYN-FIN, SYN-FIN-RST, FIN-RST, etc.).
|
||||
+ */
|
||||
+ return !tflg_syn(th);
|
||||
+}
|
||||
+
|
||||
+static inline unsigned int portscan_mt_full(int mark,
|
||||
+ enum ip_conntrack_info ctstate, bool loopback, const struct tcphdr *tcph,
|
||||
+ unsigned int payload_len)
|
||||
+{
|
||||
+ if (mark == mark_estab2) {
|
||||
+ /*
|
||||
+ * -m connmark --mark $ESTAB2
|
||||
+ */
|
||||
+ if (tflg_ack4(tcph) && payload_len == 0)
|
||||
+ return mark; /* keep mark */
|
||||
+ else if (tflg_rst(tcph) || tflg_fin(tcph))
|
||||
+ return mark_grscan;
|
||||
+ else
|
||||
+ return mark_valid;
|
||||
+ } else if (mark == mark_estab1) {
|
||||
+ /*
|
||||
+ * -m connmark --mark $ESTAB1
|
||||
+ */
|
||||
+ if (tflg_rst(tcph) || tflg_fin(tcph))
|
||||
+ return mark_cnscan;
|
||||
+ else if (!loopback && tflg_ack4(tcph) && payload_len == 0)
|
||||
+ return mark_estab2;
|
||||
+ else
|
||||
+ return mark_valid;
|
||||
+ } else if (mark == mark_synrcv) {
|
||||
+ /*
|
||||
+ * -m connmark --mark $SYN
|
||||
+ */
|
||||
+ if (loopback && tflg_synack(tcph))
|
||||
+ return mark; /* keep mark */
|
||||
+ else if (loopback && tflg_rstack(tcph))
|
||||
+ return mark_closed;
|
||||
+ else if (tflg_ack6(tcph))
|
||||
+ return mark_estab1;
|
||||
+ else
|
||||
+ return mark_synscan;
|
||||
+ } else if (ctstate == IP_CT_NEW && tflg_syn(tcph)) {
|
||||
+ /*
|
||||
+ * -p tcp --syn --ctstate NEW
|
||||
+ */
|
||||
+ return mark_synrcv;
|
||||
+ }
|
||||
+ return mark;
|
||||
+}
|
||||
+
|
||||
+static bool portscan_mt(const struct sk_buff *skb,
|
||||
+ const struct net_device *in, const struct net_device *out,
|
||||
+ const struct xt_match *match, const void *matchinfo, int offset,
|
||||
+ unsigned int protoff, bool *hotdrop)
|
||||
+{
|
||||
+ const struct xt_portscan_match_info *info = matchinfo;
|
||||
+ enum ip_conntrack_info ctstate;
|
||||
+ const struct tcphdr *tcph;
|
||||
+ struct nf_conn *ctdata;
|
||||
+ struct tcphdr tcph_buf;
|
||||
+
|
||||
+ tcph = skb_header_pointer(skb, protoff, sizeof(tcph_buf), &tcph_buf);
|
||||
+ if (tcph == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ /* Check for invalid packets: -m conntrack --ctstate INVALID */
|
||||
+ if ((ctdata = nf_ct_get(skb, &ctstate)) == NULL) {
|
||||
+ if (info->match_stealth)
|
||||
+ return portscan_mt_stealth(tcph);
|
||||
+ /*
|
||||
+ * If @ctdata is NULL, we cannot match the other scan
|
||||
+ * types, return.
|
||||
+ */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If -m portscan was previously applied to this packet, the rules we
|
||||
+ * simulate must not be run through again. And for speedup, do not call
|
||||
+ * it either when the connection is already VALID.
|
||||
+ */
|
||||
+ if ((ctdata->mark & connmark_mask) == mark_valid ||
|
||||
+ (skb->mark & packet_mask) != mark_seen) {
|
||||
+ unsigned int n;
|
||||
+
|
||||
+ n = portscan_mt_full(ctdata->mark & connmark_mask, ctstate,
|
||||
+ (in->flags & IFF_LOOPBACK) == IFF_LOOPBACK, tcph,
|
||||
+ skb->len - protoff - 4 * tcph->doff);
|
||||
+
|
||||
+ ctdata->mark = (ctdata->mark & ~connmark_mask) | n;
|
||||
+ ((struct sk_buff *)skb)->mark =
|
||||
+ (skb->mark & ~packet_mask) ^ mark_seen;
|
||||
+ }
|
||||
+
|
||||
+ return (info->match_syn && ctdata->mark == mark_synscan) ||
|
||||
+ (info->match_cn && ctdata->mark == mark_cnscan) ||
|
||||
+ (info->match_gr && ctdata->mark == mark_grscan);
|
||||
+}
|
||||
+
|
||||
+static bool portscan_mt_check(const char *tablename, const void *entry,
|
||||
+ const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
|
||||
+{
|
||||
+ const struct xt_portscan_match_info *info = matchinfo;
|
||||
+
|
||||
+ if ((info->match_stealth & ~1) || (info->match_syn & ~1) ||
|
||||
+ (info->match_cn & ~1) || (info->match_gr & ~1)) {
|
||||
+ printk(KERN_WARNING PFX "Invalid flags\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static struct xt_match portscan_mt_reg __read_mostly = {
|
||||
+ .name = "portscan",
|
||||
+ .family = AF_INET,
|
||||
+ .match = portscan_mt,
|
||||
+ .checkentry = portscan_mt_check,
|
||||
+ .matchsize = sizeof(struct xt_portscan_match_info),
|
||||
+ .proto = IPPROTO_TCP,
|
||||
+ .me = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init portscan_mt_init(void)
|
||||
+{
|
||||
+ return xt_register_match(&portscan_mt_reg);
|
||||
+}
|
||||
+
|
||||
+static void __exit portscan_mt_exit(void)
|
||||
+{
|
||||
+ xt_unregister_match(&portscan_mt_reg);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+module_init(portscan_mt_init);
|
||||
+module_exit(portscan_mt_exit);
|
||||
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
+MODULE_DESCRIPTION("netfilter \"portscan\" match");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("ipt_portscan");
|
||||
Index: linux-2.6.24/drivers/char/random.c
|
||||
===================================================================
|
||||
--- linux-2.6.24.orig/drivers/char/random.c
|
||||
+++ linux-2.6.24/drivers/char/random.c
|
||||
@@ -1564,6 +1564,8 @@ __u32 secure_tcp_sequence_number(__be32
|
||||
return seq;
|
||||
}
|
||||
|
||||
+EXPORT_SYMBOL(secure_tcp_sequence_number);
|
||||
+
|
||||
/* Generate secure starting point for ephemeral IPV4 transport port search */
|
||||
u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
|
||||
{
|
|
@ -0,0 +1,324 @@
|
|||
Index: linux-2.6.23/net/netfilter/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/net/netfilter/Kconfig
|
||||
+++ linux-2.6.23/net/netfilter/Kconfig
|
||||
@@ -401,6 +401,23 @@ config NETFILTER_XT_TARGET_CONNSECMARK
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
+config NETFILTER_XT_TARGET_TARPIT
|
||||
+ tristate '"TARPIT" target support'
|
||||
+ depends on NETFILTER_XTABLES
|
||||
+ ---help---
|
||||
+ Adds a TARPIT target to iptables, which captures and holds
|
||||
+ incoming TCP connections using no local per-connection resources.
|
||||
+ Connections are accepted, but immediately switched to the persist
|
||||
+ state (0 byte window), in which the remote side stops sending data
|
||||
+ and asks to continue every 60-240 seconds. Attempts to close the
|
||||
+ connection are ignored, forcing the remote side to time out the
|
||||
+ connection in 12-24 minutes.
|
||||
+
|
||||
+ This offers similar functionality to LaBrea
|
||||
+ <http://www.hackbusters.net/LaBrea/>, but does not require dedicated
|
||||
+ hardware or IPs. Any TCP port that you would normally DROP or REJECT
|
||||
+ can instead become a tarpit.
|
||||
+
|
||||
config NETFILTER_XT_TARGET_TCPMSS
|
||||
tristate '"TCPMSS" target support'
|
||||
depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
|
||||
Index: linux-2.6.23/net/netfilter/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/net/netfilter/Makefile
|
||||
+++ linux-2.6.23/net/netfilter/Makefile
|
||||
@@ -49,6 +49,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG)
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
|
||||
+obj-$(CONFIG_NETFILTER_XT_TARGET_TARPIT) += xt_TARPIT.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
|
||||
|
||||
Index: linux-2.6.23/net/netfilter/xt_TARPIT.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ linux-2.6.23/net/netfilter/xt_TARPIT.c
|
||||
@@ -0,0 +1,279 @@
|
||||
+/*
|
||||
+ * Kernel module to capture and hold incoming TCP connections using
|
||||
+ * no local per-connection resources.
|
||||
+ *
|
||||
+ * Based on ipt_REJECT.c and offering functionality similar to
|
||||
+ * LaBrea <http://www.hackbusters.net/LaBrea/>.
|
||||
+ *
|
||||
+ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
+ *
|
||||
+ * Goal:
|
||||
+ * - Allow incoming TCP connections to be established.
|
||||
+ * - Passing data should result in the connection being switched to the
|
||||
+ * persist state (0 byte window), in which the remote side stops sending
|
||||
+ * data and asks to continue every 60 seconds.
|
||||
+ * - Attempts to shut down the connection should be ignored completely, so
|
||||
+ * the remote side ends up having to time it out.
|
||||
+ *
|
||||
+ * This means:
|
||||
+ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
|
||||
+ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
|
||||
+ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
|
||||
+ */
|
||||
+
|
||||
+#include <linux/version.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/ip.h>
|
||||
+#include <net/ip.h>
|
||||
+#include <net/tcp.h>
|
||||
+#include <net/icmp.h>
|
||||
+struct in_device;
|
||||
+#include <net/route.h>
|
||||
+#include <linux/random.h>
|
||||
+#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
+
|
||||
+#if 0
|
||||
+#define DEBUGP printk
|
||||
+#else
|
||||
+#define DEBUGP(format, args...)
|
||||
+#endif
|
||||
+
|
||||
+/* Stolen from ip_finish_output2 */
|
||||
+static int ip_direct_send(struct sk_buff *skb)
|
||||
+{
|
||||
+ struct dst_entry *dst = skb->dst;
|
||||
+
|
||||
+ if (dst->hh != NULL)
|
||||
+ return neigh_hh_output(dst->hh, skb);
|
||||
+ else if (dst->neighbour != NULL)
|
||||
+ return dst->neighbour->output(skb);
|
||||
+
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
|
||||
+
|
||||
+ kfree_skb(skb);
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Send reply */
|
||||
+static void tarpit_tcp(const struct sk_buff *oskb, struct rtable *ort,
|
||||
+ unsigned int local)
|
||||
+{
|
||||
+ struct sk_buff *nskb;
|
||||
+ struct rtable *nrt;
|
||||
+ struct tcphdr *otcph, *ntcph;
|
||||
+ struct flowi fl = {};
|
||||
+ unsigned int otcplen;
|
||||
+ u_int16_t tmp;
|
||||
+
|
||||
+ const struct iphdr *oiph = ip_hdr(oskb);
|
||||
+ struct iphdr *niph;
|
||||
+
|
||||
+ /* A truncated TCP header is not going to be useful */
|
||||
+ if (oskb->len < ip_hdrlen(oskb) + sizeof(struct tcphdr))
|
||||
+ return;
|
||||
+
|
||||
+ otcph = (void *)oiph + ip_hdrlen(oskb);
|
||||
+ otcplen = oskb->len - ip_hdrlen(oskb);
|
||||
+
|
||||
+ /* No replies for RST or FIN */
|
||||
+ if (otcph->rst || otcph->fin)
|
||||
+ return;
|
||||
+
|
||||
+ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
|
||||
+ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
|
||||
+ return;
|
||||
+
|
||||
+ /* Check checksum. */
|
||||
+ if (tcp_v4_check(otcplen, oiph->saddr, oiph->daddr,
|
||||
+ csum_partial((char *)otcph, otcplen, 0)) != 0)
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * Copy skb (even if skb is about to be dropped, we cannot just
|
||||
+ * clone it because there may be other things, such as tcpdump,
|
||||
+ * interested in it)
|
||||
+ */
|
||||
+ nskb = skb_copy(oskb, GFP_ATOMIC);
|
||||
+ if (nskb == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ niph = ip_hdr(nskb);
|
||||
+
|
||||
+ /* This packet will not be the same as the other: clear nf fields */
|
||||
+ nf_conntrack_put(nskb->nfct);
|
||||
+ nskb->nfct = NULL;
|
||||
+#ifdef CONFIG_NETFILTER_DEBUG
|
||||
+ nskb->nf_debug = 0;
|
||||
+#endif
|
||||
+
|
||||
+ ntcph = (void *)niph + ip_hdrlen(nskb);
|
||||
+
|
||||
+ /* Truncate to length (no data) */
|
||||
+ ntcph->doff = sizeof(struct tcphdr)/4;
|
||||
+ skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
|
||||
+ niph->tot_len = htons(nskb->len);
|
||||
+
|
||||
+ /* Swap source and dest */
|
||||
+ niph->daddr = xchg(&niph->saddr, niph->daddr);
|
||||
+ tmp = ntcph->source;
|
||||
+ ntcph->source = ntcph->dest;
|
||||
+ ntcph->dest = tmp;
|
||||
+
|
||||
+ /* Use supplied sequence number or make a new one */
|
||||
+ ntcph->seq = otcph->ack ? otcph->ack_seq
|
||||
+ : htonl(secure_tcp_sequence_number(niph->saddr,
|
||||
+ niph->daddr,
|
||||
+ ntcph->source,
|
||||
+ ntcph->dest));
|
||||
+
|
||||
+ /* Our SYN-ACKs must have a >0 window */
|
||||
+ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
|
||||
+
|
||||
+ ntcph->urg_ptr = 0;
|
||||
+
|
||||
+ /* Reset flags */
|
||||
+ ((u_int8_t *)ntcph)[13] = 0;
|
||||
+
|
||||
+ if (otcph->syn && otcph->ack) {
|
||||
+ ntcph->rst = 1;
|
||||
+ ntcph->ack_seq = 0;
|
||||
+ } else {
|
||||
+ ntcph->syn = otcph->syn;
|
||||
+ ntcph->ack = 1;
|
||||
+ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
|
||||
+ }
|
||||
+
|
||||
+ /* Adjust TCP checksum */
|
||||
+ ntcph->check = 0;
|
||||
+ ntcph->check = tcp_v4_check(sizeof(struct tcphdr),
|
||||
+ niph->saddr,
|
||||
+ niph->daddr,
|
||||
+ csum_partial((char *)ntcph,
|
||||
+ sizeof(struct tcphdr), 0));
|
||||
+
|
||||
+ fl.nl_u.ip4_u.daddr = niph->daddr;
|
||||
+ fl.nl_u.ip4_u.saddr = local ? niph->saddr : 0;
|
||||
+ fl.nl_u.ip4_u.tos = RT_TOS(niph->tos) | RTO_CONN;
|
||||
+ fl.oif = 0;
|
||||
+
|
||||
+ if (ip_route_output_key(&nrt, &fl))
|
||||
+ goto free_nskb;
|
||||
+
|
||||
+ dst_release(nskb->dst);
|
||||
+ nskb->dst = &nrt->u.dst;
|
||||
+
|
||||
+ /* Adjust IP TTL */
|
||||
+ niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
|
||||
+
|
||||
+ /* Set DF, id = 0 */
|
||||
+ niph->frag_off = htons(IP_DF);
|
||||
+ niph->id = 0;
|
||||
+
|
||||
+ /* Adjust IP checksum */
|
||||
+ niph->check = 0;
|
||||
+ niph->check = ip_fast_csum((unsigned char *)niph, niph->ihl);
|
||||
+
|
||||
+ /* "Never happens" */
|
||||
+ if (nskb->len > dst_mtu(nskb->dst))
|
||||
+ goto free_nskb;
|
||||
+
|
||||
+ ip_direct_send(nskb);
|
||||
+ return;
|
||||
+
|
||||
+ free_nskb:
|
||||
+ kfree_skb(nskb);
|
||||
+}
|
||||
+
|
||||
+static unsigned int xt_tarpit_target(struct sk_buff *skb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ unsigned int hooknum,
|
||||
+ const struct xt_target *target,
|
||||
+ const void *targinfo)
|
||||
+{
|
||||
+ const struct iphdr *iph = ip_hdr(skb);
|
||||
+ struct rtable *rt = (void *)skb->dst;
|
||||
+
|
||||
+ /* Do we have an input route cache entry? */
|
||||
+ if (rt == NULL)
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ /* No replies to physical multicast/broadcast */
|
||||
+ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ /* Now check at the protocol level */
|
||||
+ if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ /*
|
||||
+ * Our naive response construction does not deal with IP
|
||||
+ * options, and probably should not try.
|
||||
+ */
|
||||
+ if (iph->ihl * 4 != sizeof(struct iphdr))
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ /* We are not interested in fragments */
|
||||
+ if (iph->frag_off & htons(IP_OFFSET))
|
||||
+ return NF_DROP;
|
||||
+
|
||||
+ tarpit_tcp(skb, rt, hooknum == NF_IP_LOCAL_IN);
|
||||
+ return NF_DROP;
|
||||
+}
|
||||
+
|
||||
+static bool xt_tarpit_check(const char *tablename, const void *entry,
|
||||
+ const struct xt_target *target, void *targinfo,
|
||||
+ unsigned int hook_mask)
|
||||
+{
|
||||
+ bool invalid;
|
||||
+
|
||||
+ if (strcmp(tablename, "raw") == 0 && hook_mask == NF_IP_PRE_ROUTING)
|
||||
+ return true;
|
||||
+ if (strcmp(tablename, "filter") != 0)
|
||||
+ return false;
|
||||
+ invalid = hook_mask & ~((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD));
|
||||
+ return !invalid;
|
||||
+}
|
||||
+
|
||||
+static struct xt_target xt_tarpit_reg = {
|
||||
+ .name = "TARPIT",
|
||||
+ .family = AF_INET,
|
||||
+ .proto = IPPROTO_TCP,
|
||||
+ .target = xt_tarpit_target,
|
||||
+ .checkentry = xt_tarpit_check,
|
||||
+ .me = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init xt_tarpit_init(void)
|
||||
+{
|
||||
+ return xt_register_target(&xt_tarpit_reg);
|
||||
+}
|
||||
+
|
||||
+static void __exit xt_tarpit_exit(void)
|
||||
+{
|
||||
+ xt_unregister_target(&xt_tarpit_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(xt_tarpit_init);
|
||||
+module_exit(xt_tarpit_exit);
|
||||
+MODULE_DESCRIPTION("netfilter xt_TARPIT target module");
|
||||
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("ipt_TARPIT");
|
|
@ -0,0 +1,22 @@
|
|||
Index: linux-2.6.23-rc6/net/netfilter/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/net/netfilter/Kconfig 2007-09-21 16:24:03.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/net/netfilter/Kconfig 2007-09-21 16:24:04.000000000 +0800
|
||||
@@ -143,7 +143,7 @@
|
||||
|
||||
config NF_CONNTRACK_H323
|
||||
tristate "H.323 protocol support"
|
||||
- depends on NF_CONNTRACK && (IPV6 || IPV6=n)
|
||||
+ depends on NF_CONNTRACK
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
|
||||
@@ -403,7 +403,7 @@
|
||||
|
||||
config NETFILTER_XT_TARGET_TCPMSS
|
||||
tristate '"TCPMSS" target support'
|
||||
- depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
|
||||
+ depends on NETFILTER_XTABLES
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
---help---
|
||||
This option adds a `TCPMSS' target, which allows you to alter the
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,799 @@
|
|||
diff -Naur linux-2.6.21.5.orig/include/linux/pkt_sched.h linux-2.6.21.5/include/linux/pkt_sched.h
|
||||
--- linux-2.6.21.5.orig/include/linux/pkt_sched.h 2007-06-11 11:37:06.000000000 -0700
|
||||
+++ linux-2.6.21.5/include/linux/pkt_sched.h 2007-06-22 22:53:46.000000000 -0700
|
||||
@@ -146,8 +146,37 @@
|
||||
*
|
||||
* The only reason for this is efficiency, it is possible
|
||||
* to change these parameters in compile time.
|
||||
+ *
|
||||
+ * If you need to play with these values, use esfq instead.
|
||||
*/
|
||||
|
||||
+/* ESFQ section */
|
||||
+
|
||||
+enum
|
||||
+{
|
||||
+ /* traditional */
|
||||
+ TCA_SFQ_HASH_CLASSIC,
|
||||
+ TCA_SFQ_HASH_DST,
|
||||
+ TCA_SFQ_HASH_SRC,
|
||||
+ TCA_SFQ_HASH_FWMARK,
|
||||
+ /* conntrack */
|
||||
+ TCA_SFQ_HASH_CTORIGDST,
|
||||
+ TCA_SFQ_HASH_CTORIGSRC,
|
||||
+ TCA_SFQ_HASH_CTREPLDST,
|
||||
+ TCA_SFQ_HASH_CTREPLSRC,
|
||||
+ TCA_SFQ_HASH_CTNATCHG,
|
||||
+};
|
||||
+
|
||||
+struct tc_esfq_qopt
|
||||
+{
|
||||
+ unsigned quantum; /* Bytes per round allocated to flow */
|
||||
+ int perturb_period; /* Period of hash perturbation */
|
||||
+ __u32 limit; /* Maximal packets in queue */
|
||||
+ unsigned divisor; /* Hash divisor */
|
||||
+ unsigned flows; /* Maximal number of flows */
|
||||
+ unsigned hash_kind; /* Hash function to use for flow identification */
|
||||
+};
|
||||
+
|
||||
/* RED section */
|
||||
|
||||
enum
|
||||
diff -Naur linux-2.6.21.5.orig/net/sched/Kconfig linux-2.6.21.5/net/sched/Kconfig
|
||||
--- linux-2.6.21.5.orig/net/sched/Kconfig 2007-06-11 11:37:06.000000000 -0700
|
||||
+++ linux-2.6.21.5/net/sched/Kconfig 2007-06-23 14:11:02.000000000 -0700
|
||||
@@ -189,6 +189,37 @@
|
||||
To compile this code as a module, choose M here: the
|
||||
module will be called sch_sfq.
|
||||
|
||||
+config NET_SCH_ESFQ
|
||||
+ tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
|
||||
+ ---help---
|
||||
+ Say Y here if you want to use the Enhanced Stochastic Fairness
|
||||
+ Queueing (ESFQ) packet scheduling algorithm for some of your network
|
||||
+ devices or as a leaf discipline for a classful qdisc such as HTB or
|
||||
+ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
|
||||
+ references to the SFQ algorithm).
|
||||
+
|
||||
+ This is an enchanced SFQ version which allows you to control some
|
||||
+ hardcoded values in the SFQ scheduler.
|
||||
+
|
||||
+ ESFQ also adds control of the hash function used to identify packet
|
||||
+ flows. The original SFQ discipline hashes by connection; ESFQ add
|
||||
+ several other hashing methods, such as by src IP or by dst IP, which
|
||||
+ can be more fair to users in some networking situations.
|
||||
+
|
||||
+ To compile this code as a module, choose M here: the
|
||||
+ module will be called sch_esfq.
|
||||
+
|
||||
+config NET_SCH_ESFQ_NFCT
|
||||
+ bool "Connection Tracking Hash Types"
|
||||
+ depends on NET_SCH_ESFQ && NF_CONNTRACK
|
||||
+ ---help---
|
||||
+ Say Y here to enable support for hashing based on netfilter connection
|
||||
+ tracking information. This is useful for a router that is also using
|
||||
+ NAT to connect privately-addressed hosts to the Internet. If you want
|
||||
+ to provide fair distribution of upstream bandwidth, ESFQ must use
|
||||
+ connection tracking information, since all outgoing packets will share
|
||||
+ the same source address.
|
||||
+
|
||||
config NET_SCH_TEQL
|
||||
tristate "True Link Equalizer (TEQL)"
|
||||
---help---
|
||||
diff -Naur linux-2.6.21.5.orig/net/sched/Makefile linux-2.6.21.5/net/sched/Makefile
|
||||
--- linux-2.6.21.5.orig/net/sched/Makefile 2007-06-11 11:37:06.000000000 -0700
|
||||
+++ linux-2.6.21.5/net/sched/Makefile 2007-06-22 22:53:46.000000000 -0700
|
||||
@@ -23,6 +23,7 @@
|
||||
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
|
||||
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
|
||||
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
|
||||
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
|
||||
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
|
||||
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
|
||||
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
|
||||
diff -Naur linux-2.6.21.5.orig/net/sched/sch_esfq.c linux-2.6.21.5/net/sched/sch_esfq.c
|
||||
--- linux-2.6.21.5.orig/net/sched/sch_esfq.c 1969-12-31 16:00:00.000000000 -0800
|
||||
+++ linux-2.6.21.5/net/sched/sch_esfq.c 2007-06-23 19:18:00.000000000 -0700
|
||||
@@ -0,0 +1,702 @@
|
||||
+/*
|
||||
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version
|
||||
+ * 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
||||
+ *
|
||||
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
|
||||
+ * Added dynamic depth,limit,divisor,hash_kind options.
|
||||
+ * Added dst and src hashes.
|
||||
+ *
|
||||
+ * Alexander Clouter, <alex@digriz.org.uk>
|
||||
+ * Ported ESFQ to Linux 2.6.
|
||||
+ *
|
||||
+ * Corey Hickey, <bugfood-c@fatooh.org>
|
||||
+ * Maintenance of the Linux 2.6 port.
|
||||
+ * Added fwmark hash (thanks to Robert Kurjata).
|
||||
+ * Added usage of jhash.
|
||||
+ * Added conntrack support.
|
||||
+ * Added ctnatchg hash (thanks to Ben Pfountz).
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <asm/uaccess.h>
|
||||
+#include <asm/system.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/string.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <linux/sockios.h>
|
||||
+#include <linux/in.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/if_ether.h>
|
||||
+#include <linux/inet.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/notifier.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <net/ip.h>
|
||||
+#include <linux/ipv6.h>
|
||||
+#include <net/route.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <net/sock.h>
|
||||
+#include <net/pkt_sched.h>
|
||||
+#include <linux/jhash.h>
|
||||
+#include <net/netfilter/nf_conntrack.h>
|
||||
+
|
||||
+/* Stochastic Fairness Queuing algorithm.
|
||||
+ For more comments look at sch_sfq.c.
|
||||
+ The difference is that you can change limit, depth,
|
||||
+ hash table size and choose alternate hash types.
|
||||
+
|
||||
+ classic: same as in sch_sfq.c
|
||||
+ dst: destination IP address
|
||||
+ src: source IP address
|
||||
+ fwmark: netfilter mark value
|
||||
+ ctorigdst: original destination IP address
|
||||
+ ctorigsrc: original source IP address
|
||||
+ ctrepldst: reply destination IP address
|
||||
+ ctreplsrc: reply source IP
|
||||
+
|
||||
+*/
|
||||
+
|
||||
+#define ESFQ_HEAD 0
|
||||
+#define ESFQ_TAIL 1
|
||||
+
|
||||
+/* This type should contain at least SFQ_DEPTH*2 values */
|
||||
+typedef unsigned int esfq_index;
|
||||
+
|
||||
+struct esfq_head
|
||||
+{
|
||||
+ esfq_index next;
|
||||
+ esfq_index prev;
|
||||
+};
|
||||
+
|
||||
+struct esfq_sched_data
|
||||
+{
|
||||
+/* Parameters */
|
||||
+ int perturb_period;
|
||||
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
|
||||
+ int limit;
|
||||
+ unsigned depth;
|
||||
+ unsigned hash_divisor;
|
||||
+ unsigned hash_kind;
|
||||
+/* Variables */
|
||||
+ struct timer_list perturb_timer;
|
||||
+ int perturbation;
|
||||
+ esfq_index tail; /* Index of current slot in round */
|
||||
+ esfq_index max_depth; /* Maximal depth */
|
||||
+
|
||||
+ esfq_index *ht; /* Hash table */
|
||||
+ esfq_index *next; /* Active slots link */
|
||||
+ short *allot; /* Current allotment per slot */
|
||||
+ unsigned short *hash; /* Hash value indexed by slots */
|
||||
+ struct sk_buff_head *qs; /* Slot queue */
|
||||
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
|
||||
+};
|
||||
+
|
||||
+/* This contains the info we will hash. */
|
||||
+struct esfq_packet_info
|
||||
+{
|
||||
+ u32 proto; /* protocol or port */
|
||||
+ u32 src; /* source from packet header */
|
||||
+ u32 dst; /* destination from packet header */
|
||||
+ u32 ctorigsrc; /* original source from conntrack */
|
||||
+ u32 ctorigdst; /* original destination from conntrack */
|
||||
+ u32 ctreplsrc; /* reply source from conntrack */
|
||||
+ u32 ctrepldst; /* reply destination from conntrack */
|
||||
+ u32 mark; /* netfilter mark (fwmark) */
|
||||
+};
|
||||
+
|
||||
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
|
||||
+{
|
||||
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
|
||||
+{
|
||||
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
|
||||
+{
|
||||
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
|
||||
+}
|
||||
+
|
||||
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct esfq_packet_info info;
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ enum ip_conntrack_info ctinfo;
|
||||
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
||||
+#endif
|
||||
+
|
||||
+ switch (skb->protocol) {
|
||||
+ case __constant_htons(ETH_P_IP):
|
||||
+ {
|
||||
+ struct iphdr *iph = ip_hdr(skb);
|
||||
+ info.dst = iph->daddr;
|
||||
+ info.src = iph->saddr;
|
||||
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
|
||||
+ (iph->protocol == IPPROTO_TCP ||
|
||||
+ iph->protocol == IPPROTO_UDP ||
|
||||
+ iph->protocol == IPPROTO_SCTP ||
|
||||
+ iph->protocol == IPPROTO_DCCP ||
|
||||
+ iph->protocol == IPPROTO_ESP))
|
||||
+ info.proto = *(((u32*)iph) + iph->ihl);
|
||||
+ else
|
||||
+ info.proto = iph->protocol;
|
||||
+ break;
|
||||
+ }
|
||||
+ case __constant_htons(ETH_P_IPV6):
|
||||
+ {
|
||||
+ struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
|
||||
+ * but the code is simple. */
|
||||
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
|
||||
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
|
||||
+ if (iph->nexthdr == IPPROTO_TCP ||
|
||||
+ iph->nexthdr == IPPROTO_UDP ||
|
||||
+ iph->nexthdr == IPPROTO_SCTP ||
|
||||
+ iph->nexthdr == IPPROTO_DCCP ||
|
||||
+ iph->nexthdr == IPPROTO_ESP)
|
||||
+ info.proto = *(u32*)&iph[1];
|
||||
+ else
|
||||
+ info.proto = iph->nexthdr;
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ info.dst = (u32)(unsigned long)skb->dst;
|
||||
+ info.src = (u32)(unsigned long)skb->sk;
|
||||
+ info.proto = skb->protocol;
|
||||
+ }
|
||||
+
|
||||
+ info.mark = skb->mark;
|
||||
+
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ /* defaults if there is no conntrack info */
|
||||
+ info.ctorigsrc = info.src;
|
||||
+ info.ctorigdst = info.dst;
|
||||
+ info.ctreplsrc = info.dst;
|
||||
+ info.ctrepldst = info.src;
|
||||
+ /* collect conntrack info */
|
||||
+ if (ct && ct != &nf_conntrack_untracked) {
|
||||
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
|
||||
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
||||
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
|
||||
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
|
||||
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
|
||||
+ }
|
||||
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
|
||||
+ /* Again, hash ipv6 addresses into a single u32. */
|
||||
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
|
||||
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
|
||||
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
|
||||
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ switch(q->hash_kind) {
|
||||
+ case TCA_SFQ_HASH_CLASSIC:
|
||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
||||
+ case TCA_SFQ_HASH_DST:
|
||||
+ return esfq_jhash_1word(q, info.dst);
|
||||
+ case TCA_SFQ_HASH_SRC:
|
||||
+ return esfq_jhash_1word(q, info.src);
|
||||
+ case TCA_SFQ_HASH_FWMARK:
|
||||
+ return esfq_jhash_1word(q, info.mark);
|
||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
||||
+ return esfq_jhash_1word(q, info.ctorigdst);
|
||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
||||
+ return esfq_jhash_1word(q, info.ctrepldst);
|
||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
||||
+ {
|
||||
+ if (info.ctorigdst == info.ctreplsrc)
|
||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
||||
+ }
|
||||
+#endif
|
||||
+ default:
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
|
||||
+ }
|
||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
||||
+}
|
||||
+
|
||||
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
|
||||
+{
|
||||
+ esfq_index p, n;
|
||||
+ int d = q->qs[x].qlen + q->depth;
|
||||
+
|
||||
+ p = d;
|
||||
+ n = q->dep[d].next;
|
||||
+ q->dep[x].next = n;
|
||||
+ q->dep[x].prev = p;
|
||||
+ q->dep[p].next = q->dep[n].prev = x;
|
||||
+}
|
||||
+
|
||||
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
|
||||
+{
|
||||
+ esfq_index p, n;
|
||||
+
|
||||
+ n = q->dep[x].next;
|
||||
+ p = q->dep[x].prev;
|
||||
+ q->dep[p].next = n;
|
||||
+ q->dep[n].prev = p;
|
||||
+
|
||||
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
|
||||
+ q->max_depth--;
|
||||
+
|
||||
+ esfq_link(q, x);
|
||||
+}
|
||||
+
|
||||
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
|
||||
+{
|
||||
+ esfq_index p, n;
|
||||
+ int d;
|
||||
+
|
||||
+ n = q->dep[x].next;
|
||||
+ p = q->dep[x].prev;
|
||||
+ q->dep[p].next = n;
|
||||
+ q->dep[n].prev = p;
|
||||
+ d = q->qs[x].qlen;
|
||||
+ if (q->max_depth < d)
|
||||
+ q->max_depth = d;
|
||||
+
|
||||
+ esfq_link(q, x);
|
||||
+}
|
||||
+
|
||||
+static unsigned int esfq_drop(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_index d = q->max_depth;
|
||||
+ struct sk_buff *skb;
|
||||
+ unsigned int len;
|
||||
+
|
||||
+ /* Queue is full! Find the longest slot and
|
||||
+ drop a packet from it */
|
||||
+
|
||||
+ if (d > 1) {
|
||||
+ esfq_index x = q->dep[d+q->depth].next;
|
||||
+ skb = q->qs[x].prev;
|
||||
+ len = skb->len;
|
||||
+ __skb_unlink(skb, &q->qs[x]);
|
||||
+ kfree_skb(skb);
|
||||
+ esfq_dec(q, x);
|
||||
+ sch->q.qlen--;
|
||||
+ sch->qstats.drops++;
|
||||
+ sch->qstats.backlog -= len;
|
||||
+ return len;
|
||||
+ }
|
||||
+
|
||||
+ if (d == 1) {
|
||||
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
|
||||
+ d = q->next[q->tail];
|
||||
+ q->next[q->tail] = q->next[d];
|
||||
+ q->allot[q->next[d]] += q->quantum;
|
||||
+ skb = q->qs[d].prev;
|
||||
+ len = skb->len;
|
||||
+ __skb_unlink(skb, &q->qs[d]);
|
||||
+ kfree_skb(skb);
|
||||
+ esfq_dec(q, d);
|
||||
+ sch->q.qlen--;
|
||||
+ q->ht[q->hash[d]] = q->depth;
|
||||
+ sch->qstats.drops++;
|
||||
+ sch->qstats.backlog -= len;
|
||||
+ return len;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
|
||||
+{
|
||||
+ unsigned hash = esfq_hash(q, skb);
|
||||
+ unsigned depth = q->depth;
|
||||
+ esfq_index x;
|
||||
+
|
||||
+ x = q->ht[hash];
|
||||
+ if (x == depth) {
|
||||
+ q->ht[hash] = x = q->dep[depth].next;
|
||||
+ q->hash[x] = hash;
|
||||
+ }
|
||||
+
|
||||
+ if (end == ESFQ_TAIL)
|
||||
+ __skb_queue_tail(&q->qs[x], skb);
|
||||
+ else
|
||||
+ __skb_queue_head(&q->qs[x], skb);
|
||||
+
|
||||
+ esfq_inc(q, x);
|
||||
+ if (q->qs[x].qlen == 1) { /* The flow is new */
|
||||
+ if (q->tail == depth) { /* It is the first flow */
|
||||
+ q->tail = x;
|
||||
+ q->next[x] = x;
|
||||
+ q->allot[x] = q->quantum;
|
||||
+ } else {
|
||||
+ q->next[x] = q->next[q->tail];
|
||||
+ q->next[q->tail] = x;
|
||||
+ q->tail = x;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_q_enqueue(skb, q, ESFQ_TAIL);
|
||||
+ sch->qstats.backlog += skb->len;
|
||||
+ if (++sch->q.qlen < q->limit-1) {
|
||||
+ sch->bstats.bytes += skb->len;
|
||||
+ sch->bstats.packets++;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ sch->qstats.drops++;
|
||||
+ esfq_drop(sch);
|
||||
+ return NET_XMIT_CN;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_q_enqueue(skb, q, ESFQ_HEAD);
|
||||
+ sch->qstats.backlog += skb->len;
|
||||
+ if (++sch->q.qlen < q->limit - 1) {
|
||||
+ sch->qstats.requeues++;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ sch->qstats.drops++;
|
||||
+ esfq_drop(sch);
|
||||
+ return NET_XMIT_CN;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+ unsigned depth = q->depth;
|
||||
+ esfq_index a, old_a;
|
||||
+
|
||||
+ /* No active slots */
|
||||
+ if (q->tail == depth)
|
||||
+ return NULL;
|
||||
+
|
||||
+ a = old_a = q->next[q->tail];
|
||||
+
|
||||
+ /* Grab packet */
|
||||
+ skb = __skb_dequeue(&q->qs[a]);
|
||||
+ esfq_dec(q, a);
|
||||
+
|
||||
+ /* Is the slot empty? */
|
||||
+ if (q->qs[a].qlen == 0) {
|
||||
+ q->ht[q->hash[a]] = depth;
|
||||
+ a = q->next[a];
|
||||
+ if (a == old_a) {
|
||||
+ q->tail = depth;
|
||||
+ return skb;
|
||||
+ }
|
||||
+ q->next[q->tail] = a;
|
||||
+ q->allot[a] += q->quantum;
|
||||
+ } else if ((q->allot[a] -= skb->len) <= 0) {
|
||||
+ q->tail = a;
|
||||
+ a = q->next[a];
|
||||
+ q->allot[a] += q->quantum;
|
||||
+ }
|
||||
+
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ skb = esfq_q_dequeue(q);
|
||||
+ if (skb == NULL)
|
||||
+ return NULL;
|
||||
+ sch->q.qlen--;
|
||||
+ sch->qstats.backlog -= skb->len;
|
||||
+ return skb;
|
||||
+}
|
||||
+
|
||||
+static void esfq_q_destroy(struct esfq_sched_data *q)
|
||||
+{
|
||||
+ del_timer(&q->perturb_timer);
|
||||
+ if(q->ht)
|
||||
+ kfree(q->ht);
|
||||
+ if(q->dep)
|
||||
+ kfree(q->dep);
|
||||
+ if(q->next)
|
||||
+ kfree(q->next);
|
||||
+ if(q->allot)
|
||||
+ kfree(q->allot);
|
||||
+ if(q->hash)
|
||||
+ kfree(q->hash);
|
||||
+ if(q->qs)
|
||||
+ kfree(q->qs);
|
||||
+}
|
||||
+
|
||||
+static void esfq_destroy(struct Qdisc *sch)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ esfq_q_destroy(q);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void esfq_reset(struct Qdisc* sch)
|
||||
+{
|
||||
+ struct sk_buff *skb;
|
||||
+
|
||||
+ while ((skb = esfq_dequeue(sch)) != NULL)
|
||||
+ kfree_skb(skb);
|
||||
+}
|
||||
+
|
||||
+static void esfq_perturbation(unsigned long arg)
|
||||
+{
|
||||
+ struct Qdisc *sch = (struct Qdisc*)arg;
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+
|
||||
+ q->perturbation = net_random()&0x1F;
|
||||
+
|
||||
+ if (q->perturb_period) {
|
||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||
+ add_timer(&q->perturb_timer);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static unsigned int esfq_check_hash(unsigned int kind)
|
||||
+{
|
||||
+ switch (kind) {
|
||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
||||
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
|
||||
+ {
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
|
||||
+ return TCA_SFQ_HASH_CLASSIC;
|
||||
+ }
|
||||
+#endif
|
||||
+ case TCA_SFQ_HASH_CLASSIC:
|
||||
+ case TCA_SFQ_HASH_DST:
|
||||
+ case TCA_SFQ_HASH_SRC:
|
||||
+ case TCA_SFQ_HASH_FWMARK:
|
||||
+ return kind;
|
||||
+ default:
|
||||
+ {
|
||||
+ if (net_ratelimit())
|
||||
+ printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
|
||||
+ return TCA_SFQ_HASH_CLASSIC;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int esfq_q_init(struct esfq_sched_data *q, struct rtattr *opt)
|
||||
+{
|
||||
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
|
||||
+ esfq_index p = ~0U/2;
|
||||
+ int i;
|
||||
+
|
||||
+ if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ q->perturbation = 0;
|
||||
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
|
||||
+ q->max_depth = 0;
|
||||
+ if (opt == NULL) {
|
||||
+ q->perturb_period = 0;
|
||||
+ q->hash_divisor = 1024;
|
||||
+ q->tail = q->limit = q->depth = 128;
|
||||
+
|
||||
+ } else {
|
||||
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
|
||||
+ if (ctl->quantum)
|
||||
+ q->quantum = ctl->quantum;
|
||||
+ q->perturb_period = ctl->perturb_period*HZ;
|
||||
+ q->hash_divisor = ctl->divisor ? : 1024;
|
||||
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
|
||||
+
|
||||
+ if ( q->depth > p - 1 )
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (ctl->limit)
|
||||
+ q->limit = min_t(u32, ctl->limit, q->depth);
|
||||
+
|
||||
+ if (ctl->hash_kind) {
|
||||
+ q->hash_kind = esfq_check_hash(ctl->hash_kind);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
|
||||
+ if (!q->ht)
|
||||
+ goto err_case;
|
||||
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
|
||||
+ if (!q->dep)
|
||||
+ goto err_case;
|
||||
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
|
||||
+ if (!q->next)
|
||||
+ goto err_case;
|
||||
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
|
||||
+ if (!q->allot)
|
||||
+ goto err_case;
|
||||
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
|
||||
+ if (!q->hash)
|
||||
+ goto err_case;
|
||||
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
|
||||
+ if (!q->qs)
|
||||
+ goto err_case;
|
||||
+
|
||||
+ for (i=0; i< q->hash_divisor; i++)
|
||||
+ q->ht[i] = q->depth;
|
||||
+ for (i=0; i<q->depth; i++) {
|
||||
+ skb_queue_head_init(&q->qs[i]);
|
||||
+ q->dep[i+q->depth].next = i+q->depth;
|
||||
+ q->dep[i+q->depth].prev = i+q->depth;
|
||||
+ }
|
||||
+
|
||||
+ for (i=0; i<q->depth; i++)
|
||||
+ esfq_link(q, i);
|
||||
+ return 0;
|
||||
+err_case:
|
||||
+ esfq_q_destroy(q);
|
||||
+ return -ENOBUFS;
|
||||
+}
|
||||
+
|
||||
+static int esfq_init(struct Qdisc *sch, struct rtattr *opt)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ int err;
|
||||
+
|
||||
+ q->quantum = psched_mtu(sch->dev); /* default */
|
||||
+ if ((err = esfq_q_init(q, opt)))
|
||||
+ return err;
|
||||
+
|
||||
+ init_timer(&q->perturb_timer);
|
||||
+ q->perturb_timer.data = (unsigned long)sch;
|
||||
+ q->perturb_timer.function = esfq_perturbation;
|
||||
+ if (q->perturb_period) {
|
||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||
+ add_timer(&q->perturb_timer);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int esfq_change(struct Qdisc *sch, struct rtattr *opt)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ struct esfq_sched_data new;
|
||||
+ struct sk_buff *skb;
|
||||
+ int err;
|
||||
+
|
||||
+ /* set up new queue */
|
||||
+ memset(&new, 0, sizeof(struct esfq_sched_data));
|
||||
+ new.quantum = psched_mtu(sch->dev); /* default */
|
||||
+ if ((err = esfq_q_init(&new, opt)))
|
||||
+ return err;
|
||||
+
|
||||
+ /* copy all packets from the old queue to the new queue */
|
||||
+ sch_tree_lock(sch);
|
||||
+ while ((skb = esfq_q_dequeue(q)) != NULL)
|
||||
+ esfq_q_enqueue(skb, &new, ESFQ_TAIL);
|
||||
+
|
||||
+ /* clean up the old queue */
|
||||
+ esfq_q_destroy(q);
|
||||
+
|
||||
+ /* copy elements of the new queue into the old queue */
|
||||
+ q->perturb_period = new.perturb_period;
|
||||
+ q->quantum = new.quantum;
|
||||
+ q->limit = new.limit;
|
||||
+ q->depth = new.depth;
|
||||
+ q->hash_divisor = new.hash_divisor;
|
||||
+ q->hash_kind = new.hash_kind;
|
||||
+ q->tail = new.tail;
|
||||
+ q->max_depth = new.max_depth;
|
||||
+ q->ht = new.ht;
|
||||
+ q->dep = new.dep;
|
||||
+ q->next = new.next;
|
||||
+ q->allot = new.allot;
|
||||
+ q->hash = new.hash;
|
||||
+ q->qs = new.qs;
|
||||
+
|
||||
+ /* finish up */
|
||||
+ if (q->perturb_period) {
|
||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
||||
+ add_timer(&q->perturb_timer);
|
||||
+ } else {
|
||||
+ q->perturbation = 0;
|
||||
+ }
|
||||
+ sch_tree_unlock(sch);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
||||
+ unsigned char *b = skb->tail;
|
||||
+ struct tc_esfq_qopt opt;
|
||||
+
|
||||
+ opt.quantum = q->quantum;
|
||||
+ opt.perturb_period = q->perturb_period/HZ;
|
||||
+
|
||||
+ opt.limit = q->limit;
|
||||
+ opt.divisor = q->hash_divisor;
|
||||
+ opt.flows = q->depth;
|
||||
+ opt.hash_kind = q->hash_kind;
|
||||
+
|
||||
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
|
||||
+
|
||||
+ return skb->len;
|
||||
+
|
||||
+rtattr_failure:
|
||||
+ skb_trim(skb, b - skb->data);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static struct Qdisc_ops esfq_qdisc_ops =
|
||||
+{
|
||||
+ .next = NULL,
|
||||
+ .cl_ops = NULL,
|
||||
+ .id = "esfq",
|
||||
+ .priv_size = sizeof(struct esfq_sched_data),
|
||||
+ .enqueue = esfq_enqueue,
|
||||
+ .dequeue = esfq_dequeue,
|
||||
+ .requeue = esfq_requeue,
|
||||
+ .drop = esfq_drop,
|
||||
+ .init = esfq_init,
|
||||
+ .reset = esfq_reset,
|
||||
+ .destroy = esfq_destroy,
|
||||
+ .change = esfq_change,
|
||||
+ .dump = esfq_dump,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int __init esfq_module_init(void)
|
||||
+{
|
||||
+ return register_qdisc(&esfq_qdisc_ops);
|
||||
+}
|
||||
+static void __exit esfq_module_exit(void)
|
||||
+{
|
||||
+ unregister_qdisc(&esfq_qdisc_ops);
|
||||
+}
|
||||
+module_init(esfq_module_init)
|
||||
+module_exit(esfq_module_exit)
|
||||
+MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,14 @@
|
|||
Index: linux-2.6.23-rc6/arch/mips/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/arch/mips/Makefile 2007-09-21 16:23:53.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/arch/mips/Makefile 2007-09-21 16:24:05.000000000 +0800
|
||||
@@ -565,6 +565,9 @@
|
||||
cflags-$(CONFIG_TOSHIBA_RBTX4938) += -Iinclude/asm-mips/mach-tx49xx
|
||||
load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
|
||||
|
||||
+# temporary until string.h is fixed
|
||||
+cflags-y += -ffreestanding
|
||||
+
|
||||
cflags-y += -Iinclude/asm-mips/mach-generic
|
||||
drivers-$(CONFIG_PCI) += arch/mips/pci/
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
Index: linux-2.6.23-rc6/fs/jffs2/build.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/jffs2/build.c 2007-09-21 16:23:53.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/jffs2/build.c 2007-09-21 16:24:05.000000000 +0800
|
||||
@@ -105,6 +105,17 @@
|
||||
dbg_fsbuild("scanned flash completely\n");
|
||||
jffs2_dbg_dump_block_lists_nolock(c);
|
||||
|
||||
+ if (c->flags & (1 << 7)) {
|
||||
+ printk("%s(): unlocking the mtd device... ", __func__);
|
||||
+ if (c->mtd->unlock)
|
||||
+ c->mtd->unlock(c->mtd, 0, c->mtd->size);
|
||||
+ printk("done.\n");
|
||||
+
|
||||
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
|
||||
+ jffs2_erase_pending_blocks(c, -1);
|
||||
+ printk("done.\n");
|
||||
+ }
|
||||
+
|
||||
dbg_fsbuild("pass 1 starting\n");
|
||||
c->flags |= JFFS2_SB_FLAG_BUILDING;
|
||||
/* Now scan the directory tree, increasing nlink according to every dirent found. */
|
||||
Index: linux-2.6.23-rc6/fs/jffs2/scan.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/jffs2/scan.c 2007-09-21 16:23:52.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/jffs2/scan.c 2007-09-21 16:24:05.000000000 +0800
|
||||
@@ -142,9 +142,12 @@
|
||||
|
||||
/* reset summary info for next eraseblock scan */
|
||||
jffs2_sum_reset_collected(s);
|
||||
-
|
||||
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
||||
- buf_size, s);
|
||||
+
|
||||
+ if (c->flags & (1 << 7))
|
||||
+ ret = BLK_STATE_ALLFF;
|
||||
+ else
|
||||
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
||||
+ buf_size, s);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -545,6 +548,17 @@
|
||||
return err;
|
||||
}
|
||||
|
||||
+ if ((buf[0] == 0xde) &&
|
||||
+ (buf[1] == 0xad) &&
|
||||
+ (buf[2] == 0xc0) &&
|
||||
+ (buf[3] == 0xde)) {
|
||||
+ /* end of filesystem. erase everything after this point */
|
||||
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
|
||||
+ c->flags |= (1 << 7);
|
||||
+
|
||||
+ return BLK_STATE_ALLFF;
|
||||
+ }
|
||||
+
|
||||
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
|
||||
ofs = 0;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
Index: linux-2.6.23-rc6/include/asm-powerpc/segment.h
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ linux-2.6.23-rc6/include/asm-powerpc/segment.h 2007-09-21 16:24:05.000000000 +0800
|
||||
@@ -0,0 +1,6 @@
|
||||
+#ifndef _ASM_SEGMENT_H
|
||||
+#define _ASM_SEGMENT_H
|
||||
+
|
||||
+/* Only here because we have some old header files that expect it.. */
|
||||
+
|
||||
+#endif /* _ASM_SEGMENT_H */
|
|
@ -0,0 +1,44 @@
|
|||
Index: linux-2.6.23/drivers/net/r8169.c
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/drivers/net/r8169.c 2007-10-10 04:31:38.000000000 +0800
|
||||
+++ linux-2.6.23/drivers/net/r8169.c 2007-10-10 13:53:17.000000000 +0800
|
||||
@@ -1459,7 +1459,7 @@
|
||||
.hw_start = rtl_hw_start_8169,
|
||||
.region = 1,
|
||||
.align = 0,
|
||||
- .intr_event = SYSErr | LinkChg | RxOverflow |
|
||||
+ .intr_event = LinkChg | RxOverflow |
|
||||
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
||||
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
|
||||
},
|
||||
@@ -1467,7 +1467,7 @@
|
||||
.hw_start = rtl_hw_start_8168,
|
||||
.region = 2,
|
||||
.align = 8,
|
||||
- .intr_event = SYSErr | LinkChg | RxOverflow |
|
||||
+ .intr_event = LinkChg | RxOverflow |
|
||||
TxErr | TxOK | RxOK | RxErr,
|
||||
.napi_event = TxErr | TxOK | RxOK | RxOverflow
|
||||
},
|
||||
@@ -1475,7 +1475,7 @@
|
||||
.hw_start = rtl_hw_start_8101,
|
||||
.region = 2,
|
||||
.align = 8,
|
||||
- .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
|
||||
+ .intr_event = LinkChg | RxOverflow | PCSTimeout |
|
||||
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
||||
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
|
||||
}
|
||||
@@ -2779,10 +2779,12 @@
|
||||
break;
|
||||
}
|
||||
|
||||
+#if 0
|
||||
if (unlikely(status & SYSErr)) {
|
||||
rtl8169_pcierr_interrupt(dev);
|
||||
break;
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (status & LinkChg)
|
||||
rtl8169_check_link_status(dev, tp, ioaddr);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
--- linux-2.6.24/lib/kobject_uevent.c 2008-01-24 23:58:37.000000000 +0100
|
||||
+++ linux-2.6.24-owrt/lib/kobject_uevent.c 2008-01-28 12:01:41.000000000 +0100
|
||||
@@ -27,7 +27,8 @@
|
||||
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
||||
static DEFINE_SPINLOCK(sequence_lock);
|
||||
#if defined(CONFIG_NET)
|
||||
-static struct sock *uevent_sock;
|
||||
+struct sock *uevent_sock = NULL;
|
||||
+EXPORT_SYMBOL_GPL(uevent_sock);
|
||||
#endif
|
||||
|
||||
/* the strings here must match the enum in include/linux/kobject.h */
|
||||
@@ -40,6 +41,18 @@
|
||||
[KOBJ_OFFLINE] = "offline",
|
||||
};
|
||||
|
||||
+u64 uevent_next_seqnum(void)
|
||||
+{
|
||||
+ u64 seq;
|
||||
+
|
||||
+ spin_lock(&sequence_lock);
|
||||
+ seq = ++uevent_seqnum;
|
||||
+ spin_unlock(&sequence_lock);
|
||||
+
|
||||
+ return seq;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(uevent_next_seqnum);
|
||||
+
|
||||
/**
|
||||
* kobject_action_type - translate action string to numeric type
|
||||
*
|
||||
@@ -173,9 +186,7 @@
|
||||
}
|
||||
|
||||
/* we will send an event, so request a new sequence number */
|
||||
- spin_lock(&sequence_lock);
|
||||
- seq = ++uevent_seqnum;
|
||||
- spin_unlock(&sequence_lock);
|
||||
+ seq = uevent_next_seqnum();
|
||||
retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
|
||||
if (retval)
|
||||
goto exit;
|
|
@ -0,0 +1,13 @@
|
|||
Index: linux-2.6.23.1/sound/core/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23.1.orig/sound/core/Kconfig 2007-11-25 18:14:23.486146184 +0100
|
||||
+++ linux-2.6.23.1/sound/core/Kconfig 2007-11-25 18:14:26.474316473 +0100
|
||||
@@ -9,7 +9,7 @@
|
||||
depends on SND
|
||||
|
||||
config SND_HWDEP
|
||||
- tristate
|
||||
+ tristate "Sound hardware support"
|
||||
depends on SND
|
||||
|
||||
config SND_RAWMIDI
|
|
@ -0,0 +1,22 @@
|
|||
Index: linux-2.6.23-rc9/drivers/leds/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc9.orig/drivers/leds/Kconfig 2007-10-02 12:51:05.000000000 +0800
|
||||
+++ linux-2.6.23-rc9/drivers/leds/Kconfig 2007-10-03 23:43:31.000000000 +0800
|
||||
@@ -133,4 +133,8 @@
|
||||
load average.
|
||||
If unsure, say Y.
|
||||
|
||||
+config LEDS_TRIGGER_MORSE
|
||||
+ tristate "LED Morse Trigger"
|
||||
+ depends on LEDS_TRIGGERS
|
||||
+
|
||||
endif # NEW_LEDS
|
||||
Index: linux-2.6.23-rc9/drivers/leds/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc9.orig/drivers/leds/Makefile 2007-10-02 12:51:05.000000000 +0800
|
||||
+++ linux-2.6.23-rc9/drivers/leds/Makefile 2007-10-03 23:42:24.000000000 +0800
|
||||
@@ -22,3 +22,4 @@
|
||||
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
|
||||
+obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
|
@ -0,0 +1,27 @@
|
|||
diff -Nur linux-2.6.23.1.orig/drivers/leds/Kconfig linux-2.6.23.1/drivers/leds/Kconfig
|
||||
--- linux-2.6.23.1.orig/drivers/leds/Kconfig 2007-10-12 12:43:44.000000000 -0400
|
||||
+++ linux-2.6.23.1/drivers/leds/Kconfig 2007-10-31 02:36:22.000000000 -0400
|
||||
@@ -81,6 +81,12 @@
|
||||
help
|
||||
This option enables support for the PCEngines WRAP programmable LEDs.
|
||||
|
||||
+config LEDS_ALIX
|
||||
+ tristate "LED Support for the ALIX 2/3 boards"
|
||||
+ depends on LEDS_CLASS
|
||||
+ help
|
||||
+ This option enables support for the three LEDs on the PCEngines ALIX 2/3 boards.
|
||||
+
|
||||
config LEDS_H1940
|
||||
tristate "LED Support for iPAQ H1940 device"
|
||||
depends LEDS_CLASS && ARCH_H1940
|
||||
diff -Nur linux-2.6.23.1.orig/drivers/leds/Makefile linux-2.6.23.1/drivers/leds/Makefile
|
||||
--- linux-2.6.23.1.orig/drivers/leds/Makefile 2007-10-12 12:43:44.000000000 -0400
|
||||
+++ linux-2.6.23.1/drivers/leds/Makefile 2007-10-31 02:36:17.000000000 -0400
|
||||
@@ -14,6 +14,7 @@
|
||||
obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
|
||||
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
|
||||
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
|
||||
+obj-$(CONFIG_LEDS_ALIX) += leds-alix.o
|
||||
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
|
||||
obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.o
|
||||
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
|
|
@ -0,0 +1,23 @@
|
|||
diff -ur linux-2.6.23.1.orig/drivers/leds/Kconfig linux-2.6.23.1/drivers/leds/Kconfig
|
||||
--- linux-2.6.23.1.orig/drivers/leds/Kconfig 2007-12-01 00:41:03.000000000 +1300
|
||||
+++ linux-2.6.23.1/drivers/leds/Kconfig 2007-12-01 01:26:43.000000000 +1300
|
||||
@@ -137,4 +137,11 @@
|
||||
tristate "LED Morse Trigger"
|
||||
depends on LEDS_TRIGGERS
|
||||
|
||||
+config LEDS_TRIGGER_DEFAULT_ON
|
||||
+ tristate "LED Default ON Trigger"
|
||||
+ depends on LEDS_TRIGGERS
|
||||
+ help
|
||||
+ This allows LEDs to be initialised in the ON state.
|
||||
+ If unsure, say Y.
|
||||
+
|
||||
endif # NEW_LEDS
|
||||
diff -ur linux-2.6.23.1.orig/drivers/leds/Makefile linux-2.6.23.1/drivers/leds/Makefile
|
||||
--- linux-2.6.23.1.orig/drivers/leds/Makefile 2007-12-01 00:41:03.000000000 +1300
|
||||
+++ linux-2.6.23.1/drivers/leds/Makefile 2007-12-01 01:27:12.000000000 +1300
|
||||
@@ -23,3 +23,4 @@
|
||||
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
||||
+obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
|
|
@ -0,0 +1,30 @@
|
|||
--- linux-2.6.24.2.orig/drivers/input/misc/Kconfig 2007-08-21 06:33:06.000000000 +0200
|
||||
+++ linux-2.6.24.2/drivers/input/misc/Kconfig 2007-10-08 10:57:23.000000000 +0200
|
||||
@@ -178,4 +178,20 @@
|
||||
Say Y here if you want to support the built-in real time clock
|
||||
of the HP SDC controller.
|
||||
|
||||
+config INPUT_GPIO_BUTTONS
|
||||
+ tristate "Polled GPIO buttons interface"
|
||||
+ depends on GENERIC_GPIO
|
||||
+ select INPUT_POLLDEV
|
||||
+ help
|
||||
+ This driver implements support for buttons connected
|
||||
+ to GPIO pins of various CPUs (and some other chips).
|
||||
+
|
||||
+ Say Y here if your device has buttons connected
|
||||
+ directly to such GPIO pins. Your board-specific
|
||||
+ setup logic must also provide a platform device,
|
||||
+ with configuration data saying which GPIOs are used.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called gpio-buttons.
|
||||
+
|
||||
endif
|
||||
--- linux-2.6.24.2.orig/drivers/input/misc/Makefile 2007-08-21 06:33:06.000000000 +0200
|
||||
+++ linux-2.6.24.2/drivers/input/misc/Makefile 2007-10-08 10:50:12.000000000 +0200
|
||||
@@ -18,3 +18,4 @@
|
||||
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
|
||||
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
|
||||
obj-$(CONFIG_INPUT_APANEL) += apanel.o
|
||||
+obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o
|
|
@ -0,0 +1,21 @@
|
|||
Index: linux-2.6.23-rc6/fs/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/Kconfig 2007-09-21 16:24:06.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/Kconfig 2007-09-21 16:24:08.000000000 +0800
|
||||
@@ -419,6 +419,7 @@
|
||||
|
||||
source "fs/xfs/Kconfig"
|
||||
source "fs/gfs2/Kconfig"
|
||||
+source "fs/yaffs2/Kconfig"
|
||||
|
||||
config OCFS2_FS
|
||||
tristate "OCFS2 file system support"
|
||||
Index: linux-2.6.23-rc6/fs/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/fs/Makefile 2007-09-21 16:24:06.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/fs/Makefile 2007-09-21 16:24:08.000000000 +0800
|
||||
@@ -120,3 +120,4 @@
|
||||
obj-$(CONFIG_DEBUG_FS) += debugfs/
|
||||
obj-$(CONFIG_OCFS2_FS) += ocfs2/
|
||||
obj-$(CONFIG_GFS2_FS) += gfs2/
|
||||
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
|
|
@ -0,0 +1,67 @@
|
|||
Index: linux-2.6.23/drivers/net/phy/phy.c
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/drivers/net/phy/phy.c 2007-10-14 00:05:26.000000000 +0200
|
||||
+++ linux-2.6.23/drivers/net/phy/phy.c 2007-10-14 00:44:21.000000000 +0200
|
||||
@@ -344,6 +344,50 @@
|
||||
}
|
||||
EXPORT_SYMBOL(phy_ethtool_gset);
|
||||
|
||||
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
|
||||
+{
|
||||
+ u32 cmd;
|
||||
+ int tmp;
|
||||
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
|
||||
+ struct ethtool_value edata = { ETHTOOL_GLINK };
|
||||
+
|
||||
+ if (get_user(cmd, (u32 *) useraddr))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case ETHTOOL_GSET:
|
||||
+ phy_ethtool_gset(phydev, &ecmd);
|
||||
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
|
||||
+ return -EFAULT;
|
||||
+ return 0;
|
||||
+
|
||||
+ case ETHTOOL_SSET:
|
||||
+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
|
||||
+ return -EFAULT;
|
||||
+ return phy_ethtool_sset(phydev, &ecmd);
|
||||
+
|
||||
+ case ETHTOOL_NWAY_RST:
|
||||
+ /* if autoneg is off, it's an error */
|
||||
+ tmp = phy_read(phydev, MII_BMCR);
|
||||
+ if (tmp & BMCR_ANENABLE) {
|
||||
+ tmp |= (BMCR_ANRESTART);
|
||||
+ phy_write(phydev, MII_BMCR, tmp);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ case ETHTOOL_GLINK:
|
||||
+ edata.data = (phy_read(phydev,
|
||||
+ MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
|
||||
+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
|
||||
+ return -EFAULT;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+EXPORT_SYMBOL(phy_ethtool_ioctl);
|
||||
+
|
||||
/**
|
||||
* phy_mii_ioctl - generic PHY MII ioctl interface
|
||||
* @phydev: the phy_device struct
|
||||
Index: linux-2.6.23/include/linux/phy.h
|
||||
===================================================================
|
||||
--- linux-2.6.23.orig/include/linux/phy.h 2007-10-14 00:05:15.000000000 +0200
|
||||
+++ linux-2.6.23/include/linux/phy.h 2007-10-14 00:18:54.000000000 +0200
|
||||
@@ -393,6 +393,7 @@
|
||||
void phy_stop_machine(struct phy_device *phydev);
|
||||
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
|
||||
int phy_mii_ioctl(struct phy_device *phydev,
|
||||
struct mii_ioctl_data *mii_data, int cmd);
|
||||
int phy_start_interrupts(struct phy_device *phydev);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
Index: linux-2.6.23-rc6/drivers/usb/serial/usb-serial.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/drivers/usb/serial/usb-serial.c 2007-09-21 16:23:52.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/drivers/usb/serial/usb-serial.c 2007-09-21 16:24:09.000000000 +0800
|
||||
@@ -58,6 +58,7 @@
|
||||
drivers depend on it.
|
||||
*/
|
||||
|
||||
+static ushort maxSize = 0;
|
||||
static int debug;
|
||||
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
|
||||
static DEFINE_MUTEX(table_lock);
|
||||
@@ -866,7 +867,7 @@
|
||||
dev_err(&interface->dev, "No free urbs available\n");
|
||||
goto probe_error;
|
||||
}
|
||||
- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
+ buffer_size = (endpoint->wMaxPacketSize > maxSize) ? endpoint->wMaxPacketSize : maxSize;
|
||||
port->bulk_in_size = buffer_size;
|
||||
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
|
||||
port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
|
||||
@@ -1276,3 +1277,5 @@
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
+module_param(maxSize, ushort,0);
|
||||
+MODULE_PARM_DESC(maxSize,"User specified USB endpoint size");
|
|
@ -0,0 +1,13 @@
|
|||
Index: linux-2.6.23.14/init/main.c
|
||||
===================================================================
|
||||
--- linux-2.6.23.14.orig/init/main.c 2008-01-25 19:12:45.000000000 +0100
|
||||
+++ linux-2.6.23.14/init/main.c 2008-01-25 19:12:52.000000000 +0100
|
||||
@@ -780,7 +780,7 @@
|
||||
numa_default_policy();
|
||||
|
||||
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
|
||||
- printk(KERN_WARNING "Warning: unable to open an initial console.\n");
|
||||
+ printk(KERN_WARNING "Please be patient, while OpenWrt loads ...\n");
|
||||
|
||||
(void) sys_dup(0);
|
||||
(void) sys_dup(0);
|
|
@ -0,0 +1,24 @@
|
|||
diff -Nur linux-2.6.24/fs/jffs2/erase.c linux-2.6.24-owrt/fs/jffs2/erase.c
|
||||
--- linux-2.6.24/fs/jffs2/erase.c 2008-01-30 17:30:15.000000000 +0100
|
||||
+++ linux-2.6.24-owrt/fs/jffs2/erase.c 2008-01-30 22:20:02.000000000 +0100
|
||||
@@ -35,6 +35,8 @@
|
||||
{
|
||||
int ret;
|
||||
uint32_t bad_offset;
|
||||
+ static char s[]="|/-\\", *p=s;
|
||||
+
|
||||
#ifdef __ECOS
|
||||
ret = jffs2_flash_erase(c, jeb);
|
||||
if (!ret) {
|
||||
@@ -47,6 +49,11 @@
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_erase_block(): erase block %#08x (range %#08x-%#08x)\n",
|
||||
jeb->offset, jeb->offset, jeb->offset + c->sector_size));
|
||||
+
|
||||
+ printk("%c\b", *p);
|
||||
+ if (*++p==0)
|
||||
+ p=s;
|
||||
+
|
||||
instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
|
||||
if (!instr) {
|
||||
printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
|
|
@ -0,0 +1,50 @@
|
|||
Index: linux-2.6.23-rc6/include/linux/time.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/include/linux/time.h 2007-09-21 16:23:52.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/include/linux/time.h 2007-09-21 16:24:09.000000000 +0800
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef _LINUX_TIME_H
|
||||
#define _LINUX_TIME_H
|
||||
|
||||
+#ifndef __KERNEL__
|
||||
+#include <time.h>
|
||||
+#else
|
||||
+
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
@@ -227,4 +231,6 @@
|
||||
*/
|
||||
#define TIMER_ABSTIME 0x01
|
||||
|
||||
+#endif /* __KERNEL__ DEBIAN */
|
||||
+
|
||||
#endif
|
||||
Index: linux-2.6.23-rc6/include/linux/types.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/include/linux/types.h 2007-09-21 16:23:52.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/include/linux/types.h 2007-09-21 16:24:09.000000000 +0800
|
||||
@@ -1,6 +1,14 @@
|
||||
#ifndef _LINUX_TYPES_H
|
||||
#define _LINUX_TYPES_H
|
||||
|
||||
+/* Debian: Use userland types instead. */
|
||||
+#ifndef __KERNEL__
|
||||
+# include <sys/types.h>
|
||||
+/* For other kernel headers. */
|
||||
+# include <linux/posix_types.h>
|
||||
+# include <asm/types.h>
|
||||
+#else
|
||||
+
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define BITS_TO_LONGS(bits) \
|
||||
@@ -162,6 +170,8 @@
|
||||
|
||||
#endif /* __KERNEL_STRICT_NAMES */
|
||||
|
||||
+#endif /* __KERNEL__ DEBIAN */
|
||||
+
|
||||
/*
|
||||
* Below are truly Linux-specific types that should never collide with
|
||||
* any application/library that wants linux/types.h.
|
|
@ -0,0 +1,114 @@
|
|||
Index: linux-2.6.23-rc6/scripts/genksyms/parse.c_shipped
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/genksyms/parse.c_shipped 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/genksyms/parse.c_shipped 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -144,7 +144,9 @@
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
+#endif
|
||||
#include "genksyms.h"
|
||||
|
||||
static int is_typedef;
|
||||
Index: linux-2.6.23-rc6/scripts/genksyms/parse.y
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/genksyms/parse.y 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/genksyms/parse.y 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -24,7 +24,9 @@
|
||||
%{
|
||||
|
||||
#include <assert.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
+#endif
|
||||
#include "genksyms.h"
|
||||
|
||||
static int is_typedef;
|
||||
Index: linux-2.6.23-rc6/scripts/kallsyms.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/kallsyms.c 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/kallsyms.c 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -28,6 +28,35 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
+#ifdef __APPLE__
|
||||
+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */
|
||||
+void *memmem (const void *haystack, size_t haystack_len,
|
||||
+ const void *needle, size_t needle_len)
|
||||
+{
|
||||
+ const char *begin;
|
||||
+ const char *const last_possible
|
||||
+ = (const char *) haystack + haystack_len - needle_len;
|
||||
+
|
||||
+ if (needle_len == 0)
|
||||
+ /* The first occurrence of the empty string is deemed to occur at
|
||||
+ the beginning of the string. */
|
||||
+ return (void *) haystack;
|
||||
+
|
||||
+ /* Sanity check, otherwise the loop might search through the whole
|
||||
+ memory. */
|
||||
+ if (__builtin_expect (haystack_len < needle_len, 0))
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (begin = (const char *) haystack; begin <= last_possible; ++begin)
|
||||
+ if (begin[0] == ((const char *) needle)[0] &&
|
||||
+ !memcmp ((const void *) &begin[1],
|
||||
+ (const void *) ((const char *) needle + 1),
|
||||
+ needle_len - 1))
|
||||
+ return (void *) begin;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+#endif
|
||||
|
||||
#define KSYM_NAME_LEN 128
|
||||
|
||||
Index: linux-2.6.23-rc6/scripts/kconfig/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/kconfig/Makefile 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/kconfig/Makefile 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -88,6 +88,9 @@
|
||||
# we really need to do so. (Do not call gcc as part of make mrproper)
|
||||
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
|
||||
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
|
||||
+ifeq ($(shell uname -s),Darwin)
|
||||
+HOST_LOADLIBES += -lncurses
|
||||
+endif
|
||||
|
||||
HOST_EXTRACFLAGS += -DLOCALE
|
||||
|
||||
Index: linux-2.6.23-rc6/scripts/mod/mk_elfconfig.c
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/mod/mk_elfconfig.c 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/mod/mk_elfconfig.c 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <elf.h>
|
||||
+#else
|
||||
+#include "../../../../../tools/sstrip/include/elf.h"
|
||||
+#endif
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
Index: linux-2.6.23-rc6/scripts/mod/modpost.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/mod/modpost.h 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/mod/modpost.h 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -7,7 +7,11 @@
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
+#ifndef __APPLE__
|
||||
#include <elf.h>
|
||||
+#else
|
||||
+#include "../../../../../tools/sstrip/include/elf.h"
|
||||
+#endif
|
||||
|
||||
#include "elfconfig.h"
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
diff -Nur linux-2.6.17/drivers/net/wireless/hostap/hostap_ap.c linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_ap.c
|
||||
--- linux-2.6.17/drivers/net/wireless/hostap/hostap_ap.c 2006-06-18 04:49:35.000000000 +0300
|
||||
+++ linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_ap.c 2006-12-10 19:13:33.000000000 +0200
|
||||
@@ -2345,13 +2345,13 @@
|
||||
addr[count].sa_family = ARPHRD_ETHER;
|
||||
memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
|
||||
if (sta->last_rx_silence == 0)
|
||||
- qual[count].qual = sta->last_rx_signal < 27 ?
|
||||
- 0 : (sta->last_rx_signal - 27) * 92 / 127;
|
||||
+ qual[count].qual = (sta->last_rx_signal - 156) == 0 ?
|
||||
+ 0 : (sta->last_rx_signal - 156) * 92 / 64;
|
||||
else
|
||||
- qual[count].qual = sta->last_rx_signal -
|
||||
- sta->last_rx_silence - 35;
|
||||
- qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
|
||||
- qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
|
||||
+ qual[count].qual = (sta->last_rx_signal -
|
||||
+ sta->last_rx_silence) * 92 / 64;
|
||||
+ qual[count].level = sta->last_rx_signal;
|
||||
+ qual[count].noise = sta->last_rx_silence;
|
||||
qual[count].updated = sta->last_rx_updated;
|
||||
|
||||
sta->last_rx_updated = IW_QUAL_DBM;
|
||||
@@ -2416,13 +2416,13 @@
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVQUAL;
|
||||
if (sta->last_rx_silence == 0)
|
||||
- iwe.u.qual.qual = sta->last_rx_signal < 27 ?
|
||||
- 0 : (sta->last_rx_signal - 27) * 92 / 127;
|
||||
+ iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ?
|
||||
+ 0 : (sta->last_rx_signal - 156) * 92 / 64;
|
||||
else
|
||||
- iwe.u.qual.qual = sta->last_rx_signal -
|
||||
- sta->last_rx_silence - 35;
|
||||
- iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
|
||||
- iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
|
||||
+ iwe.u.qual.qual = (sta->last_rx_signal -
|
||||
+ sta->last_rx_silence) * 92 / 64;
|
||||
+ iwe.u.qual.level = sta->last_rx_signal;
|
||||
+ iwe.u.qual.noise = sta->last_rx_silence;
|
||||
iwe.u.qual.updated = sta->last_rx_updated;
|
||||
iwe.len = IW_EV_QUAL_LEN;
|
||||
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
|
||||
diff -Nur linux-2.6.17/drivers/net/wireless/hostap/hostap_config.h linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_config.h
|
||||
--- linux-2.6.17/drivers/net/wireless/hostap/hostap_config.h 2006-06-18 04:49:35.000000000 +0300
|
||||
+++ linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_config.h 2006-12-10 19:13:33.000000000 +0200
|
||||
@@ -47,4 +47,9 @@
|
||||
*/
|
||||
/* #define PRISM2_NO_STATION_MODES */
|
||||
|
||||
+/* Enable TX power Setting functions
|
||||
+ * (min att = -128 , max att = 127)
|
||||
+ */
|
||||
+#define RAW_TXPOWER_SETTING
|
||||
+
|
||||
#endif /* HOSTAP_CONFIG_H */
|
||||
diff -Nur linux-2.6.17/drivers/net/wireless/hostap/hostap.h linux-2.6.17-patched/drivers/net/wireless/hostap/hostap.h
|
||||
--- linux-2.6.17/drivers/net/wireless/hostap/hostap.h 2006-06-18 04:49:35.000000000 +0300
|
||||
+++ linux-2.6.17-patched/drivers/net/wireless/hostap/hostap.h 2006-12-10 19:20:00.000000000 +0200
|
||||
@@ -89,6 +89,7 @@
|
||||
extern struct ethtool_ops prism2_ethtool_ops;
|
||||
|
||||
int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||
+int hostap_restore_power(struct net_device *dev);
|
||||
|
||||
|
||||
#endif /* HOSTAP_H */
|
||||
diff -Nur linux-2.6.17/drivers/net/wireless/hostap/hostap_hw.c linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_hw.c
|
||||
--- linux-2.6.17/drivers/net/wireless/hostap/hostap_hw.c 2006-06-18 04:49:35.000000000 +0300
|
||||
+++ linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_hw.c 2006-12-10 19:13:33.000000000 +0200
|
||||
@@ -1043,6 +1043,7 @@
|
||||
dev->name, local->fragm_threshold);
|
||||
}
|
||||
|
||||
+ hostap_restore_power(dev);
|
||||
return res;
|
||||
}
|
||||
|
||||
diff -Nur linux-2.6.17/drivers/net/wireless/hostap/hostap_info.c linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_info.c
|
||||
--- linux-2.6.17/drivers/net/wireless/hostap/hostap_info.c 2006-06-18 04:49:35.000000000 +0300
|
||||
+++ linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_info.c 2006-12-10 19:13:33.000000000 +0200
|
||||
@@ -429,6 +429,11 @@
|
||||
}
|
||||
|
||||
/* Get BSSID if we have a valid AP address */
|
||||
+
|
||||
+ if ( val == HFA384X_LINKSTATUS_CONNECTED ||
|
||||
+ val == HFA384X_LINKSTATUS_DISCONNECTED )
|
||||
+ hostap_restore_power(local->dev);
|
||||
+
|
||||
if (connected) {
|
||||
netif_carrier_on(local->dev);
|
||||
netif_carrier_on(local->ddev);
|
||||
diff -Nur linux-2.6.17/drivers/net/wireless/hostap/hostap_ioctl.c linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_ioctl.c
|
||||
--- linux-2.6.17/drivers/net/wireless/hostap/hostap_ioctl.c 2006-06-18 04:49:35.000000000 +0300
|
||||
+++ linux-2.6.17-patched/drivers/net/wireless/hostap/hostap_ioctl.c 2006-12-10 21:21:03.000000000 +0200
|
||||
@@ -1506,23 +1506,20 @@
|
||||
val = 255;
|
||||
|
||||
tmp = val;
|
||||
- tmp >>= 2;
|
||||
|
||||
- return -12 - tmp;
|
||||
+ return tmp;
|
||||
}
|
||||
|
||||
static u16 prism2_txpower_dBm_to_hfa386x(int val)
|
||||
{
|
||||
signed char tmp;
|
||||
|
||||
- if (val > 20)
|
||||
- return 128;
|
||||
- else if (val < -43)
|
||||
+ if (val > 127)
|
||||
return 127;
|
||||
+ else if (val < -128)
|
||||
+ return 128;
|
||||
|
||||
tmp = val;
|
||||
- tmp = -12 - tmp;
|
||||
- tmp <<= 2;
|
||||
|
||||
return (unsigned char) tmp;
|
||||
}
|
||||
@@ -4086,3 +4083,35 @@
|
||||
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+/* BUG FIX: Restore power setting value when lost due to F/W bug */
|
||||
+
|
||||
+int hostap_restore_power(struct net_device *dev)
|
||||
+{
|
||||
+ struct hostap_interface *iface = dev->priv;
|
||||
+ local_info_t *local = iface->local;
|
||||
+
|
||||
+ u16 val;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (local->txpower_type == PRISM2_TXPOWER_OFF) {
|
||||
+ val = 0xff; /* use all standby and sleep modes */
|
||||
+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
|
||||
+ HFA386X_CR_A_D_TEST_MODES2,
|
||||
+ &val, NULL);
|
||||
+ }
|
||||
+
|
||||
+#ifdef RAW_TXPOWER_SETTING
|
||||
+ if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
|
||||
+ val = HFA384X_TEST_CFG_BIT_ALC;
|
||||
+ local->func->cmd(dev, HFA384X_CMDCODE_TEST |
|
||||
+ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
|
||||
+ val = prism2_txpower_dBm_to_hfa386x(local->txpower);
|
||||
+ ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
|
||||
+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL));
|
||||
+ }
|
||||
+#endif /* RAW_TXPOWER_SETTING */
|
||||
+ return (ret ? -EOPNOTSUPP : 0);
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL(hostap_restore_power);
|
|
@ -0,0 +1,19 @@
|
|||
Index: linux-2.6.23-rc6/include/linux/stddef.h
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/include/linux/stddef.h 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/include/linux/stddef.h 2007-09-21 16:24:10.000000000 +0800
|
||||
@@ -16,6 +16,7 @@
|
||||
false = 0,
|
||||
true = 1
|
||||
};
|
||||
+#endif /* __KERNEL__ */
|
||||
|
||||
#undef offsetof
|
||||
#ifdef __compiler_offsetof
|
||||
@@ -23,6 +24,5 @@
|
||||
#else
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
-#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
Index: linux-2.6.23-rc6/scripts/gen_initramfs_list.sh
|
||||
===================================================================
|
||||
--- linux-2.6.23-rc6.orig/scripts/gen_initramfs_list.sh 2007-09-21 16:23:51.000000000 +0800
|
||||
+++ linux-2.6.23-rc6/scripts/gen_initramfs_list.sh 2007-09-21 16:24:11.000000000 +0800
|
||||
@@ -125,7 +125,7 @@
|
||||
str="${ftype} ${name} ${location} ${str}"
|
||||
;;
|
||||
"nod")
|
||||
- local dev=`LC_ALL=C ls -l "${location}"`
|
||||
+ local dev=`LC_ALL=C ls -l --time-style=locale "${location}"`
|
||||
local maj=`field 5 ${dev}`
|
||||
local min=`field 6 ${dev}`
|
||||
maj=${maj%,}
|
||||
@@ -135,7 +135,7 @@
|
||||
str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
|
||||
;;
|
||||
"slink")
|
||||
- local target=`field 11 $(LC_ALL=C ls -l "${location}")`
|
||||
+ local target=`field 11 $(LC_ALL=C ls -l --time-style=locale "${location}")`
|
||||
str="${ftype} ${name} ${target} ${str}"
|
||||
;;
|
||||
*)
|
|
@ -0,0 +1,12 @@
|
|||
Index: linux-2.6.23.9/arch/i386/boot/tools/build.c
|
||||
===================================================================
|
||||
--- linux-2.6.23.9.orig/arch/x86/boot/tools/build.c 2007-12-12 01:10:17.967096643 +0100
|
||||
+++ linux-2.6.23.9/arch/i386/x86/tools/build.c 2007-12-12 01:10:22.051329391 +0100
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
-#include <sys/sysmacros.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
|
@ -0,0 +1,35 @@
|
|||
Index: linux-2.6.23.14/arch/arm/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23.14.orig/arch/arm/Kconfig 2008-01-26 02:46:18.000000000 +0100
|
||||
+++ linux-2.6.23.14/arch/arm/Kconfig 2008-01-26 02:46:33.000000000 +0100
|
||||
@@ -1039,6 +1039,8 @@
|
||||
|
||||
source "drivers/leds/Kconfig"
|
||||
|
||||
+source "drivers/gpio/Kconfig"
|
||||
+
|
||||
source "drivers/media/Kconfig"
|
||||
|
||||
source "drivers/video/Kconfig"
|
||||
Index: linux-2.6.23.14/drivers/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23.14.orig/drivers/Kconfig 2008-01-26 02:45:44.000000000 +0100
|
||||
+++ linux-2.6.23.14/drivers/Kconfig 2008-01-26 02:46:05.000000000 +0100
|
||||
@@ -74,6 +74,8 @@
|
||||
|
||||
source "drivers/leds/Kconfig"
|
||||
|
||||
+source "drivers/gpio/Kconfig"
|
||||
+
|
||||
source "drivers/infiniband/Kconfig"
|
||||
|
||||
source "drivers/edac/Kconfig"
|
||||
Index: linux-2.6.23.14/drivers/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23.14.orig/drivers/Makefile 2008-01-26 02:44:13.000000000 +0100
|
||||
+++ linux-2.6.23.14/drivers/Makefile 2008-01-26 02:44:42.000000000 +0100
|
||||
@@ -91,3 +91,4 @@
|
||||
obj-$(CONFIG_OF) += of/
|
||||
obj-$(CONFIG_SSB) += ssb/
|
||||
obj-$(CONFIG_VIRTIO) += virtio/
|
||||
+obj-$(CONFIG_GPIO_DEVICE) += gpio/
|
|
@ -0,0 +1,28 @@
|
|||
Index: linux-2.6.23.16/drivers/spi/Kconfig
|
||||
===================================================================
|
||||
--- linux-2.6.23.16.orig/drivers/spi/Kconfig
|
||||
+++ linux-2.6.23.16/drivers/spi/Kconfig
|
||||
@@ -100,6 +100,11 @@ config SPI_BUTTERFLY
|
||||
inexpensive battery powered microcontroller evaluation board.
|
||||
This same cable can be used to flash new firmware.
|
||||
|
||||
+config SPI_GPIO
|
||||
+ tristate "GPIO API based bitbanging SPI controller"
|
||||
+ depends on SPI_MASTER && GENERIC_GPIO && EXPERIMENTAL
|
||||
+ select SPI_BITBANG
|
||||
+
|
||||
config SPI_IMX
|
||||
tristate "Freescale iMX SPI controller"
|
||||
depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
|
||||
Index: linux-2.6.23.16/drivers/spi/Makefile
|
||||
===================================================================
|
||||
--- linux-2.6.23.16.orig/drivers/spi/Makefile
|
||||
+++ linux-2.6.23.16/drivers/spi/Makefile
|
||||
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
|
||||
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
|
||||
+obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
|
||||
obj-$(CONFIG_SPI_IMX) += spi_imx.o
|
||||
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
|
||||
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
|
|
@ -0,0 +1,80 @@
|
|||
From a.othieno@bluewin.ch Tue Oct 11 07:50:21 2005
|
||||
From: Arthur Othieno <a.othieno@bluewin.ch>
|
||||
Subject: Big-endian I/O memory accessors.
|
||||
Date: Tue, 11 Oct 2005 07:50:21 +1000
|
||||
X-Patchwork-ID: 2759
|
||||
|
||||
From: Arthur Othieno <a.othieno@bluewin.ch>
|
||||
|
||||
I/O memory accessors. Big endian version. For those busses/devices
|
||||
that do export big-endian I/O memory.
|
||||
|
||||
Of notable relevance/reference:
|
||||
|
||||
http://lwn.net/Articles/132804/
|
||||
http://ozlabs.org/pipermail/linuxppc-embedded/2005-August/019798.html
|
||||
http://ozlabs.org/pipermail/linuxppc-embedded/2005-August/019752.html
|
||||
|
||||
Signed-off-by: Arthur Othieno <a.othieno@bluewin.ch>
|
||||
---
|
||||
|
||||
Paulus,
|
||||
|
||||
A similar patch for ppc64 made it upstream with your big ppc64 merge.
|
||||
This one is still sitting in http://patchwork.ozlabs.org/linuxppc/
|
||||
and didn't make it with the ppc32 equivalent. Thanks.
|
||||
|
||||
|
||||
include/asm-ppc/io.h | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
|
||||
---
|
||||
diff -uprN a/include/asm-ppc/io.h b/include/asm-ppc/io.h
|
||||
--- a/include/asm-ppc/io.h 2005-08-21 17:49:44.000000000 -0400
|
||||
+++ b/include/asm-ppc/io.h 2005-08-21 20:29:55.000000000 -0400
|
||||
@@ -487,11 +487,21 @@ static inline unsigned int ioread16(void
|
||||
return readw(addr);
|
||||
}
|
||||
|
||||
+static inline unsigned int ioread16be(void __iomem *addr)
|
||||
+{
|
||||
+ return in_be16(addr);
|
||||
+}
|
||||
+
|
||||
static inline unsigned int ioread32(void __iomem *addr)
|
||||
{
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
+static inline unsigned int ioread32be(void __iomem *addr)
|
||||
+{
|
||||
+ return in_be32(addr);
|
||||
+}
|
||||
+
|
||||
static inline void iowrite8(u8 val, void __iomem *addr)
|
||||
{
|
||||
writeb(val, addr);
|
||||
@@ -502,11 +512,21 @@ static inline void iowrite16(u16 val, vo
|
||||
writew(val, addr);
|
||||
}
|
||||
|
||||
+static inline void iowrite16be(u16 val, void __iomem *addr)
|
||||
+{
|
||||
+ out_be16(addr, val);
|
||||
+}
|
||||
+
|
||||
static inline void iowrite32(u32 val, void __iomem *addr)
|
||||
{
|
||||
writel(val, addr);
|
||||
}
|
||||
|
||||
+static inline void iowrite32be(u32 val, void __iomem *addr)
|
||||
+{
|
||||
+ out_be32(addr, val);
|
||||
+}
|
||||
+
|
||||
static inline void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
_insb(addr, dst, count);
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
--- linux-2.6.24.2/arch/arm/tools/mach-types 2008-04-09 01:34:47.000000000 +0200
|
||||
+++ linux-2.6.24.2-owrt/arch/arm/tools/mach-types 2008-04-09 14:26:57.000000000 +0200
|
||||
@@ -12,7 +12,7 @@
|
||||
#
|
||||
# http://www.arm.linux.org.uk/developer/machines/?action=new
|
||||
#
|
||||
-# Last update: Sat Jan 26 14:45:34 2008
|
||||
+# Last update: Sat Apr 19 15:13:28 2008
|
||||
#
|
||||
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
|
||||
#
|
||||
@@ -381,13 +381,13 @@
|
||||
se4000 ARCH_SE4000 SE4000 364
|
||||
quadriceps ARCH_QUADRICEPS QUADRICEPS 365
|
||||
bronco ARCH_BRONCO BRONCO 366
|
||||
-esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367
|
||||
+esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367
|
||||
esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
|
||||
s5c7375 ARCH_S5C7375 S5C7375 369
|
||||
spearhead ARCH_SPEARHEAD SPEARHEAD 370
|
||||
pantera ARCH_PANTERA PANTERA 371
|
||||
prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
|
||||
-gumstix ARCH_GUMSTIK GUMSTIK 373
|
||||
+gumstix ARCH_GUMSTIX GUMSTIX 373
|
||||
rcube ARCH_RCUBE RCUBE 374
|
||||
rea_olv ARCH_REA_OLV REA_OLV 375
|
||||
pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
|
||||
@@ -1463,7 +1463,7 @@
|
||||
htctitan MACH_HTCTITAN HTCTITAN 1463
|
||||
qranium MACH_QRANIUM QRANIUM 1464
|
||||
adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465
|
||||
-adx_medinet MACH_ADX_MEDINET ADX_MEDINET 1466
|
||||
+adx_medcom MACH_ADX_MEDINET ADX_MEDINET 1466
|
||||
bboard MACH_BBOARD BBOARD 1467
|
||||
cambria MACH_CAMBRIA CAMBRIA 1468
|
||||
mt7xxx MACH_MT7XXX MT7XXX 1469
|
||||
@@ -1611,3 +1611,112 @@
|
||||
mt7108 MACH_MT7108 MT7108 1613
|
||||
smtr2440 MACH_SMTR2440 SMTR2440 1614
|
||||
manao MACH_MANAO MANAO 1615
|
||||
+cm_x300 MACH_CM_X300 CM_X300 1616
|
||||
+gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617
|
||||
+lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618
|
||||
+arma37 MACH_ARMA37 ARMA37 1619
|
||||
+mendel MACH_MENDEL MENDEL 1620
|
||||
+pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621
|
||||
+unit2p MACH_UNIT2P UNIT2P 1622
|
||||
+inc20otter MACH_INC20OTTER INC20OTTER 1623
|
||||
+at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624
|
||||
+sc_ge2 MACH_STORCENTER STORCENTER 1625
|
||||
+smdk6410 MACH_SMDK6410 SMDK6410 1626
|
||||
+u300 MACH_U300 U300 1627
|
||||
+u500 MACH_U500 U500 1628
|
||||
+ds9260 MACH_DS9260 DS9260 1629
|
||||
+riverrock MACH_RIVERROCK RIVERROCK 1630
|
||||
+scibath MACH_SCIBATH SCIBATH 1631
|
||||
+at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632
|
||||
+wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633
|
||||
+multimedia MACH_MULTIMEDIA MULTIMEDIA 1634
|
||||
+marvin MACH_MARVIN MARVIN 1635
|
||||
+x500 MACH_X500 X500 1636
|
||||
+awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637
|
||||
+palermoc MACH_PALERMOC PALERMOC 1638
|
||||
+omap_ldp MACH_OMAP_LDP OMAP_LDP 1639
|
||||
+ip500 MACH_IP500 IP500 1640
|
||||
+mx35ads MACH_MACH_MX35ADS MACH_MX35ADS 1641
|
||||
+ase2 MACH_ASE2 ASE2 1642
|
||||
+mx35evb MACH_MX35EVB MX35EVB 1643
|
||||
+aml_m8050 MACH_AML_M8050 AML_M8050 1644
|
||||
+mx35_3ds MACH_MX35_3DS MX35_3DS 1645
|
||||
+mars MACH_MARS MARS 1646
|
||||
+ntosd_644xa MACH_NTOSD_644XA NTOSD_644XA 1647
|
||||
+badger MACH_BADGER BADGER 1648
|
||||
+trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649
|
||||
+trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650
|
||||
+marlin MACH_MARLIN MARLIN 1651
|
||||
+ts7800 MACH_TS7800 TS7800 1652
|
||||
+hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653
|
||||
+at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654
|
||||
+ne1board MACH_NE1BOARD NE1BOARD 1655
|
||||
+zante MACH_ZANTE ZANTE 1656
|
||||
+sffsdr MACH_SFFSDR SFFSDR 1657
|
||||
+tw2662 MACH_TW2662 TW2662 1658
|
||||
+vf10xx MACH_VF10XX VF10XX 1659
|
||||
+zoran43xx MACH_ZORAN43XX ZORAN43XX 1660
|
||||
+sonix926 MACH_SONIX926 SONIX926 1661
|
||||
+celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662
|
||||
+cc9m2443 MACH_CC9M2443 CC9M2443 1663
|
||||
+tw5334 MACH_TW5334 TW5334 1664
|
||||
+omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665
|
||||
+nal_hlite MACH_NAL_HLITE NAL_HLITE 1666
|
||||
+htcvogue MACH_HTCVOGUE HTCVOGUE 1667
|
||||
+smartweb MACH_SMARTWEB SMARTWEB 1668
|
||||
+mv86xx MACH_MV86XX MV86XX 1669
|
||||
+mv87xx MACH_MV87XX MV87XX 1670
|
||||
+songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671
|
||||
+younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672
|
||||
+pcm037 MACH_PCM037 PCM037 1673
|
||||
+mmvp MACH_MMVP MMVP 1674
|
||||
+mmap MACH_MMAP MMAP 1675
|
||||
+ptid2410 MACH_PTID2410 PTID2410 1676
|
||||
+james_926 MACH_JAMES_926 JAMES_926 1677
|
||||
+fm6000 MACH_FM6000 FM6000 1678
|
||||
+db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680
|
||||
+rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681
|
||||
+rd88f6281 MACH_RD88F6281 RD88F6281 1682
|
||||
+db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683
|
||||
+smdk2416 MACH_SMDK2416 SMDK2416 1685
|
||||
+oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686
|
||||
+oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687
|
||||
+rovern6 MACH_ROVERN6 ROVERN6 1688
|
||||
+pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689
|
||||
+wbd111 MACH_WBD111 WBD111 1690
|
||||
+elaracpe MACH_ELARACPE ELARACPE 1691
|
||||
+mabv3 MACH_MABV3 MABV3 1692
|
||||
+mv2120 MACH_MV2120 MV2120 1693
|
||||
+csb737 MACH_CSB737 CSB737 1695
|
||||
+mx51_3ds MACH_MX51_3DS MX51_3DS 1696
|
||||
+g900 MACH_G900 G900 1697
|
||||
+apf27 MACH_APF27 APF27 1698
|
||||
+ggus2000 MACH_GGUS2000 GGUS2000 1699
|
||||
+omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700
|
||||
+imx27lite MACH_IMX27LITE IMX27LITE 1701
|
||||
+almex MACH_ALMEX ALMEX 1702
|
||||
+control MACH_CONTROL CONTROL 1703
|
||||
+mba2410 MACH_MBA2410 MBA2410 1704
|
||||
+volcano MACH_VOLCANO VOLCANO 1705
|
||||
+zenith MACH_ZENITH ZENITH 1706
|
||||
+muchip MACH_MUCHIP MUCHIP 1707
|
||||
+magellan MACH_MAGELLAN MAGELLAN 1708
|
||||
+usb_a9260 MACH_USB_A9260 USB_A9260 1709
|
||||
+usb_a9263 MACH_USB_A9263 USB_A9263 1710
|
||||
+qil_a9260 MACH_QIL_A9260 QIL_A9260 1711
|
||||
+cme9210 MACH_CME9210 CME9210 1712
|
||||
+hczh4 MACH_HCZH4 HCZH4 1713
|
||||
+spearbasic MACH_SPEARBASIC SPEARBASIC 1714
|
||||
+dep2440 MACH_DEP2440 DEP2440 1715
|
||||
+hdl_gxr MACH_HDL_GXR HDL_GXR 1716
|
||||
+hdl_gt MACH_HDL_GT HDL_GT 1717
|
||||
+hdl_4g MACH_HDL_4G HDL_4G 1718
|
||||
+s3c6000 MACH_S3C6000 S3C6000 1719
|
||||
+mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720
|
||||
+mpx220 MACH_MPX220 MPX220 1721
|
||||
+kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722
|
||||
+htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723
|
||||
+htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724
|
||||
+lg_ks20 MACH_LG_KS20 LG_KS20 1725
|
||||
+hhgps MACH_HHGPS HHGPS 1726
|
||||
+nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727
|
Loading…
Reference in New Issue