📄 strip.c
字号:
* labelled in such a way that st0 can't use it). * * Thanks to Petros Maniatis for coming up with the idea of splitting * inbound and outbound traffic between two interfaces, which turned * out to be really easy to implement, even if it is a bit of a hack. * * Having set a manual address on an interface, you can restore it * to automatic operation (where the address is automatically kept * consistent with the real address of the radio) by setting a manual * address of all ones, e.g. "ifconfig st0 hw strip FFFFFFFFFFFF" * This 'turns off' manual override mode for the device address. * * Note: The IEEE 802 headers reported in tcpdump will show the *real* * radio addresses the packets were sent and received from, so that you * can see what is really going on with packets, and which interfaces * they are really going through. *//************************************************************************//* Constants *//* * CommandString1 works on all radios * Other CommandStrings are only used with firmware that provides structured responses. * * ats319=1 Enables Info message for node additions and deletions * ats319=2 Enables Info message for a new best node * ats319=4 Enables checksums * ats319=8 Enables ACK messages */static const int MaxCommandStringLength = 32;static const int CompatibilityCommand = 1;static const char CommandString0[] = "*&COMMAND*ATS319=7"; /* Turn on checksums & info messages */static const char CommandString1[] = "*&COMMAND*ATS305?"; /* Query radio name */static const char CommandString2[] = "*&COMMAND*ATS325?"; /* Query battery voltage */static const char CommandString3[] = "*&COMMAND*ATS300?"; /* Query version information */static const char CommandString4[] = "*&COMMAND*ATS311?"; /* Query poletop list */static const char CommandString5[] = "*&COMMAND*AT~LA"; /* Query portables list */typedef struct { const char *string; long length; } StringDescriptor;static const StringDescriptor CommandString[] = { { CommandString0, sizeof(CommandString0)-1 }, { CommandString1, sizeof(CommandString1)-1 }, { CommandString2, sizeof(CommandString2)-1 }, { CommandString3, sizeof(CommandString3)-1 }, { CommandString4, sizeof(CommandString4)-1 }, { CommandString5, sizeof(CommandString5)-1 } };#define GOT_ALL_RADIO_INFO(S) \ ((S)->firmware_version.c[0] && \ (S)->battery_voltage.c[0] && \ memcmp(&(S)->true_dev_addr, zero_address.c, sizeof(zero_address)))static const char hextable[16] = "0123456789ABCDEF";static const MetricomAddress zero_address;static const MetricomAddress broadcast_address = { { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF } };static const MetricomKey SIP0Key = { { "SIP0" } };static const MetricomKey ARP0Key = { { "ARP0" } };static const MetricomKey ATR_Key = { { "ATR " } };static const MetricomKey ACK_Key = { { "ACK_" } };static const MetricomKey INF_Key = { { "INF_" } };static const MetricomKey ERR_Key = { { "ERR_" } };static const long MaxARPInterval = 60 * HZ; /* One minute *//* * Maximum Starmode packet length is 1183 bytes. Allowing 4 bytes for * protocol key, 4 bytes for checksum, one byte for CR, and 65/64 expansion * for STRIP encoding, that translates to a maximum payload MTU of 1155. * Note: A standard NFS 1K data packet is a total of 0x480 (1152) bytes * long, including IP header, UDP header, and NFS header. Setting the STRIP * MTU to 1152 allows us to send default sized NFS packets without fragmentation. */static const unsigned short MAX_SEND_MTU = 1152;static const unsigned short MAX_RECV_MTU = 1500; /* Hoping for Ethernet sized packets in the future! */static const unsigned short DEFAULT_STRIP_MTU = 1152;static const int STRIP_MAGIC = 0x5303;static const long LongTime = 0x7FFFFFFF;/************************************************************************//* Global variables */static struct strip *struct_strip_list;/************************************************************************//* Macros *//* Returns TRUE if text T begins with prefix P */#define has_prefix(T,L,P) (((L) >= sizeof(P)-1) && !strncmp((T), (P), sizeof(P)-1))/* Returns TRUE if text T of length L is equal to string S */#define text_equal(T,L,S) (((L) == sizeof(S)-1) && !strncmp((T), (S), sizeof(S)-1))#define READHEX(X) ((X)>='0' && (X)<='9' ? (X)-'0' : \ (X)>='a' && (X)<='f' ? (X)-'a'+10 : \ (X)>='A' && (X)<='F' ? (X)-'A'+10 : 0 )#define READHEX16(X) ((__u16)(READHEX(X)))#define READDEC(X) ((X)>='0' && (X)<='9' ? (X)-'0' : 0)#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))#define ELEMENTS_OF(X) (sizeof(X) / sizeof((X)[0]))#define ARRAY_END(X) (&((X)[ELEMENTS_OF(X)]))#define JIFFIE_TO_SEC(X) ((X) / HZ)/************************************************************************//* Utility routines */typedef unsigned long InterruptStatus;static inline InterruptStatus DisableInterrupts(void){ InterruptStatus x; save_flags(x); cli(); return(x);}static inline void RestoreInterrupts(InterruptStatus x){ restore_flags(x);}static int arp_query(unsigned char *haddr, u32 paddr, struct net_device * dev){ struct neighbour *neighbor_entry; neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev); if (neighbor_entry != NULL) { neighbor_entry->used = jiffies; if (neighbor_entry->nud_state & NUD_VALID) { memcpy(haddr, neighbor_entry->ha, dev->addr_len); return 1; } } return 0;}static void DumpData(char *msg, struct strip *strip_info, __u8 *ptr, __u8 *end){ static const int MAX_DumpData = 80; __u8 pkt_text[MAX_DumpData], *p = pkt_text; *p++ = '\"'; while (ptr<end && p < &pkt_text[MAX_DumpData-4]) { if (*ptr == '\\') { *p++ = '\\'; *p++ = '\\'; } else { if (*ptr >= 32 && *ptr <= 126) { *p++ = *ptr; } else { sprintf(p, "\\%02X", *ptr); p+= 3; } } ptr++; } if (ptr == end) { *p++ = '\"'; } *p++ = 0; printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev.name, msg, pkt_text);}#if 0static void HexDump(char *msg, struct strip *strip_info, __u8 *start, __u8 *end){ __u8 *ptr = start; printk(KERN_INFO "%s: %s: %d bytes\n", strip_info->dev.name, msg, end-ptr); while (ptr < end) { long offset = ptr - start; __u8 text[80], *p = text; while (ptr < end && p < &text[16*3]) { *p++ = hextable[*ptr >> 4]; *p++ = hextable[*ptr++ & 0xF]; *p++ = ' '; } p[-1] = 0; printk(KERN_INFO "%s: %4lX %s\n", strip_info->dev.name, offset, text); }}#endif/************************************************************************//* Byte stuffing/unstuffing routines *//* Stuffing scheme: * 00 Unused (reserved character) * 01-3F Run of 2-64 different characters * 40-7F Run of 1-64 different characters plus a single zero at the end * 80-BF Run of 1-64 of the same character * C0-FF Run of 1-64 zeroes (ASCII 0) */typedef enum{ Stuff_Diff = 0x00, Stuff_DiffZero = 0x40, Stuff_Same = 0x80, Stuff_Zero = 0xC0, Stuff_NoCode = 0xFF, /* Special code, meaning no code selected */ Stuff_CodeMask = 0xC0, Stuff_CountMask = 0x3F, Stuff_MaxCount = 0x3F, Stuff_Magic = 0x0D /* The value we are eliminating */} StuffingCode;/* StuffData encodes the data starting at "src" for "length" bytes. * It writes it to the buffer pointed to by "dst" (which must be at least * as long as 1 + 65/64 of the input length). The output may be up to 1.6% * larger than the input for pathological input, but will usually be smaller. * StuffData returns the new value of the dst pointer as its result. * "code_ptr_ptr" points to a "__u8 *" which is used to hold encoding state * between calls, allowing an encoded packet to be incrementally built up * from small parts. On the first call, the "__u8 *" pointed to should be * initialized to NULL; between subsequent calls the calling routine should * leave the value alone and simply pass it back unchanged so that the * encoder can recover its current state. */#define StuffData_FinishBlock(X) \(*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode)static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr){ __u8 *end = src + length; __u8 *code_ptr = *code_ptr_ptr; __u8 code = Stuff_NoCode, count = 0; if (!length) return(dst); if (code_ptr) { /* * Recover state from last call, if applicable */ code = (*code_ptr ^ Stuff_Magic) & Stuff_CodeMask; count = (*code_ptr ^ Stuff_Magic) & Stuff_CountMask; } while (src < end) { switch (code) { /* Stuff_NoCode: If no current code, select one */ case Stuff_NoCode: /* Record where we're going to put this code */ code_ptr = dst++; count = 0; /* Reset the count (zero means one instance) */ /* Tentatively start a new block */ if (*src == 0) { code = Stuff_Zero; src++; } else { code = Stuff_Same; *dst++ = *src++ ^ Stuff_Magic; } /* Note: We optimistically assume run of same -- */ /* which will be fixed later in Stuff_Same */ /* if it turns out not to be true. */ break; /* Stuff_Zero: We already have at least one zero encoded */ case Stuff_Zero: /* If another zero, count it, else finish this code block */ if (*src == 0) { count++; src++; } else { StuffData_FinishBlock(Stuff_Zero + count); } break; /* Stuff_Same: We already have at least one byte encoded */ case Stuff_Same: /* If another one the same, count it */ if ((*src ^ Stuff_Magic) == code_ptr[1]) { count++; src++; break; } /* else, this byte does not match this block. */ /* If we already have two or more bytes encoded, finish this code block */ if (count) { StuffData_FinishBlock(Stuff_Same + count); break; } /* else, we only have one so far, so switch to Stuff_Diff code */ code = Stuff_Diff; /* and fall through to Stuff_Diff case below * Note cunning cleverness here: case Stuff_Diff compares * the current character with the previous two to see if it * has a run of three the same. Won't this be an error if * there aren't two previous characters stored to compare with? * No. Because we know the current character is *not* the same * as the previous one, the first test below will necessarily * fail and the send half of the "if" won't be executed. */ /* Stuff_Diff: We have at least two *different* bytes encoded */ case Stuff_Diff: /* If this is a zero, must encode a Stuff_DiffZero, and begin a new block */ if (*src == 0) { StuffData_FinishBlock(Stuff_DiffZero + count); } /* else, if we have three in a row, it is worth starting a Stuff_Same block */ else if ((*src ^ Stuff_Magic)==dst[-1] && dst[-1]==dst[-2]) { /* Back off the last two characters we encoded */ code += count-2; /* Note: "Stuff_Diff + 0" is an illegal code */ if (code == Stuff_Diff + 0) { code = Stuff_Same + 0; } StuffData_FinishBlock(code); code_ptr = dst-2; /* dst[-1] already holds the correct value */ count = 2; /* 2 means three bytes encoded */ code = Stuff_Same; } /* else, another different byte, so add it to the block */ else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -