📄 strip.c
字号:
/* * 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 LIST_HEAD(strip_list);static DEFINE_SPINLOCK(strip_lock);/************************************************************************//* 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 ARRAY_END(X) (&((X)[ARRAY_SIZE(X)]))#define JIFFIE_TO_SEC(X) ((X) / HZ)/************************************************************************//* Utility routines */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);}/************************************************************************//* 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 { *dst++ = *src ^ Stuff_Magic; count++; } src++; /* Consume the byte */ break; } if (count == Stuff_MaxCount) { StuffData_FinishBlock(code + count); } } if (code == Stuff_NoCode) { *code_ptr_ptr = NULL; } else { *code_ptr_ptr = code_ptr; StuffData_FinishBlock(code + count); } return (dst);}/* * UnStuffData decodes the data at "src", up to (but not including) "end". * It writes the decoded data into the buffer pointed to by "dst", up to a * maximum of "dst_length", and returns the new value of "src" so that a * follow-on call can read more data, continuing from where the first left off. * * There are three types of results: * 1. The source data runs out before extracting "dst_length" bytes: * UnStuffData returns NULL to indicate failure. * 2. The source data produces exactly "dst_length" bytes: * UnStuffData returns new_src = end to indicate that all bytes were consumed. * 3. "dst_length" bytes are extracted, with more remaining. * UnStuffData returns new_src < end to indicate that there are more bytes * to be read. * * Note: The decoding may be destructive, in that it may alter the source * data in the process of decoding it (this is necessary to allow a follow-on * call to resume correctly). */static __u8 *UnStuffData(__u8 * src, __u8 * end, __u8 * dst, __u32 dst_length){ __u8 *dst_end = dst + dst_length; /* Sanity check */ if (!src || !end || !dst || !dst_length) return (NULL); while (src < end && dst < dst_end) { int count = (*src ^ Stuff_Magic) & Stuff_CountMask; switch ((*src ^ Stuff_Magic) & Stuff_CodeMask) { case Stuff_Diff: if (src + 1 + count >= end) return (NULL); do { *dst++ = *++src ^ Stuff_Magic; } while (--count >= 0 && dst < dst_end); if (count < 0) src += 1; else { if (count == 0) *src = Stuff_Same ^ Stuff_Magic; else *src = (Stuff_Diff + count) ^ Stuff_Magic; } break; case Stuff_DiffZero: if (src + 1 + count >= end) return (NULL); do { *dst++ = *++src ^ Stuff_Magic; } while (--count >= 0 && dst < dst_end); if (count < 0) *src = Stuff_Zero ^ Stuff_Magic; else *src = (Stuff_DiffZero + count) ^ Stuff_Magic; break; case Stuff_Same: if (src + 1 >= end) return (NULL); do { *dst++ = src[1] ^ Stuff_Magic; } while (--count >= 0 && dst < dst_end); if (count < 0) src += 2; else *src = (Stuff_Same + count) ^ Stuff_Magic; break; case Stuff_Zero: do { *dst++ = 0; } while (--count >= 0 && dst < dst_end); if (count < 0) src += 1; else *src = (Stuff_Zero + count) ^ Stuff_Magic; break; } } if (dst < dst_end) return (NULL); else return (src);}/************************************************************************//* General routines for STRIP *//* * get_baud returns the current baud rate, as one of the constants defined in * termbits.h * If the user has issued a baud rate override using the 'setserial' command * and the logical current rate is set to 38.4, then the true baud rate * currently in effect (57.6 or 115.2) is returned. */static unsigned int get_baud(struct tty_struct *tty){ if (!tty || !tty->termios) return (0); if ((tty->termios->c_cflag & CBAUD) == B38400 && tty->driver_data) { struct async_struct *info = (struct async_struct *) tty->driver_data; if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) return (B57600); if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) return (B115200); } return (tty->termios->c_cflag & CBAUD);}/* * set_baud sets the baud rate to the rate defined by baudcode * Note: The rate B38400 should be avoided, because the user may have * issued a 'setserial' speed override to map that to a different speed. * We could achieve a true rate of 38400 if we needed to by cancelling * any user speed override that is in place, but that might annoy the * user, so it is simplest to just avoid using 38400. */static void set_baud(struct tty_struct *tty, unsigned int baudcode){ struct termios old_termios = *(tty->termios); tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */ tty->termios->c_cflag |= baudcode; /* Set the new baud setting */ tty->driver->set_termios(tty, &old_termios);}/* * Convert a string to a Metricom Address. */#define IS_RADIO_ADDRESS(p) ( \ isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) && isdigit((p)[3]) && \ (p)[4] == '-' && \ isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8]) )static int string_to_radio_address(MetricomAddress * addr, __u8 * p){ if (!IS_RADIO_ADDRESS(p)) return (1); addr->c[0] = 0; addr->c[1] = 0; addr->c[2] = READHEX(p[0]) << 4 | READHEX(p[1]); addr->c[3] = READHEX(p[2]) << 4 | READHEX(p[3]); addr->c[4] = READHEX(p[5]) << 4 | READHEX(p[6]); addr->c[5] = READHEX(p[7]) << 4 | READHEX(p[8]); return (0);}/* * Convert a Metricom Address to a string. */static __u8 *radio_address_to_string(const MetricomAddress * addr, MetricomAddressString * p){ sprintf(p->c, "%02X%02X-%02X%02X", addr->c[2], addr->c[3], addr->c[4], addr->c[5]); return (p->c);}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -