mirror of
https://github.com/hohn/sarif-cli.git
synced 2025-12-16 09:13:04 +01:00
Add source files for relatedLocations
This commit is contained in:
committed by
=Michael Hohn
parent
4ca7dda579
commit
502cb21850
558
data/linux-small/include/linux/etherdevice.h
Normal file
558
data/linux-small/include/linux/etherdevice.h
Normal file
@@ -0,0 +1,558 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* INET An implementation of the TCP/IP protocol suite for the LINUX
|
||||
* operating system. NET is implemented using the BSD Socket
|
||||
* interface as the means of communication with the user level.
|
||||
*
|
||||
* Definitions for the Ethernet handlers.
|
||||
*
|
||||
* Version: @(#)eth.h 1.0.4 05/13/93
|
||||
*
|
||||
* Authors: Ross Biro
|
||||
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
|
||||
*
|
||||
* Relocated to include/linux where it belongs by Alan Cox
|
||||
* <gw4pts@gw4pts.ampr.org>
|
||||
*/
|
||||
#ifndef _LINUX_ETHERDEVICE_H
|
||||
#define _LINUX_ETHERDEVICE_H
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <asm/bitsperlong.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct device;
|
||||
int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr);
|
||||
unsigned char *arch_get_platform_mac_address(void);
|
||||
int nvmem_get_mac_address(struct device *dev, void *addrbuf);
|
||||
u32 eth_get_headlen(const struct net_device *dev, const void *data, u32 len);
|
||||
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
|
||||
extern const struct header_ops eth_header_ops;
|
||||
|
||||
int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
|
||||
const void *daddr, const void *saddr, unsigned len);
|
||||
int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
|
||||
int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
|
||||
__be16 type);
|
||||
void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev,
|
||||
const unsigned char *haddr);
|
||||
__be16 eth_header_parse_protocol(const struct sk_buff *skb);
|
||||
int eth_prepare_mac_addr_change(struct net_device *dev, void *p);
|
||||
void eth_commit_mac_addr_change(struct net_device *dev, void *p);
|
||||
int eth_mac_addr(struct net_device *dev, void *p);
|
||||
int eth_validate_addr(struct net_device *dev);
|
||||
|
||||
struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
|
||||
unsigned int rxqs);
|
||||
#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
|
||||
#define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)
|
||||
|
||||
struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv,
|
||||
unsigned int txqs,
|
||||
unsigned int rxqs);
|
||||
#define devm_alloc_etherdev(dev, sizeof_priv) devm_alloc_etherdev_mqs(dev, sizeof_priv, 1, 1)
|
||||
|
||||
struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb);
|
||||
int eth_gro_complete(struct sk_buff *skb, int nhoff);
|
||||
|
||||
/* Reserved Ethernet Addresses per IEEE 802.1Q */
|
||||
static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
|
||||
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
|
||||
#define eth_stp_addr eth_reserved_addr_base
|
||||
|
||||
/**
|
||||
* is_link_local_ether_addr - Determine if given Ethernet address is link-local
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
|
||||
* IEEE 802.1Q 8.6.3 Frame filtering.
|
||||
*
|
||||
* Please note: addr must be aligned to u16.
|
||||
*/
|
||||
static inline bool is_link_local_ether_addr(const u8 *addr)
|
||||
{
|
||||
__be16 *a = (__be16 *)addr;
|
||||
static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
|
||||
static const __be16 m = cpu_to_be16(0xfff0);
|
||||
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
return (((*(const u32 *)addr) ^ (*(const u32 *)b)) |
|
||||
(__force int)((a[2] ^ b[2]) & m)) == 0;
|
||||
#else
|
||||
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return true if the address is all zeroes.
|
||||
*
|
||||
* Please note: addr must be aligned to u16.
|
||||
*/
|
||||
static inline bool is_zero_ether_addr(const u8 *addr)
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
return ((*(const u32 *)addr) | (*(const u16 *)(addr + 4))) == 0;
|
||||
#else
|
||||
return (*(const u16 *)(addr + 0) |
|
||||
*(const u16 *)(addr + 2) |
|
||||
*(const u16 *)(addr + 4)) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return true if the address is a multicast address.
|
||||
* By definition the broadcast address is also a multicast address.
|
||||
*/
|
||||
static inline bool is_multicast_ether_addr(const u8 *addr)
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
u32 a = *(const u32 *)addr;
|
||||
#else
|
||||
u16 a = *(const u16 *)addr;
|
||||
#endif
|
||||
#ifdef __BIG_ENDIAN
|
||||
return 0x01 & (a >> ((sizeof(a) * 8) - 8));
|
||||
#else
|
||||
return 0x01 & a;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2])
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
|
||||
#ifdef __BIG_ENDIAN
|
||||
return 0x01 & ((*(const u64 *)addr) >> 56);
|
||||
#else
|
||||
return 0x01 & (*(const u64 *)addr);
|
||||
#endif
|
||||
#else
|
||||
return is_multicast_ether_addr(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802).
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return true if the address is a local address.
|
||||
*/
|
||||
static inline bool is_local_ether_addr(const u8 *addr)
|
||||
{
|
||||
return 0x02 & addr[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* is_broadcast_ether_addr - Determine if the Ethernet address is broadcast
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return true if the address is the broadcast address.
|
||||
*
|
||||
* Please note: addr must be aligned to u16.
|
||||
*/
|
||||
static inline bool is_broadcast_ether_addr(const u8 *addr)
|
||||
{
|
||||
return (*(const u16 *)(addr + 0) &
|
||||
*(const u16 *)(addr + 2) &
|
||||
*(const u16 *)(addr + 4)) == 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_unicast_ether_addr - Determine if the Ethernet address is unicast
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return true if the address is a unicast address.
|
||||
*/
|
||||
static inline bool is_unicast_ether_addr(const u8 *addr)
|
||||
{
|
||||
return !is_multicast_ether_addr(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_valid_ether_addr - Determine if the given Ethernet address is valid
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
|
||||
* a multicast address, and is not FF:FF:FF:FF:FF:FF.
|
||||
*
|
||||
* Return true if the address is valid.
|
||||
*
|
||||
* Please note: addr must be aligned to u16.
|
||||
*/
|
||||
static inline bool is_valid_ether_addr(const u8 *addr)
|
||||
{
|
||||
/* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
|
||||
* explicitly check for it here. */
|
||||
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_proto_is_802_3 - Determine if a given Ethertype/length is a protocol
|
||||
* @proto: Ethertype/length value to be tested
|
||||
*
|
||||
* Check that the value from the Ethertype/length field is a valid Ethertype.
|
||||
*
|
||||
* Return true if the valid is an 802.3 supported Ethertype.
|
||||
*/
|
||||
static inline bool eth_proto_is_802_3(__be16 proto)
|
||||
{
|
||||
#ifndef __BIG_ENDIAN
|
||||
/* if CPU is little endian mask off bits representing LSB */
|
||||
proto &= htons(0xFF00);
|
||||
#endif
|
||||
/* cast both to u16 and compare since LSB can be ignored */
|
||||
return (__force u16)proto >= (__force u16)htons(ETH_P_802_3_MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_random_addr - Generate software assigned random Ethernet address
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Generate a random Ethernet address (MAC) that is not multicast
|
||||
* and has the local assigned bit set.
|
||||
*/
|
||||
static inline void eth_random_addr(u8 *addr)
|
||||
{
|
||||
get_random_bytes(addr, ETH_ALEN);
|
||||
addr[0] &= 0xfe; /* clear multicast bit */
|
||||
addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
|
||||
}
|
||||
|
||||
#define random_ether_addr(addr) eth_random_addr(addr)
|
||||
|
||||
/**
|
||||
* eth_broadcast_addr - Assign broadcast address
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Assign the broadcast address to the given address array.
|
||||
*/
|
||||
static inline void eth_broadcast_addr(u8 *addr)
|
||||
{
|
||||
memset(addr, 0xff, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_zero_addr - Assign zero address
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Assign the zero address to the given address array.
|
||||
*/
|
||||
static inline void eth_zero_addr(u8 *addr)
|
||||
{
|
||||
memset(addr, 0x00, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_hw_addr_random - Generate software assigned random Ethernet and
|
||||
* set device flag
|
||||
* @dev: pointer to net_device structure
|
||||
*
|
||||
* Generate a random Ethernet address (MAC) to be used by a net device
|
||||
* and set addr_assign_type so the state can be read by sysfs and be
|
||||
* used by userspace.
|
||||
*/
|
||||
static inline void eth_hw_addr_random(struct net_device *dev)
|
||||
{
|
||||
dev->addr_assign_type = NET_ADDR_RANDOM;
|
||||
eth_random_addr(dev->dev_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_hw_addr_crc - Calculate CRC from netdev_hw_addr
|
||||
* @ha: pointer to hardware address
|
||||
*
|
||||
* Calculate CRC from a hardware address as basis for filter hashes.
|
||||
*/
|
||||
static inline u32 eth_hw_addr_crc(struct netdev_hw_addr *ha)
|
||||
{
|
||||
return ether_crc(ETH_ALEN, ha->addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_addr_copy - Copy an Ethernet address
|
||||
* @dst: Pointer to a six-byte array Ethernet address destination
|
||||
* @src: Pointer to a six-byte array Ethernet address source
|
||||
*
|
||||
* Please note: dst & src must both be aligned to u16.
|
||||
*/
|
||||
static inline void ether_addr_copy(u8 *dst, const u8 *src)
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
*(u32 *)dst = *(const u32 *)src;
|
||||
*(u16 *)(dst + 4) = *(const u16 *)(src + 4);
|
||||
#else
|
||||
u16 *a = (u16 *)dst;
|
||||
const u16 *b = (const u16 *)src;
|
||||
|
||||
a[0] = b[0];
|
||||
a[1] = b[1];
|
||||
a[2] = b[2];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_hw_addr_set - Assign Ethernet address to a net_device
|
||||
* @dev: pointer to net_device structure
|
||||
* @addr: address to assign
|
||||
*
|
||||
* Assign given address to the net_device, addr_assign_type is not changed.
|
||||
*/
|
||||
static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr)
|
||||
{
|
||||
__dev_addr_set(dev, addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_hw_addr_inherit - Copy dev_addr from another net_device
|
||||
* @dst: pointer to net_device to copy dev_addr to
|
||||
* @src: pointer to net_device to copy dev_addr from
|
||||
*
|
||||
* Copy the Ethernet address from one net_device to another along with
|
||||
* the address attributes (addr_assign_type).
|
||||
*/
|
||||
static inline void eth_hw_addr_inherit(struct net_device *dst,
|
||||
struct net_device *src)
|
||||
{
|
||||
dst->addr_assign_type = src->addr_assign_type;
|
||||
ether_addr_copy(dst->dev_addr, src->dev_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_addr_equal - Compare two Ethernet addresses
|
||||
* @addr1: Pointer to a six-byte array containing the Ethernet address
|
||||
* @addr2: Pointer other six-byte array containing the Ethernet address
|
||||
*
|
||||
* Compare two Ethernet addresses, returns true if equal
|
||||
*
|
||||
* Please note: addr1 & addr2 must both be aligned to u16.
|
||||
*/
|
||||
static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
|
||||
((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
|
||||
|
||||
return fold == 0;
|
||||
#else
|
||||
const u16 *a = (const u16 *)addr1;
|
||||
const u16 *b = (const u16 *)addr2;
|
||||
|
||||
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_addr_equal_64bits - Compare two Ethernet addresses
|
||||
* @addr1: Pointer to an array of 8 bytes
|
||||
* @addr2: Pointer to an other array of 8 bytes
|
||||
*
|
||||
* Compare two Ethernet addresses, returns true if equal, false otherwise.
|
||||
*
|
||||
* The function doesn't need any conditional branches and possibly uses
|
||||
* word memory accesses on CPU allowing cheap unaligned memory reads.
|
||||
* arrays = { byte1, byte2, byte3, byte4, byte5, byte6, pad1, pad2 }
|
||||
*
|
||||
* Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits.
|
||||
*/
|
||||
|
||||
static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
|
||||
const u8 addr2[6+2])
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
|
||||
u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
return (fold >> 16) == 0;
|
||||
#else
|
||||
return (fold << 16) == 0;
|
||||
#endif
|
||||
#else
|
||||
return ether_addr_equal(addr1, addr2);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_addr_equal_unaligned - Compare two not u16 aligned Ethernet addresses
|
||||
* @addr1: Pointer to a six-byte array containing the Ethernet address
|
||||
* @addr2: Pointer other six-byte array containing the Ethernet address
|
||||
*
|
||||
* Compare two Ethernet addresses, returns true if equal
|
||||
*
|
||||
* Please note: Use only when any Ethernet address may not be u16 aligned.
|
||||
*/
|
||||
static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2)
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
||||
return ether_addr_equal(addr1, addr2);
|
||||
#else
|
||||
return memcmp(addr1, addr2, ETH_ALEN) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_addr_equal_masked - Compare two Ethernet addresses with a mask
|
||||
* @addr1: Pointer to a six-byte array containing the 1st Ethernet address
|
||||
* @addr2: Pointer to a six-byte array containing the 2nd Ethernet address
|
||||
* @mask: Pointer to a six-byte array containing the Ethernet address bitmask
|
||||
*
|
||||
* Compare two Ethernet addresses with a mask, returns true if for every bit
|
||||
* set in the bitmask the equivalent bits in the ethernet addresses are equal.
|
||||
* Using a mask with all bits set is a slower ether_addr_equal.
|
||||
*/
|
||||
static inline bool ether_addr_equal_masked(const u8 *addr1, const u8 *addr2,
|
||||
const u8 *mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
if ((addr1[i] ^ addr2[i]) & mask[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_addr_to_u64 - Convert an Ethernet address into a u64 value.
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Return a u64 value of the address
|
||||
*/
|
||||
static inline u64 ether_addr_to_u64(const u8 *addr)
|
||||
{
|
||||
u64 u = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
u = u << 8 | addr[i];
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
* u64_to_ether_addr - Convert a u64 to an Ethernet address.
|
||||
* @u: u64 to convert to an Ethernet MAC address
|
||||
* @addr: Pointer to a six-byte array to contain the Ethernet address
|
||||
*/
|
||||
static inline void u64_to_ether_addr(u64 u, u8 *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = ETH_ALEN - 1; i >= 0; i--) {
|
||||
addr[i] = u & 0xff;
|
||||
u = u >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_addr_dec - Decrement the given MAC address
|
||||
*
|
||||
* @addr: Pointer to a six-byte array containing Ethernet address to decrement
|
||||
*/
|
||||
static inline void eth_addr_dec(u8 *addr)
|
||||
{
|
||||
u64 u = ether_addr_to_u64(addr);
|
||||
|
||||
u--;
|
||||
u64_to_ether_addr(u, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_addr_inc() - Increment the given MAC address.
|
||||
* @addr: Pointer to a six-byte array containing Ethernet address to increment.
|
||||
*/
|
||||
static inline void eth_addr_inc(u8 *addr)
|
||||
{
|
||||
u64 u = ether_addr_to_u64(addr);
|
||||
|
||||
u++;
|
||||
u64_to_ether_addr(u, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_etherdev_addr - Tell if given Ethernet address belongs to the device.
|
||||
* @dev: Pointer to a device structure
|
||||
* @addr: Pointer to a six-byte array containing the Ethernet address
|
||||
*
|
||||
* Compare passed address with all addresses of the device. Return true if the
|
||||
* address if one of the device addresses.
|
||||
*
|
||||
* Note that this function calls ether_addr_equal_64bits() so take care of
|
||||
* the right padding.
|
||||
*/
|
||||
static inline bool is_etherdev_addr(const struct net_device *dev,
|
||||
const u8 addr[6 + 2])
|
||||
{
|
||||
struct netdev_hw_addr *ha;
|
||||
bool res = false;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_dev_addr(dev, ha) {
|
||||
res = ether_addr_equal_64bits(addr, ha->addr);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return res;
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/**
|
||||
* compare_ether_header - Compare two Ethernet headers
|
||||
* @a: Pointer to Ethernet header
|
||||
* @b: Pointer to Ethernet header
|
||||
*
|
||||
* Compare two Ethernet headers, returns 0 if equal.
|
||||
* This assumes that the network header (i.e., IP header) is 4-byte
|
||||
* aligned OR the platform can handle unaligned access. This is the
|
||||
* case for all packets coming into netif_receive_skb or similar
|
||||
* entry points.
|
||||
*/
|
||||
|
||||
static inline unsigned long compare_ether_header(const void *a, const void *b)
|
||||
{
|
||||
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
|
||||
unsigned long fold;
|
||||
|
||||
/*
|
||||
* We want to compare 14 bytes:
|
||||
* [a0 ... a13] ^ [b0 ... b13]
|
||||
* Use two long XOR, ORed together, with an overlap of two bytes.
|
||||
* [a0 a1 a2 a3 a4 a5 a6 a7 ] ^ [b0 b1 b2 b3 b4 b5 b6 b7 ] |
|
||||
* [a6 a7 a8 a9 a10 a11 a12 a13] ^ [b6 b7 b8 b9 b10 b11 b12 b13]
|
||||
* This means the [a6 a7] ^ [b6 b7] part is done two times.
|
||||
*/
|
||||
fold = *(unsigned long *)a ^ *(unsigned long *)b;
|
||||
fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
|
||||
return fold;
|
||||
#else
|
||||
u32 *a32 = (u32 *)((u8 *)a + 2);
|
||||
u32 *b32 = (u32 *)((u8 *)b + 2);
|
||||
|
||||
return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) |
|
||||
(a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
|
||||
* @skb: Buffer to pad
|
||||
*
|
||||
* An Ethernet frame should have a minimum size of 60 bytes. This function
|
||||
* takes short frames and pads them with zeros up to the 60 byte limit.
|
||||
*/
|
||||
static inline int eth_skb_pad(struct sk_buff *skb)
|
||||
{
|
||||
return skb_put_padto(skb, ETH_ZLEN);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_ETHERDEVICE_H */
|
||||
387
data/linux-small/include/linux/ipv6.h
Normal file
387
data/linux-small/include/linux/ipv6.h
Normal file
@@ -0,0 +1,387 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _IPV6_H
|
||||
#define _IPV6_H
|
||||
|
||||
#include <uapi/linux/ipv6.h>
|
||||
|
||||
#define ipv6_optlen(p) (((p)->hdrlen+1) << 3)
|
||||
#define ipv6_authlen(p) (((p)->hdrlen+2) << 2)
|
||||
/*
|
||||
* This structure contains configuration options per IPv6 link.
|
||||
*/
|
||||
struct ipv6_devconf {
|
||||
__s32 forwarding;
|
||||
__s32 hop_limit;
|
||||
__s32 mtu6;
|
||||
__s32 accept_ra;
|
||||
__s32 accept_redirects;
|
||||
__s32 autoconf;
|
||||
__s32 dad_transmits;
|
||||
__s32 rtr_solicits;
|
||||
__s32 rtr_solicit_interval;
|
||||
__s32 rtr_solicit_max_interval;
|
||||
__s32 rtr_solicit_delay;
|
||||
__s32 force_mld_version;
|
||||
__s32 mldv1_unsolicited_report_interval;
|
||||
__s32 mldv2_unsolicited_report_interval;
|
||||
__s32 use_tempaddr;
|
||||
__s32 temp_valid_lft;
|
||||
__s32 temp_prefered_lft;
|
||||
__s32 regen_max_retry;
|
||||
__s32 max_desync_factor;
|
||||
__s32 max_addresses;
|
||||
__s32 accept_ra_defrtr;
|
||||
__u32 ra_defrtr_metric;
|
||||
__s32 accept_ra_min_hop_limit;
|
||||
__s32 accept_ra_pinfo;
|
||||
__s32 ignore_routes_with_linkdown;
|
||||
#ifdef CONFIG_IPV6_ROUTER_PREF
|
||||
__s32 accept_ra_rtr_pref;
|
||||
__s32 rtr_probe_interval;
|
||||
#ifdef CONFIG_IPV6_ROUTE_INFO
|
||||
__s32 accept_ra_rt_info_min_plen;
|
||||
__s32 accept_ra_rt_info_max_plen;
|
||||
#endif
|
||||
#endif
|
||||
__s32 proxy_ndp;
|
||||
__s32 accept_source_route;
|
||||
__s32 accept_ra_from_local;
|
||||
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
||||
__s32 optimistic_dad;
|
||||
__s32 use_optimistic;
|
||||
#endif
|
||||
#ifdef CONFIG_IPV6_MROUTE
|
||||
__s32 mc_forwarding;
|
||||
#endif
|
||||
__s32 disable_ipv6;
|
||||
__s32 drop_unicast_in_l2_multicast;
|
||||
__s32 accept_dad;
|
||||
__s32 force_tllao;
|
||||
__s32 ndisc_notify;
|
||||
__s32 suppress_frag_ndisc;
|
||||
__s32 accept_ra_mtu;
|
||||
__s32 drop_unsolicited_na;
|
||||
struct ipv6_stable_secret {
|
||||
bool initialized;
|
||||
struct in6_addr secret;
|
||||
} stable_secret;
|
||||
__s32 use_oif_addrs_only;
|
||||
__s32 keep_addr_on_down;
|
||||
__s32 seg6_enabled;
|
||||
#ifdef CONFIG_IPV6_SEG6_HMAC
|
||||
__s32 seg6_require_hmac;
|
||||
#endif
|
||||
__u32 enhanced_dad;
|
||||
__u32 addr_gen_mode;
|
||||
__s32 disable_policy;
|
||||
__s32 ndisc_tclass;
|
||||
__s32 rpl_seg_enabled;
|
||||
__u32 ioam6_id;
|
||||
__u32 ioam6_id_wide;
|
||||
__u8 ioam6_enabled;
|
||||
|
||||
struct ctl_table_header *sysctl_header;
|
||||
};
|
||||
|
||||
struct ipv6_params {
|
||||
__s32 disable_ipv6;
|
||||
__s32 autoconf;
|
||||
};
|
||||
extern struct ipv6_params ipv6_defaults;
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
|
||||
#include <net/inet_sock.h>
|
||||
|
||||
static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
return (struct ipv6hdr *)skb_network_header(skb);
|
||||
}
|
||||
|
||||
static inline struct ipv6hdr *inner_ipv6_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
return (struct ipv6hdr *)skb_inner_network_header(skb);
|
||||
}
|
||||
|
||||
static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
return (struct ipv6hdr *)skb_transport_header(skb);
|
||||
}
|
||||
|
||||
static inline unsigned int ipv6_transport_len(const struct sk_buff *skb)
|
||||
{
|
||||
return ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr) -
|
||||
skb_network_header_len(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
This structure contains results of exthdrs parsing
|
||||
as offsets from skb->nh.
|
||||
*/
|
||||
|
||||
struct inet6_skb_parm {
|
||||
int iif;
|
||||
__be16 ra;
|
||||
__u16 dst0;
|
||||
__u16 srcrt;
|
||||
__u16 dst1;
|
||||
__u16 lastopt;
|
||||
__u16 nhoff;
|
||||
__u16 flags;
|
||||
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
|
||||
__u16 dsthao;
|
||||
#endif
|
||||
__u16 frag_max_size;
|
||||
|
||||
#define IP6SKB_XFRM_TRANSFORMED 1
|
||||
#define IP6SKB_FORWARDED 2
|
||||
#define IP6SKB_REROUTED 4
|
||||
#define IP6SKB_ROUTERALERT 8
|
||||
#define IP6SKB_FRAGMENTED 16
|
||||
#define IP6SKB_HOPBYHOP 32
|
||||
#define IP6SKB_L3SLAVE 64
|
||||
#define IP6SKB_JUMBOGRAM 128
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_L3_MASTER_DEV)
|
||||
static inline bool ipv6_l3mdev_skb(__u16 flags)
|
||||
{
|
||||
return flags & IP6SKB_L3SLAVE;
|
||||
}
|
||||
#else
|
||||
static inline bool ipv6_l3mdev_skb(__u16 flags)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
|
||||
#define IP6CBMTU(skb) ((struct ip6_mtuinfo *)((skb)->cb))
|
||||
|
||||
static inline int inet6_iif(const struct sk_buff *skb)
|
||||
{
|
||||
bool l3_slave = ipv6_l3mdev_skb(IP6CB(skb)->flags);
|
||||
|
||||
return l3_slave ? skb->skb_iif : IP6CB(skb)->iif;
|
||||
}
|
||||
|
||||
static inline bool inet6_is_jumbogram(const struct sk_buff *skb)
|
||||
{
|
||||
return !!(IP6CB(skb)->flags & IP6SKB_JUMBOGRAM);
|
||||
}
|
||||
|
||||
/* can not be used in TCP layer after tcp_v6_fill_cb */
|
||||
static inline int inet6_sdif(const struct sk_buff *skb)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
|
||||
if (skb && ipv6_l3mdev_skb(IP6CB(skb)->flags))
|
||||
return IP6CB(skb)->iif;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tcp6_request_sock {
|
||||
struct tcp_request_sock tcp6rsk_tcp;
|
||||
};
|
||||
|
||||
struct ipv6_mc_socklist;
|
||||
struct ipv6_ac_socklist;
|
||||
struct ipv6_fl_socklist;
|
||||
|
||||
struct inet6_cork {
|
||||
struct ipv6_txoptions *opt;
|
||||
u8 hop_limit;
|
||||
u8 tclass;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipv6_pinfo - ipv6 private area
|
||||
*
|
||||
* In the struct sock hierarchy (tcp6_sock, upd6_sock, etc)
|
||||
* this _must_ be the last member, so that inet6_sk_generic
|
||||
* is able to calculate its offset from the base struct sock
|
||||
* by using the struct proto->slab_obj_size member. -acme
|
||||
*/
|
||||
struct ipv6_pinfo {
|
||||
struct in6_addr saddr;
|
||||
struct in6_pktinfo sticky_pktinfo;
|
||||
const struct in6_addr *daddr_cache;
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
const struct in6_addr *saddr_cache;
|
||||
#endif
|
||||
|
||||
__be32 flow_label;
|
||||
__u32 frag_size;
|
||||
|
||||
/*
|
||||
* Packed in 16bits.
|
||||
* Omit one shift by putting the signed field at MSB.
|
||||
*/
|
||||
#if defined(__BIG_ENDIAN_BITFIELD)
|
||||
__s16 hop_limit:9;
|
||||
__u16 __unused_1:7;
|
||||
#else
|
||||
__u16 __unused_1:7;
|
||||
__s16 hop_limit:9;
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN_BITFIELD)
|
||||
/* Packed in 16bits. */
|
||||
__s16 mcast_hops:9;
|
||||
__u16 __unused_2:6,
|
||||
mc_loop:1;
|
||||
#else
|
||||
__u16 mc_loop:1,
|
||||
__unused_2:6;
|
||||
__s16 mcast_hops:9;
|
||||
#endif
|
||||
int ucast_oif;
|
||||
int mcast_oif;
|
||||
|
||||
/* pktoption flags */
|
||||
union {
|
||||
struct {
|
||||
__u16 srcrt:1,
|
||||
osrcrt:1,
|
||||
rxinfo:1,
|
||||
rxoinfo:1,
|
||||
rxhlim:1,
|
||||
rxohlim:1,
|
||||
hopopts:1,
|
||||
ohopopts:1,
|
||||
dstopts:1,
|
||||
odstopts:1,
|
||||
rxflow:1,
|
||||
rxtclass:1,
|
||||
rxpmtu:1,
|
||||
rxorigdstaddr:1,
|
||||
recvfragsize:1;
|
||||
/* 1 bits hole */
|
||||
} bits;
|
||||
__u16 all;
|
||||
} rxopt;
|
||||
|
||||
/* sockopt flags */
|
||||
__u16 recverr:1,
|
||||
sndflow:1,
|
||||
repflow:1,
|
||||
pmtudisc:3,
|
||||
padding:1, /* 1 bit hole */
|
||||
srcprefs:3, /* 001: prefer temporary address
|
||||
* 010: prefer public address
|
||||
* 100: prefer care-of address
|
||||
*/
|
||||
dontfrag:1,
|
||||
autoflowlabel:1,
|
||||
autoflowlabel_set:1,
|
||||
mc_all:1,
|
||||
recverr_rfc4884:1,
|
||||
rtalert_isolate:1;
|
||||
__u8 min_hopcount;
|
||||
__u8 tclass;
|
||||
__be32 rcv_flowinfo;
|
||||
|
||||
__u32 dst_cookie;
|
||||
__u32 rx_dst_cookie;
|
||||
|
||||
struct ipv6_mc_socklist __rcu *ipv6_mc_list;
|
||||
struct ipv6_ac_socklist *ipv6_ac_list;
|
||||
struct ipv6_fl_socklist __rcu *ipv6_fl_list;
|
||||
|
||||
struct ipv6_txoptions __rcu *opt;
|
||||
struct sk_buff *pktoptions;
|
||||
struct sk_buff *rxpmtu;
|
||||
struct inet6_cork cork;
|
||||
};
|
||||
|
||||
/* WARNING: don't change the layout of the members in {raw,udp,tcp}6_sock! */
|
||||
struct raw6_sock {
|
||||
/* inet_sock has to be the first member of raw6_sock */
|
||||
struct inet_sock inet;
|
||||
__u32 checksum; /* perform checksum */
|
||||
__u32 offset; /* checksum offset */
|
||||
struct icmp6_filter filter;
|
||||
__u32 ip6mr_table;
|
||||
/* ipv6_pinfo has to be the last member of raw6_sock, see inet6_sk_generic */
|
||||
struct ipv6_pinfo inet6;
|
||||
};
|
||||
|
||||
struct udp6_sock {
|
||||
struct udp_sock udp;
|
||||
/* ipv6_pinfo has to be the last member of udp6_sock, see inet6_sk_generic */
|
||||
struct ipv6_pinfo inet6;
|
||||
};
|
||||
|
||||
struct tcp6_sock {
|
||||
struct tcp_sock tcp;
|
||||
/* ipv6_pinfo has to be the last member of tcp6_sock, see inet6_sk_generic */
|
||||
struct ipv6_pinfo inet6;
|
||||
};
|
||||
|
||||
extern int inet6_sk_rebuild_header(struct sock *sk);
|
||||
|
||||
struct tcp6_timewait_sock {
|
||||
struct tcp_timewait_sock tcp6tw_tcp;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
bool ipv6_mod_enabled(void);
|
||||
|
||||
static inline struct ipv6_pinfo *inet6_sk(const struct sock *__sk)
|
||||
{
|
||||
return sk_fullsock(__sk) ? inet_sk(__sk)->pinet6 : NULL;
|
||||
}
|
||||
|
||||
static inline struct raw6_sock *raw6_sk(const struct sock *sk)
|
||||
{
|
||||
return (struct raw6_sock *)sk;
|
||||
}
|
||||
|
||||
#define __ipv6_only_sock(sk) (sk->sk_ipv6only)
|
||||
#define ipv6_only_sock(sk) (__ipv6_only_sock(sk))
|
||||
#define ipv6_sk_rxinfo(sk) ((sk)->sk_family == PF_INET6 && \
|
||||
inet6_sk(sk)->rxopt.bits.rxinfo)
|
||||
|
||||
static inline const struct in6_addr *inet6_rcv_saddr(const struct sock *sk)
|
||||
{
|
||||
if (sk->sk_family == AF_INET6)
|
||||
return &sk->sk_v6_rcv_saddr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int inet_v6_ipv6only(const struct sock *sk)
|
||||
{
|
||||
/* ipv6only field is at same position for timewait and other sockets */
|
||||
return ipv6_only_sock(sk);
|
||||
}
|
||||
#else
|
||||
#define __ipv6_only_sock(sk) 0
|
||||
#define ipv6_only_sock(sk) 0
|
||||
#define ipv6_sk_rxinfo(sk) 0
|
||||
|
||||
static inline bool ipv6_mod_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct inet6_request_sock *
|
||||
inet6_rsk(const struct request_sock *rsk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct raw6_sock *raw6_sk(const struct sock *sk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define inet6_rcv_saddr(__sk) NULL
|
||||
#define tcp_twsk_ipv6only(__sk) 0
|
||||
#define inet_v6_ipv6only(__sk) 0
|
||||
#endif /* IS_ENABLED(CONFIG_IPV6) */
|
||||
#endif /* _IPV6_H */
|
||||
84
data/linux-small/include/linux/pagevec.h
Normal file
84
data/linux-small/include/linux/pagevec.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* include/linux/pagevec.h
|
||||
*
|
||||
* In many places it is efficient to batch an operation up against multiple
|
||||
* pages. A pagevec is a multipage container which is used for that.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_PAGEVEC_H
|
||||
#define _LINUX_PAGEVEC_H
|
||||
|
||||
#include <linux/xarray.h>
|
||||
|
||||
/* 15 pointers + header align the pagevec structure to a power of two */
|
||||
#define PAGEVEC_SIZE 15
|
||||
|
||||
struct page;
|
||||
struct address_space;
|
||||
|
||||
struct pagevec {
|
||||
unsigned char nr;
|
||||
bool percpu_pvec_drained;
|
||||
struct page *pages[PAGEVEC_SIZE];
|
||||
};
|
||||
|
||||
void __pagevec_release(struct pagevec *pvec);
|
||||
void __pagevec_lru_add(struct pagevec *pvec);
|
||||
void pagevec_remove_exceptionals(struct pagevec *pvec);
|
||||
unsigned pagevec_lookup_range(struct pagevec *pvec,
|
||||
struct address_space *mapping,
|
||||
pgoff_t *start, pgoff_t end);
|
||||
static inline unsigned pagevec_lookup(struct pagevec *pvec,
|
||||
struct address_space *mapping,
|
||||
pgoff_t *start)
|
||||
{
|
||||
return pagevec_lookup_range(pvec, mapping, start, (pgoff_t)-1);
|
||||
}
|
||||
|
||||
unsigned pagevec_lookup_range_tag(struct pagevec *pvec,
|
||||
struct address_space *mapping, pgoff_t *index, pgoff_t end,
|
||||
xa_mark_t tag);
|
||||
static inline unsigned pagevec_lookup_tag(struct pagevec *pvec,
|
||||
struct address_space *mapping, pgoff_t *index, xa_mark_t tag)
|
||||
{
|
||||
return pagevec_lookup_range_tag(pvec, mapping, index, (pgoff_t)-1, tag);
|
||||
}
|
||||
|
||||
static inline void pagevec_init(struct pagevec *pvec)
|
||||
{
|
||||
pvec->nr = 0;
|
||||
pvec->percpu_pvec_drained = false;
|
||||
}
|
||||
|
||||
static inline void pagevec_reinit(struct pagevec *pvec)
|
||||
{
|
||||
pvec->nr = 0;
|
||||
}
|
||||
|
||||
static inline unsigned pagevec_count(struct pagevec *pvec)
|
||||
{
|
||||
return pvec->nr;
|
||||
}
|
||||
|
||||
static inline unsigned pagevec_space(struct pagevec *pvec)
|
||||
{
|
||||
return PAGEVEC_SIZE - pvec->nr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a page to a pagevec. Returns the number of slots still available.
|
||||
*/
|
||||
static inline unsigned pagevec_add(struct pagevec *pvec, struct page *page)
|
||||
{
|
||||
pvec->pages[pvec->nr++] = page;
|
||||
return pagevec_space(pvec);
|
||||
}
|
||||
|
||||
static inline void pagevec_release(struct pagevec *pvec)
|
||||
{
|
||||
if (pagevec_count(pvec))
|
||||
__pagevec_release(pvec);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_PAGEVEC_H */
|
||||
8313
data/linux-small/include/net/cfg80211.h
Normal file
8313
data/linux-small/include/net/cfg80211.h
Normal file
File diff suppressed because it is too large
Load Diff
814
data/linux-small/lib/zlib_inflate/inflate.c
Normal file
814
data/linux-small/lib/zlib_inflate/inflate.c
Normal file
@@ -0,0 +1,814 @@
|
||||
/* inflate.c -- zlib decompression
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Based on zlib 1.2.3 but modified for the Linux Kernel by
|
||||
* Richard Purdie <richard@openedhand.com>
|
||||
*
|
||||
* Changes mainly for static instead of dynamic memory allocation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/zutil.h>
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
#include "infutil.h"
|
||||
|
||||
/* architecture-specific bits */
|
||||
#ifdef CONFIG_ZLIB_DFLTCC
|
||||
# include "../zlib_dfltcc/dfltcc.h"
|
||||
#else
|
||||
#define INFLATE_RESET_HOOK(strm) do {} while (0)
|
||||
#define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
|
||||
#define INFLATE_NEED_UPDATEWINDOW(strm) 1
|
||||
#define INFLATE_NEED_CHECKSUM(strm) 1
|
||||
#endif
|
||||
|
||||
int zlib_inflate_workspacesize(void)
|
||||
{
|
||||
return sizeof(struct inflate_workspace);
|
||||
}
|
||||
|
||||
int zlib_inflateReset(z_streamp strm)
|
||||
{
|
||||
struct inflate_state *state;
|
||||
|
||||
if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state *)strm->state;
|
||||
strm->total_in = strm->total_out = state->total = 0;
|
||||
strm->msg = NULL;
|
||||
strm->adler = 1; /* to support ill-conceived Java test suite */
|
||||
state->mode = HEAD;
|
||||
state->last = 0;
|
||||
state->havedict = 0;
|
||||
state->dmax = 32768U;
|
||||
state->hold = 0;
|
||||
state->bits = 0;
|
||||
state->lencode = state->distcode = state->next = state->codes;
|
||||
|
||||
/* Initialise Window */
|
||||
state->wsize = 1U << state->wbits;
|
||||
state->write = 0;
|
||||
state->whave = 0;
|
||||
|
||||
INFLATE_RESET_HOOK(strm);
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int zlib_inflateInit2(z_streamp strm, int windowBits)
|
||||
{
|
||||
struct inflate_state *state;
|
||||
|
||||
if (strm == NULL) return Z_STREAM_ERROR;
|
||||
strm->msg = NULL; /* in case we return an error */
|
||||
|
||||
state = &WS(strm)->inflate_state;
|
||||
strm->state = (struct internal_state *)state;
|
||||
|
||||
if (windowBits < 0) {
|
||||
state->wrap = 0;
|
||||
windowBits = -windowBits;
|
||||
}
|
||||
else {
|
||||
state->wrap = (windowBits >> 4) + 1;
|
||||
}
|
||||
if (windowBits < 8 || windowBits > 15) {
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
state->wbits = (unsigned)windowBits;
|
||||
#ifdef CONFIG_ZLIB_DFLTCC
|
||||
/*
|
||||
* DFLTCC requires the window to be page aligned.
|
||||
* Thus, we overallocate and take the aligned portion of the buffer.
|
||||
*/
|
||||
state->window = PTR_ALIGN(&WS(strm)->working_window[0], PAGE_SIZE);
|
||||
#else
|
||||
state->window = &WS(strm)->working_window[0];
|
||||
#endif
|
||||
|
||||
return zlib_inflateReset(strm);
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. This returns fixed tables from inffixed.h.
|
||||
*/
|
||||
static void zlib_fixedtables(struct inflate_state *state)
|
||||
{
|
||||
# include "inffixed.h"
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Update the window with the last wsize (normally 32K) bytes written before
|
||||
returning. This is only called when a window is already in use, or when
|
||||
output has been written during this inflate call, but the end of the deflate
|
||||
stream has not been reached yet. It is also called to window dictionary data
|
||||
when a dictionary is loaded.
|
||||
|
||||
Providing output buffers larger than 32K to inflate() should provide a speed
|
||||
advantage, since only the last 32K of output is copied to the sliding window
|
||||
upon return from inflate(), and since all distances after the first 32K of
|
||||
output will fall in the output data, making match copies simpler and faster.
|
||||
The advantage may be dependent on the size of the processor's data caches.
|
||||
*/
|
||||
static void zlib_updatewindow(z_streamp strm, unsigned out)
|
||||
{
|
||||
struct inflate_state *state;
|
||||
unsigned copy, dist;
|
||||
|
||||
state = (struct inflate_state *)strm->state;
|
||||
|
||||
/* copy state->wsize or less output bytes into the circular window */
|
||||
copy = out - strm->avail_out;
|
||||
if (copy >= state->wsize) {
|
||||
memcpy(state->window, strm->next_out - state->wsize, state->wsize);
|
||||
state->write = 0;
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
else {
|
||||
dist = state->wsize - state->write;
|
||||
if (dist > copy) dist = copy;
|
||||
memcpy(state->window + state->write, strm->next_out - copy, dist);
|
||||
copy -= dist;
|
||||
if (copy) {
|
||||
memcpy(state->window, strm->next_out - copy, copy);
|
||||
state->write = copy;
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
else {
|
||||
state->write += dist;
|
||||
if (state->write == state->wsize) state->write = 0;
|
||||
if (state->whave < state->wsize) state->whave += dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* At the end of a Deflate-compressed PPP packet, we expect to have seen
|
||||
* a `stored' block type value but not the (zero) length bytes.
|
||||
*/
|
||||
/*
|
||||
Returns true if inflate is currently at the end of a block generated by
|
||||
Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
|
||||
implementation to provide an additional safety check. PPP uses
|
||||
Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
|
||||
block. When decompressing, PPP checks that at the end of input packet,
|
||||
inflate is waiting for these length bytes.
|
||||
*/
|
||||
static int zlib_inflateSyncPacket(z_streamp strm)
|
||||
{
|
||||
struct inflate_state *state;
|
||||
|
||||
if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state *)strm->state;
|
||||
|
||||
if (state->mode == STORED && state->bits == 0) {
|
||||
state->mode = TYPE;
|
||||
return Z_OK;
|
||||
}
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* Macros for inflate(): */
|
||||
|
||||
/* check function to use adler32() for zlib or crc32() for gzip */
|
||||
#define UPDATE(check, buf, len) zlib_adler32(check, buf, len)
|
||||
|
||||
/* Load registers with state in inflate() for speed */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Restore state from registers in inflate() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflate()
|
||||
if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
if (have == 0) goto inf_leave; \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflate(). */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
inflate() uses a state machine to process as much input data and generate as
|
||||
much output data as possible before returning. The state machine is
|
||||
structured roughly as follows:
|
||||
|
||||
for (;;) switch (state) {
|
||||
...
|
||||
case STATEn:
|
||||
if (not enough input data or output space to make progress)
|
||||
return;
|
||||
... make progress ...
|
||||
state = STATEm;
|
||||
break;
|
||||
...
|
||||
}
|
||||
|
||||
so when inflate() is called again, the same case is attempted again, and
|
||||
if the appropriate resources are provided, the machine proceeds to the
|
||||
next state. The NEEDBITS() macro is usually the way the state evaluates
|
||||
whether it can proceed or should return. NEEDBITS() does the return if
|
||||
the requested bits are not available. The typical use of the BITS macros
|
||||
is:
|
||||
|
||||
NEEDBITS(n);
|
||||
... do something with BITS(n) ...
|
||||
DROPBITS(n);
|
||||
|
||||
where NEEDBITS(n) either returns from inflate() if there isn't enough
|
||||
input left to load n bits into the accumulator, or it continues. BITS(n)
|
||||
gives the low n bits in the accumulator. When done, DROPBITS(n) drops
|
||||
the low n bits off the accumulator. INITBITS() clears the accumulator
|
||||
and sets the number of available bits to zero. BYTEBITS() discards just
|
||||
enough bits to put the accumulator on a byte boundary. After BYTEBITS()
|
||||
and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
|
||||
|
||||
NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
|
||||
if there is no input available. The decoding of variable length codes uses
|
||||
PULLBYTE() directly in order to pull just enough bytes to decode the next
|
||||
code, and no more.
|
||||
|
||||
Some states loop until they get enough input, making sure that enough
|
||||
state information is maintained to continue the loop where it left off
|
||||
if NEEDBITS() returns in the loop. For example, want, need, and keep
|
||||
would all have to actually be part of the saved state in case NEEDBITS()
|
||||
returns:
|
||||
|
||||
case STATEw:
|
||||
while (want < need) {
|
||||
NEEDBITS(n);
|
||||
keep[want++] = BITS(n);
|
||||
DROPBITS(n);
|
||||
}
|
||||
state = STATEx;
|
||||
case STATEx:
|
||||
|
||||
As shown above, if the next state is also the next case, then the break
|
||||
is omitted.
|
||||
|
||||
A state may also return if there is not enough output space available to
|
||||
complete that state. Those states are copying stored data, writing a
|
||||
literal byte, and copying a matching string.
|
||||
|
||||
When returning, a "goto inf_leave" is used to update the total counters,
|
||||
update the check value, and determine whether any progress has been made
|
||||
during that inflate() call in order to return the proper return code.
|
||||
Progress is defined as a change in either strm->avail_in or strm->avail_out.
|
||||
When there is a window, goto inf_leave will update the window with the last
|
||||
output written. If a goto inf_leave occurs in the middle of decompression
|
||||
and there is no window currently, goto inf_leave will create one and copy
|
||||
output to the window for the next call of inflate().
|
||||
|
||||
In this implementation, the flush parameter of inflate() only affects the
|
||||
return code (per zlib.h). inflate() always writes as much as possible to
|
||||
strm->next_out, given the space available and the provided input--the effect
|
||||
documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
|
||||
the allocation of and copying into a sliding window until necessary, which
|
||||
provides the effect documented in zlib.h for Z_FINISH when the entire input
|
||||
stream available. So the only thing the flush parameter actually does is:
|
||||
when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
|
||||
will return Z_BUF_ERROR if it has not reached the end of the stream.
|
||||
*/
|
||||
|
||||
int zlib_inflate(z_streamp strm, int flush)
|
||||
{
|
||||
struct inflate_state *state;
|
||||
const unsigned char *next; /* next input */
|
||||
unsigned char *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned in, out; /* save starting available input and output */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char *from; /* where to copy match bytes from */
|
||||
code this; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Do not check for strm->next_out == NULL here as ppc zImage
|
||||
inflates to strm->next_out = 0 */
|
||||
|
||||
if (strm == NULL || strm->state == NULL ||
|
||||
(strm->next_in == NULL && strm->avail_in != 0))
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
state = (struct inflate_state *)strm->state;
|
||||
|
||||
if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
|
||||
LOAD();
|
||||
in = have;
|
||||
out = left;
|
||||
ret = Z_OK;
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case HEAD:
|
||||
if (state->wrap == 0) {
|
||||
state->mode = TYPEDO;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(16);
|
||||
if (
|
||||
((BITS(8) << 8) + (hold >> 8)) % 31) {
|
||||
strm->msg = (char *)"incorrect header check";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
if (BITS(4) != Z_DEFLATED) {
|
||||
strm->msg = (char *)"unknown compression method";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
DROPBITS(4);
|
||||
len = BITS(4) + 8;
|
||||
if (len > state->wbits) {
|
||||
strm->msg = (char *)"invalid window size";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->dmax = 1U << len;
|
||||
strm->adler = state->check = zlib_adler32(0L, NULL, 0);
|
||||
state->mode = hold & 0x200 ? DICTID : TYPE;
|
||||
INITBITS();
|
||||
break;
|
||||
case DICTID:
|
||||
NEEDBITS(32);
|
||||
strm->adler = state->check = REVERSE(hold);
|
||||
INITBITS();
|
||||
state->mode = DICT;
|
||||
fallthrough;
|
||||
case DICT:
|
||||
if (state->havedict == 0) {
|
||||
RESTORE();
|
||||
return Z_NEED_DICT;
|
||||
}
|
||||
strm->adler = state->check = zlib_adler32(0L, NULL, 0);
|
||||
state->mode = TYPE;
|
||||
fallthrough;
|
||||
case TYPE:
|
||||
if (flush == Z_BLOCK) goto inf_leave;
|
||||
fallthrough;
|
||||
case TYPEDO:
|
||||
INFLATE_TYPEDO_HOOK(strm, flush);
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = CHECK;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
zlib_fixedtables(state);
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
case STORED:
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
INITBITS();
|
||||
state->mode = COPY;
|
||||
fallthrough;
|
||||
case COPY:
|
||||
copy = state->length;
|
||||
if (copy) {
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
if (copy == 0) goto inf_leave;
|
||||
memcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
break;
|
||||
}
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
case TABLE:
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
state->have = 0;
|
||||
state->mode = LENLENS;
|
||||
fallthrough;
|
||||
case LENLENS:
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = zlib_inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->have = 0;
|
||||
state->mode = CODELENS;
|
||||
fallthrough;
|
||||
case CODELENS:
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
this = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (this.val < 16) {
|
||||
NEEDBITS(this.bits);
|
||||
DROPBITS(this.bits);
|
||||
state->lens[state->have++] = this.val;
|
||||
}
|
||||
else {
|
||||
if (this.val == 16) {
|
||||
NEEDBITS(this.bits + 2);
|
||||
DROPBITS(this.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = state->lens[state->have - 1];
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (this.val == 17) {
|
||||
NEEDBITS(this.bits + 3);
|
||||
DROPBITS(this.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(this.bits + 7);
|
||||
DROPBITS(this.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* build code tables */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = zlib_inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = zlib_inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->mode = LEN;
|
||||
fallthrough;
|
||||
case LEN:
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
inflate_fast(strm, out);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
for (;;) {
|
||||
this = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (this.op && (this.op & 0xf0) == 0) {
|
||||
last = this;
|
||||
for (;;) {
|
||||
this = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(this.bits);
|
||||
state->length = (unsigned)this.val;
|
||||
if ((int)(this.op) == 0) {
|
||||
state->mode = LIT;
|
||||
break;
|
||||
}
|
||||
if (this.op & 32) {
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
if (this.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->extra = (unsigned)(this.op) & 15;
|
||||
state->mode = LENEXT;
|
||||
fallthrough;
|
||||
case LENEXT:
|
||||
if (state->extra) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
state->mode = DIST;
|
||||
fallthrough;
|
||||
case DIST:
|
||||
for (;;) {
|
||||
this = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((this.op & 0xf0) == 0) {
|
||||
last = this;
|
||||
for (;;) {
|
||||
this = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(this.bits);
|
||||
if (this.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)this.val;
|
||||
state->extra = (unsigned)(this.op) & 15;
|
||||
state->mode = DISTEXT;
|
||||
fallthrough;
|
||||
case DISTEXT:
|
||||
if (state->extra) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
#ifdef INFLATE_STRICT
|
||||
if (state->offset > state->dmax) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (state->offset > state->whave + out - left) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->mode = MATCH;
|
||||
fallthrough;
|
||||
case MATCH:
|
||||
if (left == 0) goto inf_leave;
|
||||
copy = out - left;
|
||||
if (state->offset > copy) { /* copy from window */
|
||||
copy = state->offset - copy;
|
||||
if (copy > state->write) {
|
||||
copy -= state->write;
|
||||
from = state->window + (state->wsize - copy);
|
||||
}
|
||||
else
|
||||
from = state->window + (state->write - copy);
|
||||
if (copy > state->length) copy = state->length;
|
||||
}
|
||||
else { /* copy from output */
|
||||
from = put - state->offset;
|
||||
copy = state->length;
|
||||
}
|
||||
if (copy > left) copy = left;
|
||||
left -= copy;
|
||||
state->length -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
if (state->length == 0) state->mode = LEN;
|
||||
break;
|
||||
case LIT:
|
||||
if (left == 0) goto inf_leave;
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
case CHECK:
|
||||
if (state->wrap) {
|
||||
NEEDBITS(32);
|
||||
out -= left;
|
||||
strm->total_out += out;
|
||||
state->total += out;
|
||||
if (INFLATE_NEED_CHECKSUM(strm) && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, put - out, out);
|
||||
out = left;
|
||||
if ((
|
||||
REVERSE(hold)) != state->check) {
|
||||
strm->msg = (char *)"incorrect data check";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
INITBITS();
|
||||
}
|
||||
state->mode = DONE;
|
||||
fallthrough;
|
||||
case DONE:
|
||||
ret = Z_STREAM_END;
|
||||
goto inf_leave;
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
case MEM:
|
||||
return Z_MEM_ERROR;
|
||||
case SYNC:
|
||||
default:
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
Return from inflate(), updating the total counts and the check value.
|
||||
If there was no progress during the inflate() call, return a buffer
|
||||
error. Call zlib_updatewindow() to create and/or update the window state.
|
||||
*/
|
||||
inf_leave:
|
||||
RESTORE();
|
||||
if (INFLATE_NEED_UPDATEWINDOW(strm) &&
|
||||
(state->wsize || (state->mode < CHECK && out != strm->avail_out)))
|
||||
zlib_updatewindow(strm, out);
|
||||
|
||||
in -= strm->avail_in;
|
||||
out -= strm->avail_out;
|
||||
strm->total_in += in;
|
||||
strm->total_out += out;
|
||||
state->total += out;
|
||||
if (INFLATE_NEED_CHECKSUM(strm) && state->wrap && out)
|
||||
strm->adler = state->check =
|
||||
UPDATE(state->check, strm->next_out - out, out);
|
||||
|
||||
strm->data_type = state->bits + (state->last ? 64 : 0) +
|
||||
(state->mode == TYPE ? 128 : 0);
|
||||
|
||||
if (flush == Z_PACKET_FLUSH && ret == Z_OK &&
|
||||
strm->avail_out != 0 && strm->avail_in == 0)
|
||||
return zlib_inflateSyncPacket(strm);
|
||||
|
||||
if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
|
||||
ret = Z_BUF_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int zlib_inflateEnd(z_streamp strm)
|
||||
{
|
||||
if (strm == NULL || strm->state == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This subroutine adds the data at next_in/avail_in to the output history
|
||||
* without performing any output. The output buffer must be "caught up";
|
||||
* i.e. no pending output but this should always be the case. The state must
|
||||
* be waiting on the start of a block (i.e. mode == TYPE or HEAD). On exit,
|
||||
* the output will also be caught up, and the checksum will have been updated
|
||||
* if need be.
|
||||
*/
|
||||
int zlib_inflateIncomp(z_stream *z)
|
||||
{
|
||||
struct inflate_state *state = (struct inflate_state *)z->state;
|
||||
Byte *saved_no = z->next_out;
|
||||
uInt saved_ao = z->avail_out;
|
||||
|
||||
if (state->mode != TYPE && state->mode != HEAD)
|
||||
return Z_DATA_ERROR;
|
||||
|
||||
/* Setup some variables to allow misuse of updateWindow */
|
||||
z->avail_out = 0;
|
||||
z->next_out = (unsigned char*)z->next_in + z->avail_in;
|
||||
|
||||
zlib_updatewindow(z, z->avail_in);
|
||||
|
||||
/* Restore saved variables */
|
||||
z->avail_out = saved_ao;
|
||||
z->next_out = saved_no;
|
||||
|
||||
z->adler = state->check =
|
||||
UPDATE(state->check, z->next_in, z->avail_in);
|
||||
|
||||
z->total_out += z->avail_in;
|
||||
z->total_in += z->avail_in;
|
||||
z->next_in += z->avail_in;
|
||||
state->total += z->avail_in;
|
||||
z->avail_in = 0;
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user