Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

385
include/net/6lowpan.h Normal file
View file

@ -0,0 +1,385 @@
/*
* Copyright 2011, Siemens AG
* written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
/*
* Based on patches from Jon Smirl <jonsmirl@gmail.com>
* Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
*
* 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.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Jon's code is based on 6lowpan implementation for Contiki which is:
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __6LOWPAN_H__
#define __6LOWPAN_H__
#include <net/ipv6.h>
#include <net/net_namespace.h>
#define UIP_802154_SHORTADDR_LEN 2 /* compressed ipv6 address length */
#define UIP_IPH_LEN 40 /* ipv6 fixed header size */
#define UIP_PROTO_UDP 17 /* ipv6 next header value for UDP */
#define UIP_FRAGH_LEN 8 /* ipv6 fragment header size */
/*
* ipv6 address based on mac
* second bit-flip (Universe/Local) is done according RFC2464
*/
#define is_addr_mac_addr_based(a, m) \
((((a)->s6_addr[8]) == (((m)[0]) ^ 0x02)) && \
(((a)->s6_addr[9]) == (m)[1]) && \
(((a)->s6_addr[10]) == (m)[2]) && \
(((a)->s6_addr[11]) == (m)[3]) && \
(((a)->s6_addr[12]) == (m)[4]) && \
(((a)->s6_addr[13]) == (m)[5]) && \
(((a)->s6_addr[14]) == (m)[6]) && \
(((a)->s6_addr[15]) == (m)[7]))
/*
* check whether we can compress the IID to 16 bits,
* it's possible for unicast adresses with first 49 bits are zero only.
*/
#define lowpan_is_iid_16_bit_compressable(a) \
((((a)->s6_addr16[4]) == 0) && \
(((a)->s6_addr[10]) == 0) && \
(((a)->s6_addr[11]) == 0xff) && \
(((a)->s6_addr[12]) == 0xfe) && \
(((a)->s6_addr[13]) == 0))
/* check whether the 112-bit gid of the multicast address is mappable to: */
/* 48 bits, FFXX::00XX:XXXX:XXXX */
#define lowpan_is_mcast_addr_compressable48(a) \
((((a)->s6_addr16[1]) == 0) && \
(((a)->s6_addr16[2]) == 0) && \
(((a)->s6_addr16[3]) == 0) && \
(((a)->s6_addr16[4]) == 0) && \
(((a)->s6_addr[10]) == 0))
/* 32 bits, FFXX::00XX:XXXX */
#define lowpan_is_mcast_addr_compressable32(a) \
((((a)->s6_addr16[1]) == 0) && \
(((a)->s6_addr16[2]) == 0) && \
(((a)->s6_addr16[3]) == 0) && \
(((a)->s6_addr16[4]) == 0) && \
(((a)->s6_addr16[5]) == 0) && \
(((a)->s6_addr[12]) == 0))
/* 8 bits, FF02::00XX */
#define lowpan_is_mcast_addr_compressable8(a) \
((((a)->s6_addr[1]) == 2) && \
(((a)->s6_addr16[1]) == 0) && \
(((a)->s6_addr16[2]) == 0) && \
(((a)->s6_addr16[3]) == 0) && \
(((a)->s6_addr16[4]) == 0) && \
(((a)->s6_addr16[5]) == 0) && \
(((a)->s6_addr16[6]) == 0) && \
(((a)->s6_addr[14]) == 0))
#define lowpan_is_addr_broadcast(a) \
((((a)[0]) == 0xFF) && \
(((a)[1]) == 0xFF) && \
(((a)[2]) == 0xFF) && \
(((a)[3]) == 0xFF) && \
(((a)[4]) == 0xFF) && \
(((a)[5]) == 0xFF) && \
(((a)[6]) == 0xFF) && \
(((a)[7]) == 0xFF))
#define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
#define LOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */
#define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
#define LOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */
#define LOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */
#define LOWPAN_DISPATCH_MASK 0xf8 /* 11111000 */
#define LOWPAN_FRAG_TIMEOUT (HZ * 60) /* time-out 60 sec */
#define LOWPAN_FRAG1_HEAD_SIZE 0x4
#define LOWPAN_FRAGN_HEAD_SIZE 0x5
/*
* Values of fields within the IPHC encoding first byte
* (C stands for compressed and I for inline)
*/
#define LOWPAN_IPHC_TF 0x18
#define LOWPAN_IPHC_FL_C 0x10
#define LOWPAN_IPHC_TC_C 0x08
#define LOWPAN_IPHC_NH_C 0x04
#define LOWPAN_IPHC_TTL_1 0x01
#define LOWPAN_IPHC_TTL_64 0x02
#define LOWPAN_IPHC_TTL_255 0x03
#define LOWPAN_IPHC_TTL_I 0x00
/* Values of fields within the IPHC encoding second byte */
#define LOWPAN_IPHC_CID 0x80
#define LOWPAN_IPHC_ADDR_00 0x00
#define LOWPAN_IPHC_ADDR_01 0x01
#define LOWPAN_IPHC_ADDR_02 0x02
#define LOWPAN_IPHC_ADDR_03 0x03
#define LOWPAN_IPHC_SAC 0x40
#define LOWPAN_IPHC_SAM 0x30
#define LOWPAN_IPHC_SAM_BIT 4
#define LOWPAN_IPHC_M 0x08
#define LOWPAN_IPHC_DAC 0x04
#define LOWPAN_IPHC_DAM_00 0x00
#define LOWPAN_IPHC_DAM_01 0x01
#define LOWPAN_IPHC_DAM_10 0x02
#define LOWPAN_IPHC_DAM_11 0x03
#define LOWPAN_IPHC_DAM_BIT 0
/*
* LOWPAN_UDP encoding (works together with IPHC)
*/
#define LOWPAN_NHC_UDP_MASK 0xF8
#define LOWPAN_NHC_UDP_ID 0xF0
#define LOWPAN_NHC_UDP_CHECKSUMC 0x04
#define LOWPAN_NHC_UDP_CHECKSUMI 0x00
#define LOWPAN_NHC_UDP_4BIT_PORT 0xF0B0
#define LOWPAN_NHC_UDP_4BIT_MASK 0xFFF0
#define LOWPAN_NHC_UDP_8BIT_PORT 0xF000
#define LOWPAN_NHC_UDP_8BIT_MASK 0xFF00
/* values for port compression, _with checksum_ ie bit 5 set to 0 */
#define LOWPAN_NHC_UDP_CS_P_00 0xF0 /* all inline */
#define LOWPAN_NHC_UDP_CS_P_01 0xF1 /* source 16bit inline,
dest = 0xF0 + 8 bit inline */
#define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline,
dest = 16 bit inline */
#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
#define LOWPAN_NHC_UDP_CS_C 0x04 /* checksum elided */
#ifdef DEBUG
/* print data in line */
static inline void raw_dump_inline(const char *caller, char *msg,
unsigned char *buf, int len)
{
if (msg)
pr_debug("%s():%s: ", caller, msg);
print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, false);
}
/* print data in a table format:
*
* addr: xx xx xx xx xx xx
* addr: xx xx xx xx xx xx
* ...
*/
static inline void raw_dump_table(const char *caller, char *msg,
unsigned char *buf, int len)
{
if (msg)
pr_debug("%s():%s:\n", caller, msg);
print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 16, 1, buf, len, false);
}
#else
static inline void raw_dump_table(const char *caller, char *msg,
unsigned char *buf, int len) { }
static inline void raw_dump_inline(const char *caller, char *msg,
unsigned char *buf, int len) { }
#endif
static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
{
if (unlikely(!pskb_may_pull(skb, 1)))
return -EINVAL;
*val = skb->data[0];
skb_pull(skb, 1);
return 0;
}
static inline bool lowpan_fetch_skb(struct sk_buff *skb,
void *data, const unsigned int len)
{
if (unlikely(!pskb_may_pull(skb, len)))
return true;
skb_copy_from_linear_data(skb, data, len);
skb_pull(skb, len);
return false;
}
static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
const size_t len)
{
memcpy(*hc_ptr, data, len);
*hc_ptr += len;
}
static inline u8 lowpan_addr_mode_size(const u8 addr_mode)
{
static const u8 addr_sizes[] = {
[LOWPAN_IPHC_ADDR_00] = 16,
[LOWPAN_IPHC_ADDR_01] = 8,
[LOWPAN_IPHC_ADDR_02] = 2,
[LOWPAN_IPHC_ADDR_03] = 0,
};
return addr_sizes[addr_mode];
}
static inline u8 lowpan_next_hdr_size(const u8 h_enc, u16 *uncomp_header)
{
u8 ret = 1;
if ((h_enc & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
*uncomp_header += sizeof(struct udphdr);
switch (h_enc & LOWPAN_NHC_UDP_CS_P_11) {
case LOWPAN_NHC_UDP_CS_P_00:
ret += 4;
break;
case LOWPAN_NHC_UDP_CS_P_01:
case LOWPAN_NHC_UDP_CS_P_10:
ret += 3;
break;
case LOWPAN_NHC_UDP_CS_P_11:
ret++;
break;
default:
break;
}
if (!(h_enc & LOWPAN_NHC_UDP_CS_C))
ret += 2;
}
return ret;
}
/**
* lowpan_uncompress_size - returns skb->len size with uncompressed header
* @skb: sk_buff with 6lowpan header inside
* @datagram_offset: optional to get the datagram_offset value
*
* Returns the skb->len with uncompressed header
*/
static inline u16
lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
{
u16 ret = 2, uncomp_header = sizeof(struct ipv6hdr);
u8 iphc0, iphc1, h_enc;
iphc0 = skb_network_header(skb)[0];
iphc1 = skb_network_header(skb)[1];
switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
case 0:
ret += 4;
break;
case 1:
ret += 3;
break;
case 2:
ret++;
break;
default:
break;
}
if (!(iphc0 & LOWPAN_IPHC_NH_C))
ret++;
if (!(iphc0 & 0x03))
ret++;
ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_SAM) >>
LOWPAN_IPHC_SAM_BIT);
if (iphc1 & LOWPAN_IPHC_M) {
switch ((iphc1 & LOWPAN_IPHC_DAM_11) >>
LOWPAN_IPHC_DAM_BIT) {
case LOWPAN_IPHC_DAM_00:
ret += 16;
break;
case LOWPAN_IPHC_DAM_01:
ret += 6;
break;
case LOWPAN_IPHC_DAM_10:
ret += 4;
break;
case LOWPAN_IPHC_DAM_11:
ret++;
break;
default:
break;
}
} else {
ret += lowpan_addr_mode_size((iphc1 & LOWPAN_IPHC_DAM_11) >>
LOWPAN_IPHC_DAM_BIT);
}
if (iphc0 & LOWPAN_IPHC_NH_C) {
h_enc = skb_network_header(skb)[ret];
ret += lowpan_next_hdr_size(h_enc, &uncomp_header);
}
if (dgram_offset)
*dgram_offset = uncomp_header;
return skb->len + uncomp_header - ret;
}
typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *_daddr,
const void *_saddr, unsigned int len);
#endif /* __6LOWPAN_H__ */

577
include/net/9p/9p.h Normal file
View file

@ -0,0 +1,577 @@
/*
* include/net/9p/9p.h
*
* 9P protocol definitions.
*
* Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
*
* 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:
* Free Software Foundation
* 51 Franklin Street, Fifth Floor
* Boston, MA 02111-1301 USA
*
*/
#ifndef NET_9P_H
#define NET_9P_H
/**
* enum p9_debug_flags - bits for mount time debug parameter
* @P9_DEBUG_ERROR: more verbose error messages including original error string
* @P9_DEBUG_9P: 9P protocol tracing
* @P9_DEBUG_VFS: VFS API tracing
* @P9_DEBUG_CONV: protocol conversion tracing
* @P9_DEBUG_MUX: trace management of concurrent transactions
* @P9_DEBUG_TRANS: transport tracing
* @P9_DEBUG_SLABS: memory management tracing
* @P9_DEBUG_FCALL: verbose dump of protocol messages
* @P9_DEBUG_FID: fid allocation/deallocation tracking
* @P9_DEBUG_PKT: packet marshalling/unmarshalling
* @P9_DEBUG_FSC: FS-cache tracing
* @P9_DEBUG_VPKT: Verbose packet debugging (full packet dump)
*
* These flags are passed at mount time to turn on various levels of
* verbosity and tracing which will be output to the system logs.
*/
enum p9_debug_flags {
P9_DEBUG_ERROR = (1<<0),
P9_DEBUG_9P = (1<<2),
P9_DEBUG_VFS = (1<<3),
P9_DEBUG_CONV = (1<<4),
P9_DEBUG_MUX = (1<<5),
P9_DEBUG_TRANS = (1<<6),
P9_DEBUG_SLABS = (1<<7),
P9_DEBUG_FCALL = (1<<8),
P9_DEBUG_FID = (1<<9),
P9_DEBUG_PKT = (1<<10),
P9_DEBUG_FSC = (1<<11),
P9_DEBUG_VPKT = (1<<12),
};
#ifdef CONFIG_NET_9P_DEBUG
extern unsigned int p9_debug_level;
__printf(3, 4)
void _p9_debug(enum p9_debug_flags level, const char *func,
const char *fmt, ...);
#define p9_debug(level, fmt, ...) \
_p9_debug(level, __func__, fmt, ##__VA_ARGS__)
#else
#define p9_debug(level, fmt, ...) \
no_printk(fmt, ##__VA_ARGS__)
#endif
/**
* enum p9_msg_t - 9P message types
* @P9_TLERROR: not used
* @P9_RLERROR: response for any failed request for 9P2000.L
* @P9_TSTATFS: file system status request
* @P9_RSTATFS: file system status response
* @P9_TSYMLINK: make symlink request
* @P9_RSYMLINK: make symlink response
* @P9_TMKNOD: create a special file object request
* @P9_RMKNOD: create a special file object response
* @P9_TLCREATE: prepare a handle for I/O on an new file for 9P2000.L
* @P9_RLCREATE: response with file access information for 9P2000.L
* @P9_TRENAME: rename request
* @P9_RRENAME: rename response
* @P9_TMKDIR: create a directory request
* @P9_RMKDIR: create a directory response
* @P9_TVERSION: version handshake request
* @P9_RVERSION: version handshake response
* @P9_TAUTH: request to establish authentication channel
* @P9_RAUTH: response with authentication information
* @P9_TATTACH: establish user access to file service
* @P9_RATTACH: response with top level handle to file hierarchy
* @P9_TERROR: not used
* @P9_RERROR: response for any failed request
* @P9_TFLUSH: request to abort a previous request
* @P9_RFLUSH: response when previous request has been cancelled
* @P9_TWALK: descend a directory hierarchy
* @P9_RWALK: response with new handle for position within hierarchy
* @P9_TOPEN: prepare a handle for I/O on an existing file
* @P9_ROPEN: response with file access information
* @P9_TCREATE: prepare a handle for I/O on a new file
* @P9_RCREATE: response with file access information
* @P9_TREAD: request to transfer data from a file or directory
* @P9_RREAD: response with data requested
* @P9_TWRITE: reuqest to transfer data to a file
* @P9_RWRITE: response with out much data was transferred to file
* @P9_TCLUNK: forget about a handle to an entity within the file system
* @P9_RCLUNK: response when server has forgotten about the handle
* @P9_TREMOVE: request to remove an entity from the hierarchy
* @P9_RREMOVE: response when server has removed the entity
* @P9_TSTAT: request file entity attributes
* @P9_RSTAT: response with file entity attributes
* @P9_TWSTAT: request to update file entity attributes
* @P9_RWSTAT: response when file entity attributes are updated
*
* There are 14 basic operations in 9P2000, paired as
* requests and responses. The one special case is ERROR
* as there is no @P9_TERROR request for clients to transmit to
* the server, but the server may respond to any other request
* with an @P9_RERROR.
*
* See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html
*/
enum p9_msg_t {
P9_TLERROR = 6,
P9_RLERROR,
P9_TSTATFS = 8,
P9_RSTATFS,
P9_TLOPEN = 12,
P9_RLOPEN,
P9_TLCREATE = 14,
P9_RLCREATE,
P9_TSYMLINK = 16,
P9_RSYMLINK,
P9_TMKNOD = 18,
P9_RMKNOD,
P9_TRENAME = 20,
P9_RRENAME,
P9_TREADLINK = 22,
P9_RREADLINK,
P9_TGETATTR = 24,
P9_RGETATTR,
P9_TSETATTR = 26,
P9_RSETATTR,
P9_TXATTRWALK = 30,
P9_RXATTRWALK,
P9_TXATTRCREATE = 32,
P9_RXATTRCREATE,
P9_TREADDIR = 40,
P9_RREADDIR,
P9_TFSYNC = 50,
P9_RFSYNC,
P9_TLOCK = 52,
P9_RLOCK,
P9_TGETLOCK = 54,
P9_RGETLOCK,
P9_TLINK = 70,
P9_RLINK,
P9_TMKDIR = 72,
P9_RMKDIR,
P9_TRENAMEAT = 74,
P9_RRENAMEAT,
P9_TUNLINKAT = 76,
P9_RUNLINKAT,
P9_TVERSION = 100,
P9_RVERSION,
P9_TAUTH = 102,
P9_RAUTH,
P9_TATTACH = 104,
P9_RATTACH,
P9_TERROR = 106,
P9_RERROR,
P9_TFLUSH = 108,
P9_RFLUSH,
P9_TWALK = 110,
P9_RWALK,
P9_TOPEN = 112,
P9_ROPEN,
P9_TCREATE = 114,
P9_RCREATE,
P9_TREAD = 116,
P9_RREAD,
P9_TWRITE = 118,
P9_RWRITE,
P9_TCLUNK = 120,
P9_RCLUNK,
P9_TREMOVE = 122,
P9_RREMOVE,
P9_TSTAT = 124,
P9_RSTAT,
P9_TWSTAT = 126,
P9_RWSTAT,
};
/**
* enum p9_open_mode_t - 9P open modes
* @P9_OREAD: open file for reading only
* @P9_OWRITE: open file for writing only
* @P9_ORDWR: open file for reading or writing
* @P9_OEXEC: open file for execution
* @P9_OTRUNC: truncate file to zero-length before opening it
* @P9_OREXEC: close the file when an exec(2) system call is made
* @P9_ORCLOSE: remove the file when the file is closed
* @P9_OAPPEND: open the file and seek to the end
* @P9_OEXCL: only create a file, do not open it
*
* 9P open modes differ slightly from Posix standard modes.
* In particular, there are extra modes which specify different
* semantic behaviors than may be available on standard Posix
* systems. For example, @P9_OREXEC and @P9_ORCLOSE are modes that
* most likely will not be issued from the Linux VFS client, but may
* be supported by servers.
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/open
*/
enum p9_open_mode_t {
P9_OREAD = 0x00,
P9_OWRITE = 0x01,
P9_ORDWR = 0x02,
P9_OEXEC = 0x03,
P9_OTRUNC = 0x10,
P9_OREXEC = 0x20,
P9_ORCLOSE = 0x40,
P9_OAPPEND = 0x80,
P9_OEXCL = 0x1000,
};
/**
* enum p9_perm_t - 9P permissions
* @P9_DMDIR: mode bit for directories
* @P9_DMAPPEND: mode bit for is append-only
* @P9_DMEXCL: mode bit for excluse use (only one open handle allowed)
* @P9_DMMOUNT: mode bit for mount points
* @P9_DMAUTH: mode bit for authentication file
* @P9_DMTMP: mode bit for non-backed-up files
* @P9_DMSYMLINK: mode bit for symbolic links (9P2000.u)
* @P9_DMLINK: mode bit for hard-link (9P2000.u)
* @P9_DMDEVICE: mode bit for device files (9P2000.u)
* @P9_DMNAMEDPIPE: mode bit for named pipe (9P2000.u)
* @P9_DMSOCKET: mode bit for socket (9P2000.u)
* @P9_DMSETUID: mode bit for setuid (9P2000.u)
* @P9_DMSETGID: mode bit for setgid (9P2000.u)
* @P9_DMSETVTX: mode bit for sticky bit (9P2000.u)
*
* 9P permissions differ slightly from Posix standard modes.
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
*/
enum p9_perm_t {
P9_DMDIR = 0x80000000,
P9_DMAPPEND = 0x40000000,
P9_DMEXCL = 0x20000000,
P9_DMMOUNT = 0x10000000,
P9_DMAUTH = 0x08000000,
P9_DMTMP = 0x04000000,
/* 9P2000.u extensions */
P9_DMSYMLINK = 0x02000000,
P9_DMLINK = 0x01000000,
P9_DMDEVICE = 0x00800000,
P9_DMNAMEDPIPE = 0x00200000,
P9_DMSOCKET = 0x00100000,
P9_DMSETUID = 0x00080000,
P9_DMSETGID = 0x00040000,
P9_DMSETVTX = 0x00010000,
};
/* 9p2000.L open flags */
#define P9_DOTL_RDONLY 00000000
#define P9_DOTL_WRONLY 00000001
#define P9_DOTL_RDWR 00000002
#define P9_DOTL_NOACCESS 00000003
#define P9_DOTL_CREATE 00000100
#define P9_DOTL_EXCL 00000200
#define P9_DOTL_NOCTTY 00000400
#define P9_DOTL_TRUNC 00001000
#define P9_DOTL_APPEND 00002000
#define P9_DOTL_NONBLOCK 00004000
#define P9_DOTL_DSYNC 00010000
#define P9_DOTL_FASYNC 00020000
#define P9_DOTL_DIRECT 00040000
#define P9_DOTL_LARGEFILE 00100000
#define P9_DOTL_DIRECTORY 00200000
#define P9_DOTL_NOFOLLOW 00400000
#define P9_DOTL_NOATIME 01000000
#define P9_DOTL_CLOEXEC 02000000
#define P9_DOTL_SYNC 04000000
/* 9p2000.L at flags */
#define P9_DOTL_AT_REMOVEDIR 0x200
/* 9p2000.L lock type */
#define P9_LOCK_TYPE_RDLCK 0
#define P9_LOCK_TYPE_WRLCK 1
#define P9_LOCK_TYPE_UNLCK 2
/**
* enum p9_qid_t - QID types
* @P9_QTDIR: directory
* @P9_QTAPPEND: append-only
* @P9_QTEXCL: excluse use (only one open handle allowed)
* @P9_QTMOUNT: mount points
* @P9_QTAUTH: authentication file
* @P9_QTTMP: non-backed-up files
* @P9_QTSYMLINK: symbolic links (9P2000.u)
* @P9_QTLINK: hard-link (9P2000.u)
* @P9_QTFILE: normal files
*
* QID types are a subset of permissions - they are primarily
* used to differentiate semantics for a file system entity via
* a jump-table. Their value is also the most significant 16 bits
* of the permission_t
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
*/
enum p9_qid_t {
P9_QTDIR = 0x80,
P9_QTAPPEND = 0x40,
P9_QTEXCL = 0x20,
P9_QTMOUNT = 0x10,
P9_QTAUTH = 0x08,
P9_QTTMP = 0x04,
P9_QTSYMLINK = 0x02,
P9_QTLINK = 0x01,
P9_QTFILE = 0x00,
};
/* 9P Magic Numbers */
#define P9_NOTAG (u16)(~0)
#define P9_NOFID (u32)(~0)
#define P9_MAXWELEM 16
/* ample room for Twrite/Rread header */
#define P9_IOHDRSZ 24
/* Room for readdir header */
#define P9_READDIRHDRSZ 24
/* size of header for zero copy read/write */
#define P9_ZC_HDR_SZ 4096
/**
* struct p9_qid - file system entity information
* @type: 8-bit type &p9_qid_t
* @version: 16-bit monotonically incrementing version number
* @path: 64-bit per-server-unique ID for a file system element
*
* qids are identifiers used by 9P servers to track file system
* entities. The type is used to differentiate semantics for operations
* on the entity (ie. read means something different on a directory than
* on a file). The path provides a server unique index for an entity
* (roughly analogous to an inode number), while the version is updated
* every time a file is modified and can be used to maintain cache
* coherency between clients and serves.
* Servers will often differentiate purely synthetic entities by setting
* their version to 0, signaling that they should never be cached and
* should be accessed synchronously.
*
* See Also://plan9.bell-labs.com/magic/man2html/2/stat
*/
struct p9_qid {
u8 type;
u32 version;
u64 path;
};
/**
* struct p9_wstat - file system metadata information
* @size: length prefix for this stat structure instance
* @type: the type of the server (equivalent to a major number)
* @dev: the sub-type of the server (equivalent to a minor number)
* @qid: unique id from the server of type &p9_qid
* @mode: Plan 9 format permissions of type &p9_perm_t
* @atime: Last access/read time
* @mtime: Last modify/write time
* @length: file length
* @name: last element of path (aka filename)
* @uid: owner name
* @gid: group owner
* @muid: last modifier
* @extension: area used to encode extended UNIX support
* @n_uid: numeric user id of owner (part of 9p2000.u extension)
* @n_gid: numeric group id (part of 9p2000.u extension)
* @n_muid: numeric user id of laster modifier (part of 9p2000.u extension)
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
*/
struct p9_wstat {
u16 size;
u16 type;
u32 dev;
struct p9_qid qid;
u32 mode;
u32 atime;
u32 mtime;
u64 length;
char *name;
char *uid;
char *gid;
char *muid;
char *extension; /* 9p2000.u extensions */
kuid_t n_uid; /* 9p2000.u extensions */
kgid_t n_gid; /* 9p2000.u extensions */
kuid_t n_muid; /* 9p2000.u extensions */
};
struct p9_stat_dotl {
u64 st_result_mask;
struct p9_qid qid;
u32 st_mode;
kuid_t st_uid;
kgid_t st_gid;
u64 st_nlink;
u64 st_rdev;
u64 st_size;
u64 st_blksize;
u64 st_blocks;
u64 st_atime_sec;
u64 st_atime_nsec;
u64 st_mtime_sec;
u64 st_mtime_nsec;
u64 st_ctime_sec;
u64 st_ctime_nsec;
u64 st_btime_sec;
u64 st_btime_nsec;
u64 st_gen;
u64 st_data_version;
};
#define P9_STATS_MODE 0x00000001ULL
#define P9_STATS_NLINK 0x00000002ULL
#define P9_STATS_UID 0x00000004ULL
#define P9_STATS_GID 0x00000008ULL
#define P9_STATS_RDEV 0x00000010ULL
#define P9_STATS_ATIME 0x00000020ULL
#define P9_STATS_MTIME 0x00000040ULL
#define P9_STATS_CTIME 0x00000080ULL
#define P9_STATS_INO 0x00000100ULL
#define P9_STATS_SIZE 0x00000200ULL
#define P9_STATS_BLOCKS 0x00000400ULL
#define P9_STATS_BTIME 0x00000800ULL
#define P9_STATS_GEN 0x00001000ULL
#define P9_STATS_DATA_VERSION 0x00002000ULL
#define P9_STATS_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */
#define P9_STATS_ALL 0x00003fffULL /* Mask for All fields above */
/**
* struct p9_iattr_dotl - P9 inode attribute for setattr
* @valid: bitfield specifying which fields are valid
* same as in struct iattr
* @mode: File permission bits
* @uid: user id of owner
* @gid: group id
* @size: File size
* @atime_sec: Last access time, seconds
* @atime_nsec: Last access time, nanoseconds
* @mtime_sec: Last modification time, seconds
* @mtime_nsec: Last modification time, nanoseconds
*/
struct p9_iattr_dotl {
u32 valid;
u32 mode;
kuid_t uid;
kgid_t gid;
u64 size;
u64 atime_sec;
u64 atime_nsec;
u64 mtime_sec;
u64 mtime_nsec;
};
#define P9_LOCK_SUCCESS 0
#define P9_LOCK_BLOCKED 1
#define P9_LOCK_ERROR 2
#define P9_LOCK_GRACE 3
#define P9_LOCK_FLAGS_BLOCK 1
#define P9_LOCK_FLAGS_RECLAIM 2
/* struct p9_flock: POSIX lock structure
* @type - type of lock
* @flags - lock flags
* @start - starting offset of the lock
* @length - number of bytes
* @proc_id - process id which wants to take lock
* @client_id - client id
*/
struct p9_flock {
u8 type;
u32 flags;
u64 start;
u64 length;
u32 proc_id;
char *client_id;
};
/* struct p9_getlock: getlock structure
* @type - type of lock
* @start - starting offset of the lock
* @length - number of bytes
* @proc_id - process id which wants to take lock
* @client_id - client id
*/
struct p9_getlock {
u8 type;
u64 start;
u64 length;
u32 proc_id;
char *client_id;
};
struct p9_rstatfs {
u32 type;
u32 bsize;
u64 blocks;
u64 bfree;
u64 bavail;
u64 files;
u64 ffree;
u64 fsid;
u32 namelen;
};
/**
* struct p9_fcall - primary packet structure
* @size: prefixed length of the structure
* @id: protocol operating identifier of type &p9_msg_t
* @tag: transaction id of the request
* @offset: used by marshalling routines to track current position in buffer
* @capacity: used by marshalling routines to track total malloc'd capacity
* @sdata: payload
*
* &p9_fcall represents the structure for all 9P RPC
* transactions. Requests are packaged into fcalls, and reponses
* must be extracted from them.
*
* See Also: http://plan9.bell-labs.com/magic/man2html/2/fcall
*/
struct p9_fcall {
u32 size;
u8 id;
u16 tag;
size_t offset;
size_t capacity;
u8 *sdata;
};
struct p9_idpool;
int p9_errstr2errno(char *errstr, int len);
struct p9_idpool *p9_idpool_create(void);
void p9_idpool_destroy(struct p9_idpool *);
int p9_idpool_get(struct p9_idpool *p);
void p9_idpool_put(int id, struct p9_idpool *p);
int p9_idpool_check(int id, struct p9_idpool *p);
int p9_error_init(void);
int p9_trans_fd_init(void);
void p9_trans_fd_exit(void);
#endif /* NET_9P_H */

272
include/net/9p/client.h Normal file
View file

@ -0,0 +1,272 @@
/*
* include/net/9p/client.h
*
* 9P Client Definitions
*
* Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
*
* 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.
*
* 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:
* Free Software Foundation
* 51 Franklin Street, Fifth Floor
* Boston, MA 02111-1301 USA
*
*/
#ifndef NET_9P_CLIENT_H
#define NET_9P_CLIENT_H
#include <linux/utsname.h>
/* Number of requests per row */
#define P9_ROW_MAXTAG 255
/** enum p9_proto_versions - 9P protocol versions
* @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
* @p9_proto_2000u: 9P2000.u extension
* @p9_proto_2000L: 9P2000.L extension
*/
enum p9_proto_versions{
p9_proto_legacy,
p9_proto_2000u,
p9_proto_2000L,
};
/**
* enum p9_trans_status - different states of underlying transports
* @Connected: transport is connected and healthy
* @Disconnected: transport has been disconnected
* @Hung: transport is connected by wedged
*
* This enumeration details the various states a transport
* instatiation can be in.
*/
enum p9_trans_status {
Connected,
BeginDisconnect,
Disconnected,
Hung,
};
/**
* enum p9_req_status_t - status of a request
* @REQ_STATUS_IDLE: request slot unused
* @REQ_STATUS_ALLOC: request has been allocated but not sent
* @REQ_STATUS_UNSENT: request waiting to be sent
* @REQ_STATUS_SENT: request sent to server
* @REQ_STATUS_RCVD: response received from server
* @REQ_STATUS_FLSHD: request has been flushed
* @REQ_STATUS_ERROR: request encountered an error on the client side
*
* The @REQ_STATUS_IDLE state is used to mark a request slot as unused
* but use is actually tracked by the idpool structure which handles tag
* id allocation.
*
*/
enum p9_req_status_t {
REQ_STATUS_IDLE,
REQ_STATUS_ALLOC,
REQ_STATUS_UNSENT,
REQ_STATUS_SENT,
REQ_STATUS_RCVD,
REQ_STATUS_FLSHD,
REQ_STATUS_ERROR,
};
/**
* struct p9_req_t - request slots
* @status: status of this request slot
* @t_err: transport error
* @flush_tag: tag of request being flushed (for flush requests)
* @wq: wait_queue for the client to block on for this request
* @tc: the request fcall structure
* @rc: the response fcall structure
* @aux: transport specific data (provided for trans_fd migration)
* @req_list: link for higher level objects to chain requests
*
* Transport use an array to track outstanding requests
* instead of a list. While this may incurr overhead during initial
* allocation or expansion, it makes request lookup much easier as the
* tag id is a index into an array. (We use tag+1 so that we can accommodate
* the -1 tag for the T_VERSION request).
* This also has the nice effect of only having to allocate wait_queues
* once, instead of constantly allocating and freeing them. Its possible
* other resources could benefit from this scheme as well.
*
*/
struct p9_req_t {
int status;
int t_err;
wait_queue_head_t *wq;
struct p9_fcall *tc;
struct p9_fcall *rc;
void *aux;
struct list_head req_list;
};
/**
* struct p9_client - per client instance state
* @lock: protect @fidlist
* @msize: maximum data size negotiated by protocol
* @dotu: extension flags negotiated by protocol
* @proto_version: 9P protocol version to use
* @trans_mod: module API instantiated with this client
* @trans: tranport instance state and API
* @fidpool: fid handle accounting for session
* @fidlist: List of active fid handles
* @tagpool - transaction id accounting for session
* @reqs - 2D array of requests
* @max_tag - current maximum tag id allocated
* @name - node name used as client id
*
* The client structure is used to keep track of various per-client
* state that has been instantiated.
* In order to minimize per-transaction overhead we use a
* simple array to lookup requests instead of a hash table
* or linked list. In order to support larger number of
* transactions, we make this a 2D array, allocating new rows
* when we need to grow the total number of the transactions.
*
* Each row is 256 requests and we'll support up to 256 rows for
* a total of 64k concurrent requests per session.
*
* Bugs: duplicated data and potentially unnecessary elements.
*/
struct p9_client {
spinlock_t lock; /* protect client structure */
unsigned int msize;
unsigned char proto_version;
struct p9_trans_module *trans_mod;
enum p9_trans_status status;
void *trans;
struct p9_idpool *fidpool;
struct list_head fidlist;
struct p9_idpool *tagpool;
struct p9_req_t *reqs[P9_ROW_MAXTAG];
int max_tag;
char name[__NEW_UTS_LEN + 1];
};
/**
* struct p9_fid - file system entity handle
* @clnt: back pointer to instantiating &p9_client
* @fid: numeric identifier for this handle
* @mode: current mode of this fid (enum?)
* @qid: the &p9_qid server identifier this handle points to
* @iounit: the server reported maximum transaction size for this file
* @uid: the numeric uid of the local user who owns this handle
* @rdir: readdir accounting structure (allocated on demand)
* @flist: per-client-instance fid tracking
* @dlist: per-dentry fid tracking
*
* TODO: This needs lots of explanation.
*/
struct p9_fid {
struct p9_client *clnt;
u32 fid;
int mode;
struct p9_qid qid;
u32 iounit;
kuid_t uid;
void *rdir;
struct list_head flist;
struct hlist_node dlist; /* list of all fids attached to a dentry */
};
/**
* struct p9_dirent - directory entry structure
* @qid: The p9 server qid for this dirent
* @d_off: offset to the next dirent
* @d_type: type of file
* @d_name: file name
*/
struct p9_dirent {
struct p9_qid qid;
u64 d_off;
unsigned char d_type;
char d_name[256];
};
int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid,
const char *name);
int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
struct p9_fid *newdirfid, const char *new_name);
struct p9_client *p9_client_create(const char *dev_name, char *options);
void p9_client_destroy(struct p9_client *clnt);
void p9_client_disconnect(struct p9_client *clnt);
void p9_client_begin_disconnect(struct p9_client *clnt);
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
char *uname, kuid_t n_uname, char *aname);
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
char **wnames, int clone);
int p9_client_open(struct p9_fid *fid, int mode);
int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
char *extension);
int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname);
int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, kgid_t gid,
struct p9_qid *qid);
int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
kgid_t gid, struct p9_qid *qid);
int p9_client_clunk(struct p9_fid *fid);
int p9_client_fsync(struct p9_fid *fid, int datasync);
int p9_client_remove(struct p9_fid *fid);
int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
u64 offset, u32 count);
int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
u64 offset, u32 count);
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
int p9dirent_read(struct p9_client *clnt, char *buf, int len,
struct p9_dirent *dirent);
struct p9_wstat *p9_client_stat(struct p9_fid *fid);
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
u64 request_mask);
int p9_client_mknod_dotl(struct p9_fid *oldfid, char *name, int mode,
dev_t rdev, kgid_t gid, struct p9_qid *);
int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
kgid_t gid, struct p9_qid *);
int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int);
int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *);
void p9stat_free(struct p9_wstat *);
int p9_is_proto_dotu(struct p9_client *clnt);
int p9_is_proto_dotl(struct p9_client *clnt);
struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *);
int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int);
int p9_client_readlink(struct p9_fid *fid, char **target);
#endif /* NET_9P_CLIENT_H */

View file

@ -0,0 +1,72 @@
/*
* include/net/9p/transport.h
*
* Transport Definition
*
* Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
*
* 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.
*
* 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:
* Free Software Foundation
* 51 Franklin Street, Fifth Floor
* Boston, MA 02111-1301 USA
*
*/
#ifndef NET_9P_TRANSPORT_H
#define NET_9P_TRANSPORT_H
#define P9_DEF_MIN_RESVPORT (665U)
#define P9_DEF_MAX_RESVPORT (1023U)
/**
* struct p9_trans_module - transport module interface
* @list: used to maintain a list of currently available transports
* @name: the human-readable name of the transport
* @maxsize: transport provided maximum packet size
* @def: set if this transport should be considered the default
* @create: member function to create a new connection on this transport
* @close: member function to discard a connection on this transport
* @request: member function to issue a request to the transport
* @cancel: member function to cancel a request (if it hasn't been sent)
* @cancelled: member function to notify that a cancelled request will not
* not receive a reply
*
* This is the basic API for a transport module which is registered by the
* transport module with the 9P core network module and used by the client
* to instantiate a new connection on a transport.
*
* The transport module list is protected by v9fs_trans_lock.
*/
struct p9_trans_module {
struct list_head list;
char *name; /* name of transport */
int maxsize; /* max message size of transport */
int def; /* this transport should be default */
struct module *owner;
int (*create)(struct p9_client *, const char *, char *);
void (*close) (struct p9_client *);
int (*request) (struct p9_client *, struct p9_req_t *req);
int (*cancel) (struct p9_client *, struct p9_req_t *req);
int (*cancelled)(struct p9_client *, struct p9_req_t *req);
int (*zc_request)(struct p9_client *, struct p9_req_t *,
char *, char *, int , int, int, int);
};
void v9fs_register_trans(struct p9_trans_module *m);
void v9fs_unregister_trans(struct p9_trans_module *m);
struct p9_trans_module *v9fs_get_trans_by_name(char *s);
struct p9_trans_module *v9fs_get_default_trans(void);
void v9fs_put_trans(struct p9_trans_module *m);
#endif /* NET_9P_TRANSPORT_H */

31
include/net/Space.h Normal file
View file

@ -0,0 +1,31 @@
/* A unified ethernet device probe. This is the easiest way to have every
* ethernet adaptor have the name "eth[0123...]".
*/
struct net_device *hp100_probe(int unit);
struct net_device *ultra_probe(int unit);
struct net_device *wd_probe(int unit);
struct net_device *ne_probe(int unit);
struct net_device *fmv18x_probe(int unit);
struct net_device *i82596_probe(int unit);
struct net_device *ni65_probe(int unit);
struct net_device *sonic_probe(int unit);
struct net_device *smc_init(int unit);
struct net_device *atarilance_probe(int unit);
struct net_device *sun3lance_probe(int unit);
struct net_device *sun3_82586_probe(int unit);
struct net_device *apne_probe(int unit);
struct net_device *cs89x0_probe(int unit);
struct net_device *mvme147lance_probe(int unit);
struct net_device *tc515_probe(int unit);
struct net_device *lance_probe(int unit);
struct net_device *mac8390_probe(int unit);
struct net_device *mac89x0_probe(int unit);
struct net_device *cops_probe(int unit);
struct net_device *ltpc_probe(void);
/* Fibre Channel adapters */
int iph5526_probe(struct net_device *dev);
/* SBNI adapters */
int sbni_probe(int unit);

126
include/net/act_api.h Normal file
View file

@ -0,0 +1,126 @@
#ifndef __NET_ACT_API_H
#define __NET_ACT_API_H
/*
* Public police action API for classifiers/qdiscs
*/
#include <net/sch_generic.h>
#include <net/pkt_sched.h>
struct tcf_common {
struct hlist_node tcfc_head;
u32 tcfc_index;
int tcfc_refcnt;
int tcfc_bindcnt;
u32 tcfc_capab;
int tcfc_action;
struct tcf_t tcfc_tm;
struct gnet_stats_basic_packed tcfc_bstats;
struct gnet_stats_queue tcfc_qstats;
struct gnet_stats_rate_est64 tcfc_rate_est;
spinlock_t tcfc_lock;
struct rcu_head tcfc_rcu;
};
#define tcf_head common.tcfc_head
#define tcf_index common.tcfc_index
#define tcf_refcnt common.tcfc_refcnt
#define tcf_bindcnt common.tcfc_bindcnt
#define tcf_capab common.tcfc_capab
#define tcf_action common.tcfc_action
#define tcf_tm common.tcfc_tm
#define tcf_bstats common.tcfc_bstats
#define tcf_qstats common.tcfc_qstats
#define tcf_rate_est common.tcfc_rate_est
#define tcf_lock common.tcfc_lock
#define tcf_rcu common.tcfc_rcu
struct tcf_hashinfo {
struct hlist_head *htab;
unsigned int hmask;
spinlock_t lock;
u32 index;
};
static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
{
return index & hmask;
}
static inline int tcf_hashinfo_init(struct tcf_hashinfo *hf, unsigned int mask)
{
int i;
spin_lock_init(&hf->lock);
hf->index = 0;
hf->hmask = mask;
hf->htab = kzalloc((mask + 1) * sizeof(struct hlist_head),
GFP_KERNEL);
if (!hf->htab)
return -ENOMEM;
for (i = 0; i < mask + 1; i++)
INIT_HLIST_HEAD(&hf->htab[i]);
return 0;
}
static inline void tcf_hashinfo_destroy(struct tcf_hashinfo *hf)
{
kfree(hf->htab);
}
#ifdef CONFIG_NET_CLS_ACT
#define ACT_P_CREATED 1
#define ACT_P_DELETED 1
struct tc_action {
void *priv;
const struct tc_action_ops *ops;
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
__u32 order;
struct list_head list;
};
struct tc_action_ops {
struct list_head head;
struct tcf_hashinfo *hinfo;
char kind[IFNAMSIZ];
__u32 type; /* TBD to match kind */
struct module *owner;
int (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void (*cleanup)(struct tc_action *, int bind);
int (*lookup)(struct tc_action *, u32);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *act, int ovr,
int bind);
int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *);
};
int tcf_hash_search(struct tc_action *a, u32 index);
void tcf_hash_destroy(struct tc_action *a);
int tcf_hash_release(struct tc_action *a, int bind);
u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo);
int tcf_hash_check(u32 index, struct tc_action *a, int bind);
int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
int size, int bind);
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
void tcf_hash_insert(struct tc_action *a);
int tcf_register_action(struct tc_action_ops *a, unsigned int mask);
int tcf_unregister_action(struct tc_action_ops *a);
int tcf_action_destroy(struct list_head *actions, int bind);
int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
struct tcf_result *res);
int tcf_action_init(struct net *net, struct nlattr *nla,
struct nlattr *est, char *n, int ovr,
int bind, struct list_head *);
struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
struct nlattr *est, char *n, int ovr,
int bind);
int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
#endif /* CONFIG_NET_CLS_ACT */
#endif

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2010 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
* Author: Mike Chan (mike@android.com)
*/
#ifndef __activity_stats_h
#define __activity_stats_h
#ifdef CONFIG_NET_ACTIVITY_STATS
void activity_stats_update(void);
#else
#define activity_stats_update(void) {}
#endif
#endif /* _NET_ACTIVITY_STATS_H */

364
include/net/addrconf.h Normal file
View file

@ -0,0 +1,364 @@
#ifndef _ADDRCONF_H
#define _ADDRCONF_H
#define MAX_RTR_SOLICITATIONS 3
#define RTR_SOLICITATION_INTERVAL (4*HZ)
#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
#define TEMP_VALID_LIFETIME (7*86400)
#define TEMP_PREFERRED_LIFETIME (86400)
#define REGEN_MAX_RETRY (3)
#define MAX_DESYNC_FACTOR (600)
#define ADDR_CHECK_FREQUENCY (120*HZ)
#define IPV6_MAX_ADDRESSES 16
#define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ / 50 : 1)
#define ADDRCONF_TIMER_FUZZ (HZ / 4)
#define ADDRCONF_TIMER_FUZZ_MAX (HZ)
#include <linux/in.h>
#include <linux/in6.h>
struct prefix_info {
__u8 type;
__u8 length;
__u8 prefix_len;
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 onlink : 1,
autoconf : 1,
reserved : 6;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 reserved : 6,
autoconf : 1,
onlink : 1;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__be32 valid;
__be32 prefered;
__be32 reserved2;
struct in6_addr prefix;
};
#include <linux/netdevice.h>
#include <net/if_inet6.h>
#include <net/ipv6.h>
#define IN6_ADDR_HSIZE_SHIFT 4
#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
int addrconf_init(void);
void addrconf_cleanup(void);
int addrconf_add_ifaddr(struct net *net, void __user *arg);
int addrconf_del_ifaddr(struct net *net, void __user *arg);
int addrconf_set_dstaddr(struct net *net, void __user *arg);
int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
const struct net_device *dev, int strict);
int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
const struct net_device *dev, int strict,
u32 banned_flags);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
#endif
bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
const unsigned int prefix_len,
struct net_device *dev);
int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
const struct in6_addr *addr,
struct net_device *dev, int strict);
int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
const struct in6_addr *daddr, unsigned int srcprefs,
struct in6_addr *saddr);
int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
u32 banned_flags);
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
u32 banned_flags);
int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2);
void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
static inline unsigned long addrconf_timeout_fixup(u32 timeout,
unsigned int unit)
{
if (timeout == 0xffffffff)
return ~0UL;
/*
* Avoid arithmetic overflow.
* Assuming unit is constant and non-zero, this "if" statement
* will go away on 64bit archs.
*/
if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
return LONG_MAX / unit;
return timeout;
}
static inline int addrconf_finite_timeout(unsigned long timeout)
{
return ~timeout;
}
/*
* IPv6 Address Label subsystem (addrlabel.c)
*/
int ipv6_addr_label_init(void);
void ipv6_addr_label_cleanup(void);
void ipv6_addr_label_rtnl_register(void);
u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr,
int type, int ifindex);
/*
* multicast prototypes (mcast.c)
*/
int ipv6_sock_mc_join(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
const struct in6_addr *addr);
void ipv6_sock_mc_close(struct sock *sk);
bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
const struct in6_addr *src_addr);
int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
void ipv6_mc_up(struct inet6_dev *idev);
void ipv6_mc_down(struct inet6_dev *idev);
void ipv6_mc_unmap(struct inet6_dev *idev);
void ipv6_mc_remap(struct inet6_dev *idev);
void ipv6_mc_init_dev(struct inet6_dev *idev);
void ipv6_mc_destroy_dev(struct inet6_dev *idev);
void addrconf_dad_failure(struct inet6_ifaddr *ifp);
bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
const struct in6_addr *src_addr);
void ipv6_mc_dad_complete(struct inet6_dev *idev);
/* A stub used by vxlan module. This is ugly, ideally these
* symbols should be built into the core kernel.
*/
struct ipv6_stub {
int (*ipv6_sock_mc_join)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int (*ipv6_dst_lookup)(struct sock *sk, struct dst_entry **dst,
struct flowi6 *fl6);
void (*udpv6_encap_enable)(void);
void (*ndisc_send_na)(struct net_device *dev, struct neighbour *neigh,
const struct in6_addr *daddr,
const struct in6_addr *solicited_addr,
bool router, bool solicited, bool override, bool inc_opt);
struct neigh_table *nd_tbl;
};
extern const struct ipv6_stub *ipv6_stub __read_mostly;
/*
* identify MLD packets for MLD filter exceptions
*/
static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset)
{
struct icmp6hdr *hdr;
if (nexthdr != IPPROTO_ICMPV6 ||
!pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr)))
return false;
hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset);
switch (hdr->icmp6_type) {
case ICMPV6_MGM_QUERY:
case ICMPV6_MGM_REPORT:
case ICMPV6_MGM_REDUCTION:
case ICMPV6_MLD2_REPORT:
return true;
default:
break;
}
return false;
}
void addrconf_prefix_rcv(struct net_device *dev,
u8 *opt, int len, bool sllao);
u32 addrconf_rt_table(const struct net_device *dev, u32 default_table);
/*
* anycast prototypes (anycast.c)
*/
int ipv6_sock_ac_join(struct sock *sk, int ifindex,
const struct in6_addr *addr);
int ipv6_sock_ac_drop(struct sock *sk, int ifindex,
const struct in6_addr *addr);
void ipv6_sock_ac_close(struct sock *sk);
int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr);
int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
void ipv6_ac_destroy_dev(struct inet6_dev *idev);
bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
const struct in6_addr *addr);
bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev,
const struct in6_addr *addr);
/* Device notifier */
int register_inet6addr_notifier(struct notifier_block *nb);
int unregister_inet6addr_notifier(struct notifier_block *nb);
int inet6addr_notifier_call_chain(unsigned long val, void *v);
void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
struct ipv6_devconf *devconf);
/**
* __in6_dev_get - get inet6_dev pointer from netdevice
* @dev: network device
*
* Caller must hold rcu_read_lock or RTNL, because this function
* does not take a reference on the inet6_dev.
*/
static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
{
return rcu_dereference_rtnl(dev->ip6_ptr);
}
/**
* in6_dev_get - get inet6_dev pointer from netdevice
* @dev: network device
*
* This version can be used in any context, and takes a reference
* on the inet6_dev. Callers must use in6_dev_put() later to
* release this reference.
*/
static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
{
struct inet6_dev *idev;
rcu_read_lock();
idev = rcu_dereference(dev->ip6_ptr);
if (idev)
atomic_inc(&idev->refcnt);
rcu_read_unlock();
return idev;
}
static inline struct neigh_parms *__in6_dev_nd_parms_get_rcu(const struct net_device *dev)
{
struct inet6_dev *idev = __in6_dev_get(dev);
return idev ? idev->nd_parms : NULL;
}
void in6_dev_finish_destroy(struct inet6_dev *idev);
static inline void in6_dev_put(struct inet6_dev *idev)
{
if (atomic_dec_and_test(&idev->refcnt))
in6_dev_finish_destroy(idev);
}
static inline void __in6_dev_put(struct inet6_dev *idev)
{
atomic_dec(&idev->refcnt);
}
static inline void in6_dev_hold(struct inet6_dev *idev)
{
atomic_inc(&idev->refcnt);
}
void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp);
static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
{
if (atomic_dec_and_test(&ifp->refcnt))
inet6_ifa_finish_destroy(ifp);
}
static inline void __in6_ifa_put(struct inet6_ifaddr *ifp)
{
atomic_dec(&ifp->refcnt);
}
static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
{
atomic_inc(&ifp->refcnt);
}
/*
* compute link-local solicited-node multicast address
*/
static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
struct in6_addr *solicited)
{
ipv6_addr_set(solicited,
htonl(0xFF020000), 0,
htonl(0x1),
htonl(0xFF000000) | addr->s6_addr32[3]);
}
static inline bool ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
__be64 *p = (__be64 *)addr;
return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(1))) == 0UL;
#else
return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
addr->s6_addr32[1] | addr->s6_addr32[2] |
(addr->s6_addr32[3] ^ htonl(0x00000001))) == 0;
#endif
}
static inline bool ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
__be64 *p = (__be64 *)addr;
return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | (p[1] ^ cpu_to_be64(2))) == 0UL;
#else
return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
addr->s6_addr32[1] | addr->s6_addr32[2] |
(addr->s6_addr32[3] ^ htonl(0x00000002))) == 0;
#endif
}
static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
{
return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
}
static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
__be64 *p = (__be64 *)addr;
return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) &
cpu_to_be64(0xffffffffff000000UL))) == 0UL;
#else
return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
addr->s6_addr32[1] |
(addr->s6_addr32[2] ^ htonl(0x00000001)) |
(addr->s6_addr[12] ^ 0xff)) == 0;
#endif
}
#ifdef CONFIG_PROC_FS
int if6_proc_init(void);
void if6_proc_exit(void);
#endif
#endif

View file

@ -0,0 +1,70 @@
/*
* IEEE 802.15.4 inteface for userspace
*
* Copyright 2007, 2008 Siemens AG
*
* 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.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
*/
#ifndef _AF_IEEE802154_H
#define _AF_IEEE802154_H
#include <linux/socket.h> /* for sa_family_t */
enum {
IEEE802154_ADDR_NONE = 0x0,
/* RESERVED = 0x01, */
IEEE802154_ADDR_SHORT = 0x2, /* 16-bit address + PANid */
IEEE802154_ADDR_LONG = 0x3, /* 64-bit address + PANid */
};
/* address length, octets */
#define IEEE802154_ADDR_LEN 8
struct ieee802154_addr_sa {
int addr_type;
u16 pan_id;
union {
u8 hwaddr[IEEE802154_ADDR_LEN];
u16 short_addr;
};
};
#define IEEE802154_PANID_BROADCAST 0xffff
#define IEEE802154_ADDR_BROADCAST 0xffff
#define IEEE802154_ADDR_UNDEF 0xfffe
struct sockaddr_ieee802154 {
sa_family_t family; /* AF_IEEE802154 */
struct ieee802154_addr_sa addr;
};
/* get/setsockopt */
#define SOL_IEEE802154 0
#define WPAN_WANTACK 0
#define WPAN_SECURITY 1
#define WPAN_SECURITY_LEVEL 2
#define WPAN_SECURITY_DEFAULT 0
#define WPAN_SECURITY_OFF 1
#define WPAN_SECURITY_ON 2
#define WPAN_SECURITY_LEVEL_DEFAULT (-1)
#endif

51
include/net/af_rxrpc.h Normal file
View file

@ -0,0 +1,51 @@
/* RxRPC kernel service interface definitions
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* 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.
*/
#ifndef _NET_RXRPC_H
#define _NET_RXRPC_H
#include <linux/rxrpc.h>
struct rxrpc_call;
/*
* the mark applied to socket buffers that may be intercepted
*/
enum {
RXRPC_SKB_MARK_DATA, /* data message */
RXRPC_SKB_MARK_FINAL_ACK, /* final ACK received message */
RXRPC_SKB_MARK_BUSY, /* server busy message */
RXRPC_SKB_MARK_REMOTE_ABORT, /* remote abort message */
RXRPC_SKB_MARK_NET_ERROR, /* network error message */
RXRPC_SKB_MARK_LOCAL_ERROR, /* local error message */
RXRPC_SKB_MARK_NEW_CALL, /* local error message */
};
typedef void (*rxrpc_interceptor_t)(struct sock *, unsigned long,
struct sk_buff *);
void rxrpc_kernel_intercept_rx_messages(struct socket *, rxrpc_interceptor_t);
struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
struct sockaddr_rxrpc *,
struct key *,
unsigned long,
gfp_t);
int rxrpc_kernel_send_data(struct rxrpc_call *, struct msghdr *, size_t);
void rxrpc_kernel_abort_call(struct rxrpc_call *, u32);
void rxrpc_kernel_end_call(struct rxrpc_call *);
bool rxrpc_kernel_is_data_last(struct sk_buff *);
u32 rxrpc_kernel_get_abort_code(struct sk_buff *);
int rxrpc_kernel_get_error_number(struct sk_buff *);
void rxrpc_kernel_data_delivered(struct sk_buff *);
void rxrpc_kernel_free_skb(struct sk_buff *);
struct rxrpc_call *rxrpc_kernel_accept_call(struct socket *, unsigned long);
int rxrpc_kernel_reject_call(struct socket *);
#endif /* _NET_RXRPC_H */

82
include/net/af_unix.h Normal file
View file

@ -0,0 +1,82 @@
#ifndef __LINUX_NET_AFUNIX_H
#define __LINUX_NET_AFUNIX_H
#include <linux/socket.h>
#include <linux/un.h>
#include <linux/mutex.h>
#include <net/sock.h>
void unix_inflight(struct file *fp);
void unix_notinflight(struct file *fp);
void unix_gc(void);
void wait_for_unix_gc(void);
struct sock *unix_get_socket(struct file *filp);
struct sock *unix_peer_get(struct sock *);
#define UNIX_HASH_SIZE 256
#define UNIX_HASH_BITS 8
extern unsigned int unix_tot_inflight;
extern spinlock_t unix_table_lock;
extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
struct unix_address {
atomic_t refcnt;
int len;
unsigned int hash;
struct sockaddr_un name[0];
};
struct unix_skb_parms {
struct pid *pid; /* Skb credentials */
kuid_t uid;
kgid_t gid;
struct scm_fp_list *fp; /* Passed files */
#ifdef CONFIG_SECURITY_NETWORK
u32 secid; /* Security ID */
#endif
u32 consumed;
};
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
#define UNIXSID(skb) (&UNIXCB((skb)).secid)
#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
#define unix_state_lock_nested(s) \
spin_lock_nested(&unix_sk(s)->lock, \
SINGLE_DEPTH_NESTING)
/* The AF_UNIX socket */
struct unix_sock {
/* WARNING: sk has to be the first member */
struct sock sk;
struct unix_address *addr;
struct path path;
struct mutex readlock;
struct sock *peer;
struct list_head link;
atomic_long_t inflight;
spinlock_t lock;
unsigned char recursion_level;
unsigned long gc_flags;
#define UNIX_GC_CANDIDATE 0
#define UNIX_GC_MAYBE_CYCLE 1
struct socket_wq peer_wq;
wait_queue_t peer_wake;
};
#define unix_sk(__sk) ((struct unix_sock *)__sk)
#define peer_wait peer_wq.wait
long unix_inq_len(struct sock *sk);
long unix_outq_len(struct sock *sk);
#ifdef CONFIG_SYSCTL
int unix_sysctl_register(struct net *net);
void unix_sysctl_unregister(struct net *net);
#else
static inline int unix_sysctl_register(struct net *net) { return 0; }
static inline void unix_sysctl_unregister(struct net *net) {}
#endif
#endif

179
include/net/af_vsock.h Normal file
View file

@ -0,0 +1,179 @@
/*
* VMware vSockets Driver
*
* Copyright (C) 2007-2013 VMware, Inc. All rights reserved.
*
* 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 version 2 and no 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.
*/
#ifndef __AF_VSOCK_H__
#define __AF_VSOCK_H__
#include <linux/kernel.h>
#include <linux/workqueue.h>
#include <linux/vm_sockets.h>
#include "vsock_addr.h"
#define LAST_RESERVED_PORT 1023
#define vsock_sk(__sk) ((struct vsock_sock *)__sk)
#define sk_vsock(__vsk) (&(__vsk)->sk)
struct vsock_sock {
/* sk must be the first member. */
struct sock sk;
struct sockaddr_vm local_addr;
struct sockaddr_vm remote_addr;
/* Links for the global tables of bound and connected sockets. */
struct list_head bound_table;
struct list_head connected_table;
/* Accessed without the socket lock held. This means it can never be
* modified outsided of socket create or destruct.
*/
bool trusted;
bool cached_peer_allow_dgram; /* Dgram communication allowed to
* cached peer?
*/
u32 cached_peer; /* Context ID of last dgram destination check. */
const struct cred *owner;
/* Rest are SOCK_STREAM only. */
long connect_timeout;
/* Listening socket that this came from. */
struct sock *listener;
/* Used for pending list and accept queue during connection handshake.
* The listening socket is the head for both lists. Sockets created
* for connection requests are placed in the pending list until they
* are connected, at which point they are put in the accept queue list
* so they can be accepted in accept(). If accept() cannot accept the
* connection, it is marked as rejected so the cleanup function knows
* to clean up the socket.
*/
struct list_head pending_links;
struct list_head accept_queue;
bool rejected;
struct delayed_work dwork;
u32 peer_shutdown;
bool sent_request;
bool ignore_connecting_rst;
/* Private to transport. */
void *trans;
};
s64 vsock_stream_has_data(struct vsock_sock *vsk);
s64 vsock_stream_has_space(struct vsock_sock *vsk);
void vsock_pending_work(struct work_struct *work);
struct sock *__vsock_create(struct net *net,
struct socket *sock,
struct sock *parent,
gfp_t priority, unsigned short type);
/**** TRANSPORT ****/
struct vsock_transport_recv_notify_data {
u64 data1; /* Transport-defined. */
u64 data2; /* Transport-defined. */
bool notify_on_block;
};
struct vsock_transport_send_notify_data {
u64 data1; /* Transport-defined. */
u64 data2; /* Transport-defined. */
};
struct vsock_transport {
/* Initialize/tear-down socket. */
int (*init)(struct vsock_sock *, struct vsock_sock *);
void (*destruct)(struct vsock_sock *);
void (*release)(struct vsock_sock *);
/* Connections. */
int (*connect)(struct vsock_sock *);
/* DGRAM. */
int (*dgram_bind)(struct vsock_sock *, struct sockaddr_vm *);
int (*dgram_dequeue)(struct kiocb *kiocb, struct vsock_sock *vsk,
struct msghdr *msg, size_t len, int flags);
int (*dgram_enqueue)(struct vsock_sock *, struct sockaddr_vm *,
struct iovec *, size_t len);
bool (*dgram_allow)(u32 cid, u32 port);
/* STREAM. */
/* TODO: stream_bind() */
ssize_t (*stream_dequeue)(struct vsock_sock *, struct iovec *,
size_t len, int flags);
ssize_t (*stream_enqueue)(struct vsock_sock *, struct iovec *,
size_t len);
s64 (*stream_has_data)(struct vsock_sock *);
s64 (*stream_has_space)(struct vsock_sock *);
u64 (*stream_rcvhiwat)(struct vsock_sock *);
bool (*stream_is_active)(struct vsock_sock *);
bool (*stream_allow)(u32 cid, u32 port);
/* Notification. */
int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
int (*notify_poll_out)(struct vsock_sock *, size_t, bool *);
int (*notify_recv_init)(struct vsock_sock *, size_t,
struct vsock_transport_recv_notify_data *);
int (*notify_recv_pre_block)(struct vsock_sock *, size_t,
struct vsock_transport_recv_notify_data *);
int (*notify_recv_pre_dequeue)(struct vsock_sock *, size_t,
struct vsock_transport_recv_notify_data *);
int (*notify_recv_post_dequeue)(struct vsock_sock *, size_t,
ssize_t, bool, struct vsock_transport_recv_notify_data *);
int (*notify_send_init)(struct vsock_sock *,
struct vsock_transport_send_notify_data *);
int (*notify_send_pre_block)(struct vsock_sock *,
struct vsock_transport_send_notify_data *);
int (*notify_send_pre_enqueue)(struct vsock_sock *,
struct vsock_transport_send_notify_data *);
int (*notify_send_post_enqueue)(struct vsock_sock *, ssize_t,
struct vsock_transport_send_notify_data *);
/* Shutdown. */
int (*shutdown)(struct vsock_sock *, int);
/* Buffer sizes. */
void (*set_buffer_size)(struct vsock_sock *, u64);
void (*set_min_buffer_size)(struct vsock_sock *, u64);
void (*set_max_buffer_size)(struct vsock_sock *, u64);
u64 (*get_buffer_size)(struct vsock_sock *);
u64 (*get_min_buffer_size)(struct vsock_sock *);
u64 (*get_max_buffer_size)(struct vsock_sock *);
/* Addressing. */
u32 (*get_local_cid)(void);
};
/**** CORE ****/
int __vsock_core_init(const struct vsock_transport *t, struct module *owner);
static inline int vsock_core_init(const struct vsock_transport *t)
{
return __vsock_core_init(t, THIS_MODULE);
}
void vsock_core_exit(void);
/**** UTILS ****/
void vsock_release_pending(struct sock *pending);
void vsock_add_pending(struct sock *listener, struct sock *pending);
void vsock_remove_pending(struct sock *listener, struct sock *pending);
void vsock_enqueue_accept(struct sock *listener, struct sock *connected);
void vsock_insert_connected(struct vsock_sock *vsk);
void vsock_remove_bound(struct vsock_sock *vsk);
void vsock_remove_connected(struct vsock_sock *vsk);
struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
struct sockaddr_vm *dst);
void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
#endif /* __AF_VSOCK_H__ */

22
include/net/ah.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef _NET_AH_H
#define _NET_AH_H
#include <linux/skbuff.h>
struct crypto_ahash;
struct ah_data {
int icv_full_len;
int icv_trunc_len;
struct crypto_ahash *ahash;
};
struct ip_auth_hdr;
static inline struct ip_auth_hdr *ip_auth_hdr(const struct sk_buff *skb)
{
return (struct ip_auth_hdr *)skb_transport_header(skb);
}
#endif

66
include/net/arp.h Normal file
View file

@ -0,0 +1,66 @@
/* linux/net/inet/arp.h */
#ifndef _ARP_H
#define _ARP_H
#include <linux/if_arp.h>
#include <linux/hash.h>
#include <net/neighbour.h>
extern struct neigh_table arp_tbl;
static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd)
{
u32 val = key ^ hash32_ptr(dev);
return val * hash_rnd;
}
static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key)
{
struct neigh_hash_table *nht = rcu_dereference_bh(arp_tbl.nht);
struct neighbour *n;
u32 hash_val;
hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift);
for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
n != NULL;
n = rcu_dereference_bh(n->next)) {
if (n->dev == dev && *(u32 *)n->primary_key == key)
return n;
}
return NULL;
}
static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key)
{
struct neighbour *n;
rcu_read_lock_bh();
n = __ipv4_neigh_lookup_noref(dev, key);
if (n && !atomic_inc_not_zero(&n->refcnt))
n = NULL;
rcu_read_unlock_bh();
return n;
}
void arp_init(void);
int arp_find(unsigned char *haddr, struct sk_buff *skb);
int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
void arp_send(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw, const unsigned char *th);
int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
void arp_ifdown(struct net_device *dev);
struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw,
const unsigned char *target_hw);
void arp_xmit(struct sk_buff *skb);
#endif /* _ARP_H */

52
include/net/atmclip.h Normal file
View file

@ -0,0 +1,52 @@
/* net/atm/atmarp.h - RFC1577 ATM ARP */
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
#ifndef _ATMCLIP_H
#define _ATMCLIP_H
#include <linux/netdevice.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmarp.h>
#include <linux/spinlock.h>
#include <net/neighbour.h>
#define CLIP_VCC(vcc) ((struct clip_vcc *) ((vcc)->user_back))
struct sk_buff;
struct clip_vcc {
struct atm_vcc *vcc; /* VCC descriptor */
struct atmarp_entry *entry; /* ATMARP table entry, NULL if IP addr.
isn't known yet */
int xoff; /* 1 if send buffer is full */
unsigned char encap; /* 0: NULL, 1: LLC/SNAP */
unsigned long last_use; /* last send or receive operation */
unsigned long idle_timeout; /* keep open idle for so many jiffies*/
void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
/* keep old push fn for chaining */
void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb);
/* keep old pop fn for chaining */
struct clip_vcc *next; /* next VCC */
};
struct atmarp_entry {
struct clip_vcc *vccs; /* active VCCs; NULL if resolution is
pending */
unsigned long expires; /* entry expiration time */
struct neighbour *neigh; /* neighbour back-pointer */
};
#define PRIV(dev) ((struct clip_priv *) netdev_priv(dev))
struct clip_priv {
int number; /* for convenience ... */
spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */
struct net_device *next; /* next CLIP interface */
};
#endif

454
include/net/ax25.h Normal file
View file

@ -0,0 +1,454 @@
/*
* Declarations of AX.25 type objects.
*
* Alan Cox (GW4PTS) 10/11/93
*/
#ifndef _AX25_H
#define _AX25_H
#include <linux/ax25.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/atomic.h>
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ)
#define AX25_BPQ_HEADER_LEN 16
#define AX25_KISS_HEADER_LEN 1
#define AX25_HEADER_LEN 17
#define AX25_ADDR_LEN 7
#define AX25_DIGI_HEADER_LEN (AX25_MAX_DIGIS * AX25_ADDR_LEN)
#define AX25_MAX_HEADER_LEN (AX25_HEADER_LEN + AX25_DIGI_HEADER_LEN)
/* AX.25 Protocol IDs */
#define AX25_P_ROSE 0x01
#define AX25_P_VJCOMP 0x06 /* Compressed TCP/IP packet */
/* Van Jacobsen (RFC 1144) */
#define AX25_P_VJUNCOMP 0x07 /* Uncompressed TCP/IP packet */
/* Van Jacobsen (RFC 1144) */
#define AX25_P_SEGMENT 0x08 /* Segmentation fragment */
#define AX25_P_TEXNET 0xc3 /* TEXTNET datagram protocol */
#define AX25_P_LQ 0xc4 /* Link Quality Protocol */
#define AX25_P_ATALK 0xca /* Appletalk */
#define AX25_P_ATALK_ARP 0xcb /* Appletalk ARP */
#define AX25_P_IP 0xcc /* ARPA Internet Protocol */
#define AX25_P_ARP 0xcd /* ARPA Address Resolution */
#define AX25_P_FLEXNET 0xce /* FlexNet */
#define AX25_P_NETROM 0xcf /* NET/ROM */
#define AX25_P_TEXT 0xF0 /* No layer 3 protocol impl. */
/* AX.25 Segment control values */
#define AX25_SEG_REM 0x7F
#define AX25_SEG_FIRST 0x80
#define AX25_CBIT 0x80 /* Command/Response bit */
#define AX25_EBIT 0x01 /* HDLC Address Extension bit */
#define AX25_HBIT 0x80 /* Has been repeated bit */
#define AX25_SSSID_SPARE 0x60 /* Unused bits in SSID for standard AX.25 */
#define AX25_ESSID_SPARE 0x20 /* Unused bits in SSID for extended AX.25 */
#define AX25_DAMA_FLAG 0x20 /* Well, it is *NOT* unused! (dl1bke 951121 */
#define AX25_COND_ACK_PENDING 0x01
#define AX25_COND_REJECT 0x02
#define AX25_COND_PEER_RX_BUSY 0x04
#define AX25_COND_OWN_RX_BUSY 0x08
#define AX25_COND_DAMA_MODE 0x10
#ifndef _LINUX_NETDEVICE_H
#include <linux/netdevice.h>
#endif
/* Upper sub-layer (LAPB) definitions */
/* Control field templates */
#define AX25_I 0x00 /* Information frames */
#define AX25_S 0x01 /* Supervisory frames */
#define AX25_RR 0x01 /* Receiver ready */
#define AX25_RNR 0x05 /* Receiver not ready */
#define AX25_REJ 0x09 /* Reject */
#define AX25_U 0x03 /* Unnumbered frames */
#define AX25_SABM 0x2f /* Set Asynchronous Balanced Mode */
#define AX25_SABME 0x6f /* Set Asynchronous Balanced Mode Extended */
#define AX25_DISC 0x43 /* Disconnect */
#define AX25_DM 0x0f /* Disconnected mode */
#define AX25_UA 0x63 /* Unnumbered acknowledge */
#define AX25_FRMR 0x87 /* Frame reject */
#define AX25_UI 0x03 /* Unnumbered information */
#define AX25_XID 0xaf /* Exchange information */
#define AX25_TEST 0xe3 /* Test */
#define AX25_PF 0x10 /* Poll/final bit for standard AX.25 */
#define AX25_EPF 0x01 /* Poll/final bit for extended AX.25 */
#define AX25_ILLEGAL 0x100 /* Impossible to be a real frame type */
#define AX25_POLLOFF 0
#define AX25_POLLON 1
/* AX25 L2 C-bit */
#define AX25_COMMAND 1
#define AX25_RESPONSE 2
/* Define Link State constants. */
enum {
AX25_STATE_0, /* Listening */
AX25_STATE_1, /* SABM sent */
AX25_STATE_2, /* DISC sent */
AX25_STATE_3, /* Established */
AX25_STATE_4 /* Recovery */
};
#define AX25_MODULUS 8 /* Standard AX.25 modulus */
#define AX25_EMODULUS 128 /* Extended AX.25 modulus */
enum {
AX25_PROTO_STD_SIMPLEX,
AX25_PROTO_STD_DUPLEX,
#ifdef CONFIG_AX25_DAMA_SLAVE
AX25_PROTO_DAMA_SLAVE,
#ifdef CONFIG_AX25_DAMA_MASTER
AX25_PROTO_DAMA_MASTER,
#define AX25_PROTO_MAX AX25_PROTO_DAMA_MASTER
#endif
#endif
__AX25_PROTO_MAX,
AX25_PROTO_MAX = __AX25_PROTO_MAX -1
};
enum {
AX25_VALUES_IPDEFMODE, /* 0=DG 1=VC */
AX25_VALUES_AXDEFMODE, /* 0=Normal 1=Extended Seq Nos */
AX25_VALUES_BACKOFF, /* 0=None 1=Linear 2=Exponential */
AX25_VALUES_CONMODE, /* Allow connected modes - 0=No 1=no "PID text" 2=all PIDs */
AX25_VALUES_WINDOW, /* Default window size for standard AX.25 */
AX25_VALUES_EWINDOW, /* Default window size for extended AX.25 */
AX25_VALUES_T1, /* Default T1 timeout value */
AX25_VALUES_T2, /* Default T2 timeout value */
AX25_VALUES_T3, /* Default T3 timeout value */
AX25_VALUES_IDLE, /* Connected mode idle timer */
AX25_VALUES_N2, /* Default N2 value */
AX25_VALUES_PACLEN, /* AX.25 MTU */
AX25_VALUES_PROTOCOL, /* Std AX.25, DAMA Slave, DAMA Master */
AX25_VALUES_DS_TIMEOUT, /* DAMA Slave timeout */
AX25_MAX_VALUES /* THIS MUST REMAIN THE LAST ENTRY OF THIS LIST */
};
#define AX25_DEF_IPDEFMODE 0 /* Datagram */
#define AX25_DEF_AXDEFMODE 0 /* Normal */
#define AX25_DEF_BACKOFF 1 /* Linear backoff */
#define AX25_DEF_CONMODE 2 /* Connected mode allowed */
#define AX25_DEF_WINDOW 2 /* Window=2 */
#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */
#define AX25_DEF_T1 10000 /* T1=10s */
#define AX25_DEF_T2 3000 /* T2=3s */
#define AX25_DEF_T3 300000 /* T3=300s */
#define AX25_DEF_N2 10 /* N2=10 */
#define AX25_DEF_IDLE 0 /* Idle=None */
#define AX25_DEF_PACLEN 256 /* Paclen=256 */
#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */
#define AX25_DEF_DS_TIMEOUT 180000 /* DAMA timeout 3 minutes */
typedef struct ax25_uid_assoc {
struct hlist_node uid_node;
atomic_t refcount;
kuid_t uid;
ax25_address call;
} ax25_uid_assoc;
#define ax25_uid_for_each(__ax25, list) \
hlist_for_each_entry(__ax25, list, uid_node)
#define ax25_uid_hold(ax25) \
atomic_inc(&((ax25)->refcount))
static inline void ax25_uid_put(ax25_uid_assoc *assoc)
{
if (atomic_dec_and_test(&assoc->refcount)) {
kfree(assoc);
}
}
typedef struct {
ax25_address calls[AX25_MAX_DIGIS];
unsigned char repeated[AX25_MAX_DIGIS];
unsigned char ndigi;
signed char lastrepeat;
} ax25_digi;
typedef struct ax25_route {
struct ax25_route *next;
atomic_t refcount;
ax25_address callsign;
struct net_device *dev;
ax25_digi *digipeat;
char ip_mode;
} ax25_route;
static inline void ax25_hold_route(ax25_route *ax25_rt)
{
atomic_inc(&ax25_rt->refcount);
}
void __ax25_put_route(ax25_route *ax25_rt);
static inline void ax25_put_route(ax25_route *ax25_rt)
{
if (atomic_dec_and_test(&ax25_rt->refcount))
__ax25_put_route(ax25_rt);
}
typedef struct {
char slave; /* slave_mode? */
struct timer_list slave_timer; /* timeout timer */
unsigned short slave_timeout; /* when? */
} ax25_dama_info;
struct ctl_table;
typedef struct ax25_dev {
struct ax25_dev *next;
struct net_device *dev;
struct net_device *forward;
struct ctl_table_header *sysheader;
int values[AX25_MAX_VALUES];
#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
ax25_dama_info dama;
#endif
} ax25_dev;
typedef struct ax25_cb {
struct hlist_node ax25_node;
ax25_address source_addr, dest_addr;
ax25_digi *digipeat;
ax25_dev *ax25_dev;
unsigned char iamdigi;
unsigned char state, modulus, pidincl;
unsigned short vs, vr, va;
unsigned char condition, backoff;
unsigned char n2, n2count;
struct timer_list t1timer, t2timer, t3timer, idletimer;
unsigned long t1, t2, t3, idle, rtt;
unsigned short paclen, fragno, fraglen;
struct sk_buff_head write_queue;
struct sk_buff_head reseq_queue;
struct sk_buff_head ack_queue;
struct sk_buff_head frag_queue;
unsigned char window;
struct timer_list timer, dtimer;
struct sock *sk; /* Backlink to socket */
atomic_t refcount;
} ax25_cb;
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->sk_protinfo)
#define ax25_for_each(__ax25, list) \
hlist_for_each_entry(__ax25, list, ax25_node)
#define ax25_cb_hold(__ax25) \
atomic_inc(&((__ax25)->refcount))
static __inline__ void ax25_cb_put(ax25_cb *ax25)
{
if (atomic_dec_and_test(&ax25->refcount)) {
kfree(ax25->digipeat);
kfree(ax25);
}
}
static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->dev = dev;
skb_reset_mac_header(skb);
skb->pkt_type = PACKET_HOST;
return htons(ETH_P_AX25);
}
/* af_ax25.c */
extern struct hlist_head ax25_list;
extern spinlock_t ax25_list_lock;
void ax25_cb_add(ax25_cb *);
struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *,
struct net_device *);
void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
void ax25_destroy_socket(ax25_cb *);
ax25_cb * __must_check ax25_create_cb(void);
void ax25_fillin_cb(ax25_cb *, ax25_dev *);
struct sock *ax25_make_new(struct sock *, struct ax25_dev *);
/* ax25_addr.c */
extern const ax25_address ax25_bcast;
extern const ax25_address ax25_defaddr;
extern const ax25_address null_ax25_address;
char *ax2asc(char *buf, const ax25_address *);
void asc2ax(ax25_address *addr, const char *callsign);
int ax25cmp(const ax25_address *, const ax25_address *);
int ax25digicmp(const ax25_digi *, const ax25_digi *);
const unsigned char *ax25_addr_parse(const unsigned char *, int,
ax25_address *, ax25_address *, ax25_digi *, int *, int *);
int ax25_addr_build(unsigned char *, const ax25_address *,
const ax25_address *, const ax25_digi *, int, int);
int ax25_addr_size(const ax25_digi *);
void ax25_digi_invert(const ax25_digi *, ax25_digi *);
/* ax25_dev.c */
extern ax25_dev *ax25_dev_list;
extern spinlock_t ax25_dev_lock;
static inline ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
{
return dev->ax25_ptr;
}
ax25_dev *ax25_addr_ax25dev(ax25_address *);
void ax25_dev_device_up(struct net_device *);
void ax25_dev_device_down(struct net_device *);
int ax25_fwd_ioctl(unsigned int, struct ax25_fwd_struct *);
struct net_device *ax25_fwd_dev(struct net_device *);
void ax25_dev_free(void);
/* ax25_ds_in.c */
int ax25_ds_frame_in(ax25_cb *, struct sk_buff *, int);
/* ax25_ds_subr.c */
void ax25_ds_nr_error_recovery(ax25_cb *);
void ax25_ds_enquiry_response(ax25_cb *);
void ax25_ds_establish_data_link(ax25_cb *);
void ax25_dev_dama_off(ax25_dev *);
void ax25_dama_on(ax25_cb *);
void ax25_dama_off(ax25_cb *);
/* ax25_ds_timer.c */
void ax25_ds_setup_timer(ax25_dev *);
void ax25_ds_set_timer(ax25_dev *);
void ax25_ds_del_timer(ax25_dev *);
void ax25_ds_timer(ax25_cb *);
void ax25_ds_t1_timeout(ax25_cb *);
void ax25_ds_heartbeat_expiry(ax25_cb *);
void ax25_ds_t3timer_expiry(ax25_cb *);
void ax25_ds_idletimer_expiry(ax25_cb *);
/* ax25_iface.c */
struct ax25_protocol {
struct ax25_protocol *next;
unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *);
};
void ax25_register_pid(struct ax25_protocol *ap);
void ax25_protocol_release(unsigned int);
struct ax25_linkfail {
struct hlist_node lf_node;
void (*func)(ax25_cb *, int);
};
void ax25_linkfail_register(struct ax25_linkfail *lf);
void ax25_linkfail_release(struct ax25_linkfail *lf);
int __must_check ax25_listen_register(ax25_address *, struct net_device *);
void ax25_listen_release(ax25_address *, struct net_device *);
int(*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *);
int ax25_listen_mine(ax25_address *, struct net_device *);
void ax25_link_failed(ax25_cb *, int);
int ax25_protocol_is_registered(unsigned int);
/* ax25_in.c */
int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *,
struct net_device *);
/* ax25_ip.c */
int ax25_hard_header(struct sk_buff *, struct net_device *, unsigned short,
const void *, const void *, unsigned int);
int ax25_rebuild_header(struct sk_buff *);
extern const struct header_ops ax25_header_ops;
/* ax25_out.c */
ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *,
ax25_digi *, struct net_device *);
void ax25_output(ax25_cb *, int, struct sk_buff *);
void ax25_kick(ax25_cb *);
void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);
int ax25_check_iframes_acked(ax25_cb *, unsigned short);
/* ax25_route.c */
void ax25_rt_device_down(struct net_device *);
int ax25_rt_ioctl(unsigned int, void __user *);
extern const struct file_operations ax25_route_fops;
ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
int ax25_rt_autobind(ax25_cb *, ax25_address *);
struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *,
ax25_address *, ax25_digi *);
void ax25_rt_free(void);
/* ax25_std_in.c */
int ax25_std_frame_in(ax25_cb *, struct sk_buff *, int);
/* ax25_std_subr.c */
void ax25_std_nr_error_recovery(ax25_cb *);
void ax25_std_establish_data_link(ax25_cb *);
void ax25_std_transmit_enquiry(ax25_cb *);
void ax25_std_enquiry_response(ax25_cb *);
void ax25_std_timeout_response(ax25_cb *);
/* ax25_std_timer.c */
void ax25_std_heartbeat_expiry(ax25_cb *);
void ax25_std_t1timer_expiry(ax25_cb *);
void ax25_std_t2timer_expiry(ax25_cb *);
void ax25_std_t3timer_expiry(ax25_cb *);
void ax25_std_idletimer_expiry(ax25_cb *);
/* ax25_subr.c */
void ax25_clear_queues(ax25_cb *);
void ax25_frames_acked(ax25_cb *, unsigned short);
void ax25_requeue_frames(ax25_cb *);
int ax25_validate_nr(ax25_cb *, unsigned short);
int ax25_decode(ax25_cb *, struct sk_buff *, int *, int *, int *);
void ax25_send_control(ax25_cb *, int, int, int);
void ax25_return_dm(struct net_device *, ax25_address *, ax25_address *,
ax25_digi *);
void ax25_calculate_t1(ax25_cb *);
void ax25_calculate_rtt(ax25_cb *);
void ax25_disconnect(ax25_cb *, int);
/* ax25_timer.c */
void ax25_setup_timers(ax25_cb *);
void ax25_start_heartbeat(ax25_cb *);
void ax25_start_t1timer(ax25_cb *);
void ax25_start_t2timer(ax25_cb *);
void ax25_start_t3timer(ax25_cb *);
void ax25_start_idletimer(ax25_cb *);
void ax25_stop_heartbeat(ax25_cb *);
void ax25_stop_t1timer(ax25_cb *);
void ax25_stop_t2timer(ax25_cb *);
void ax25_stop_t3timer(ax25_cb *);
void ax25_stop_idletimer(ax25_cb *);
int ax25_t1timer_running(ax25_cb *);
unsigned long ax25_display_timer(struct timer_list *);
/* ax25_uid.c */
extern int ax25_uid_policy;
ax25_uid_assoc *ax25_findbyuid(kuid_t);
int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
extern const struct file_operations ax25_uid_fops;
void ax25_uid_free(void);
/* sysctl_net_ax25.c */
#ifdef CONFIG_SYSCTL
int ax25_register_dev_sysctl(ax25_dev *ax25_dev);
void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev);
#else
static inline int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { return 0; }
static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {}
#endif /* CONFIG_SYSCTL */
#endif

31
include/net/ax88796.h Normal file
View file

@ -0,0 +1,31 @@
/* include/net/ax88796.h
*
* Copyright 2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* 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.
*
*/
#ifndef __NET_AX88796_PLAT_H
#define __NET_AX88796_PLAT_H
#define AXFLG_HAS_EEPROM (1<<0)
#define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */
#define AXFLG_HAS_93CX6 (1<<2) /* use eeprom_93cx6 driver */
#define AXFLG_MAC_FROMPLATFORM (1<<3) /* MAC given by platform data */
struct ax_plat_data {
unsigned int flags;
unsigned char wordlength; /* 1 or 2 */
unsigned char dcr_val; /* default value for DCR */
unsigned char rcr_val; /* default value for RCR */
unsigned char gpoc_val; /* default value for GPOC */
u32 *reg_offsets; /* register offsets */
u8 *mac_addr; /* MAC addr (only used when
AXFLG_MAC_FROMPLATFORM is used */
};
#endif /* __NET_AX88796_PLAT_H */

View file

@ -0,0 +1,363 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __BLUETOOTH_H
#define __BLUETOOTH_H
#include <linux/poll.h>
#include <net/sock.h>
#include <linux/seq_file.h>
#ifndef AF_BLUETOOTH
#define AF_BLUETOOTH 31
#define PF_BLUETOOTH AF_BLUETOOTH
#endif
/* Bluetooth versions */
#define BLUETOOTH_VER_1_1 1
#define BLUETOOTH_VER_1_2 2
#define BLUETOOTH_VER_2_0 3
/* Reserv for core and drivers use */
#define BT_SKB_RESERVE 8
#define BTPROTO_L2CAP 0
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define BTPROTO_RFCOMM 3
#define BTPROTO_BNEP 4
#define BTPROTO_CMTP 5
#define BTPROTO_HIDP 6
#define BTPROTO_AVDTP 7
#define SOL_HCI 0
#define SOL_L2CAP 6
#define SOL_SCO 17
#define SOL_RFCOMM 18
#define BT_SECURITY 4
struct bt_security {
__u8 level;
__u8 key_size;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3
#define BT_SECURITY_FIPS 4
#define BT_DEFER_SETUP 7
#define BT_FLUSHABLE 8
#define BT_FLUSHABLE_OFF 0
#define BT_FLUSHABLE_ON 1
#define BT_POWER 9
struct bt_power {
__u8 force_active;
};
#define BT_POWER_FORCE_ACTIVE_OFF 0
#define BT_POWER_FORCE_ACTIVE_ON 1
#define BT_CHANNEL_POLICY 10
/* BR/EDR only (default policy)
* AMP controllers cannot be used.
* Channel move requests from the remote device are denied.
* If the L2CAP channel is currently using AMP, move the channel to BR/EDR.
*/
#define BT_CHANNEL_POLICY_BREDR_ONLY 0
/* BR/EDR Preferred
* Allow use of AMP controllers.
* If the L2CAP channel is currently on AMP, move it to BR/EDR.
* Channel move requests from the remote device are allowed.
*/
#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1
/* AMP Preferred
* Allow use of AMP controllers
* If the L2CAP channel is currently on BR/EDR and AMP controller
* resources are available, initiate a channel move to AMP.
* Channel move requests from the remote device are allowed.
* If the L2CAP socket has not been connected yet, try to create
* and configure the channel directly on an AMP controller rather
* than BR/EDR.
*/
#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
#define BT_VOICE 11
struct bt_voice {
__u16 setting;
};
#define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060
#define BT_SNDMTU 12
#define BT_RCVMTU 13
__printf(1, 2)
void bt_info(const char *fmt, ...);
__printf(1, 2)
void bt_err(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
/* Connection and socket states */
enum {
BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
BT_OPEN,
BT_BOUND,
BT_LISTEN,
BT_CONNECT,
BT_CONNECT2,
BT_CONFIG,
BT_DISCONN,
BT_CLOSED
};
/* If unused will be removed by compiler */
static inline const char *state_to_string(int state)
{
switch (state) {
case BT_CONNECTED:
return "BT_CONNECTED";
case BT_OPEN:
return "BT_OPEN";
case BT_BOUND:
return "BT_BOUND";
case BT_LISTEN:
return "BT_LISTEN";
case BT_CONNECT:
return "BT_CONNECT";
case BT_CONNECT2:
return "BT_CONNECT2";
case BT_CONFIG:
return "BT_CONFIG";
case BT_DISCONN:
return "BT_DISCONN";
case BT_CLOSED:
return "BT_CLOSED";
}
return "invalid state";
}
/* BD Address */
typedef struct {
__u8 b[6];
} __packed bdaddr_t;
/* BD Address type */
#define BDADDR_BREDR 0x00
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
static inline bool bdaddr_type_is_valid(__u8 type)
{
switch (type) {
case BDADDR_BREDR:
case BDADDR_LE_PUBLIC:
case BDADDR_LE_RANDOM:
return true;
}
return false;
}
static inline bool bdaddr_type_is_le(__u8 type)
{
switch (type) {
case BDADDR_LE_PUBLIC:
case BDADDR_LE_RANDOM:
return true;
}
return false;
}
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_NONE (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
/* Copy, swap, convert BD Address */
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
}
void baswap(bdaddr_t *dst, bdaddr_t *src);
/* Common socket structures and functions */
#define bt_sk(__sk) ((struct bt_sock *) __sk)
struct bt_sock {
struct sock sk;
struct list_head accept_q;
struct sock *parent;
unsigned long flags;
void (*skb_msg_name)(struct sk_buff *, void *, int *);
};
enum {
BT_SK_DEFER_SETUP,
BT_SK_SUSPEND,
};
struct bt_sock_list {
struct hlist_head head;
rwlock_t lock;
#ifdef CONFIG_PROC_FS
int (* custom_seq_show)(struct seq_file *, void *);
#endif
};
int bt_sock_register(int proto, const struct net_proto_family *ops);
void bt_sock_unregister(int proto);
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
int bt_sock_wait_ready(struct sock *sk, unsigned long flags);
void bt_accept_enqueue(struct sock *parent, struct sock *sk);
void bt_accept_unlink(struct sock *sk);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
struct l2cap_ctrl {
__u8 sframe:1,
poll:1,
final:1,
fcs:1,
sar:2,
super:2;
__u16 reqseq;
__u16 txseq;
__u8 retries;
};
struct hci_dev;
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
struct hci_req_ctrl {
bool start;
u8 event;
hci_req_complete_t complete;
};
struct bt_skb_cb {
__u8 pkt_type;
__u8 incoming;
__u16 opcode;
__u16 expect;
__u8 force_active;
struct l2cap_chan *chan;
struct l2cap_ctrl control;
struct hci_req_ctrl req;
bdaddr_t bdaddr;
__le16 psm;
};
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
{
struct sk_buff *skb;
skb = alloc_skb(len + BT_SKB_RESERVE, how);
if (skb) {
skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0;
}
return skb;
}
static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
unsigned long len, int nb, int *err)
{
struct sk_buff *skb;
skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err);
if (skb) {
skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0;
}
if (!skb && *err)
return NULL;
*err = sock_error(sk);
if (*err)
goto out;
if (sk->sk_shutdown) {
*err = -ECONNRESET;
goto out;
}
return skb;
out:
kfree_skb(skb);
return NULL;
}
int bt_to_errno(__u16 code);
int hci_sock_init(void);
void hci_sock_cleanup(void);
int bt_sysfs_init(void);
void bt_sysfs_cleanup(void);
int bt_procfs_init(struct net *net, const char *name,
struct bt_sock_list *sk_list,
int (*seq_show)(struct seq_file *, void *));
void bt_procfs_cleanup(struct net *net, const char *name);
extern struct dentry *bt_debugfs;
int l2cap_init(void);
void l2cap_exit(void);
int sco_init(void);
void sco_exit(void);
void bt_sock_reclassify_lock(struct sock *sk, int proto);
#endif /* __BLUETOOTH_H */

1853
include/net/bluetooth/hci.h Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2011-2012 Intel Corporation
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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __HCI_MON_H
#define __HCI_MON_H
struct hci_mon_hdr {
__le16 opcode;
__le16 index;
__le16 len;
} __packed;
#define HCI_MON_HDR_SIZE 6
#define HCI_MON_NEW_INDEX 0
#define HCI_MON_DEL_INDEX 1
#define HCI_MON_COMMAND_PKT 2
#define HCI_MON_EVENT_PKT 3
#define HCI_MON_ACL_TX_PKT 4
#define HCI_MON_ACL_RX_PKT 5
#define HCI_MON_SCO_TX_PKT 6
#define HCI_MON_SCO_RX_PKT 7
struct hci_mon_new_index {
__u8 type;
__u8 bus;
bdaddr_t bdaddr;
char name[8];
} __packed;
#define HCI_MON_NEW_INDEX_SIZE 16
#endif /* __HCI_MON_H */

View file

@ -0,0 +1,175 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __HCI_SOCK_H
#define __HCI_SOCK_H
/* Socket options */
#define HCI_DATA_DIR 1
#define HCI_FILTER 2
#define HCI_TIME_STAMP 3
/* CMSG flags */
#define HCI_CMSG_DIR 0x0001
#define HCI_CMSG_TSTAMP 0x0002
struct sockaddr_hci {
sa_family_t hci_family;
unsigned short hci_dev;
unsigned short hci_channel;
};
#define HCI_DEV_NONE 0xffff
#define HCI_CHANNEL_RAW 0
#define HCI_CHANNEL_USER 1
#define HCI_CHANNEL_MONITOR 2
#define HCI_CHANNEL_CONTROL 3
struct hci_filter {
unsigned long type_mask;
unsigned long event_mask[2];
__le16 opcode;
};
struct hci_ufilter {
__u32 type_mask;
__u32 event_mask[2];
__le16 opcode;
};
#define HCI_FLT_TYPE_BITS 31
#define HCI_FLT_EVENT_BITS 63
#define HCI_FLT_OGF_BITS 63
#define HCI_FLT_OCF_BITS 127
/* Ioctl defines */
#define HCIDEVUP _IOW('H', 201, int)
#define HCIDEVDOWN _IOW('H', 202, int)
#define HCIDEVRESET _IOW('H', 203, int)
#define HCIDEVRESTAT _IOW('H', 204, int)
#define HCIGETDEVLIST _IOR('H', 210, int)
#define HCIGETDEVINFO _IOR('H', 211, int)
#define HCIGETCONNLIST _IOR('H', 212, int)
#define HCIGETCONNINFO _IOR('H', 213, int)
#define HCIGETAUTHINFO _IOR('H', 215, int)
#define HCISETRAW _IOW('H', 220, int)
#define HCISETSCAN _IOW('H', 221, int)
#define HCISETAUTH _IOW('H', 222, int)
#define HCISETENCRYPT _IOW('H', 223, int)
#define HCISETPTYPE _IOW('H', 224, int)
#define HCISETLINKPOL _IOW('H', 225, int)
#define HCISETLINKMODE _IOW('H', 226, int)
#define HCISETACLMTU _IOW('H', 227, int)
#define HCISETSCOMTU _IOW('H', 228, int)
#define HCIBLOCKADDR _IOW('H', 230, int)
#define HCIUNBLOCKADDR _IOW('H', 231, int)
#define HCIINQUIRY _IOR('H', 240, int)
/* Ioctl requests structures */
struct hci_dev_stats {
__u32 err_rx;
__u32 err_tx;
__u32 cmd_tx;
__u32 evt_rx;
__u32 acl_tx;
__u32 acl_rx;
__u32 sco_tx;
__u32 sco_rx;
__u32 byte_rx;
__u32 byte_tx;
};
struct hci_dev_info {
__u16 dev_id;
char name[8];
bdaddr_t bdaddr;
__u32 flags;
__u8 type;
__u8 features[8];
__u32 pkt_type;
__u32 link_policy;
__u32 link_mode;
__u16 acl_mtu;
__u16 acl_pkts;
__u16 sco_mtu;
__u16 sco_pkts;
struct hci_dev_stats stat;
};
struct hci_conn_info {
__u16 handle;
bdaddr_t bdaddr;
__u8 type;
__u8 out;
__u16 state;
__u32 link_mode;
};
struct hci_dev_req {
__u16 dev_id;
__u32 dev_opt;
};
struct hci_dev_list_req {
__u16 dev_num;
struct hci_dev_req dev_req[0]; /* hci_dev_req structures */
};
struct hci_conn_list_req {
__u16 dev_id;
__u16 conn_num;
struct hci_conn_info conn_info[0];
};
struct hci_conn_info_req {
bdaddr_t bdaddr;
__u8 type;
struct hci_conn_info conn_info[0];
};
struct hci_auth_info_req {
bdaddr_t bdaddr;
__u8 type;
};
struct hci_inquiry_req {
__u16 dev_id;
__u16 flags;
__u8 lap[3];
__u8 length;
__u8 num_rsp;
};
#define IREQ_CACHE_FLUSH 0x0001
#endif /* __HCI_SOCK_H */

View file

@ -0,0 +1,954 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __L2CAP_H
#define __L2CAP_H
#include <asm/unaligned.h>
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF
#define L2CAP_DEFAULT_TX_WINDOW 63
#define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF
#define L2CAP_DEFAULT_MAX_TX 3
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
#define L2CAP_DEFAULT_MAX_PDU_SIZE 1492 /* Sized for AMP packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
#define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF
#define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */
#define L2CAP_LE_MIN_MTU 23
#define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100)
#define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000)
#define L2CAP_ENC_TIMEOUT msecs_to_jiffies(5000)
#define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000)
#define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000)
#define L2CAP_MOVE_TIMEOUT msecs_to_jiffies(4000)
#define L2CAP_MOVE_ERTX_TIMEOUT msecs_to_jiffies(60000)
#define L2CAP_A2MP_DEFAULT_MTU 670
/* L2CAP socket address */
struct sockaddr_l2 {
sa_family_t l2_family;
__le16 l2_psm;
bdaddr_t l2_bdaddr;
__le16 l2_cid;
__u8 l2_bdaddr_type;
};
/* L2CAP socket options */
#define L2CAP_OPTIONS 0x01
struct l2cap_options {
__u16 omtu;
__u16 imtu;
__u16 flush_to;
__u8 mode;
__u8 fcs;
__u8 max_tx;
__u16 txwin_size;
};
#define L2CAP_CONNINFO 0x02
struct l2cap_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define L2CAP_LM 0x03
#define L2CAP_LM_MASTER 0x0001
#define L2CAP_LM_AUTH 0x0002
#define L2CAP_LM_ENCRYPT 0x0004
#define L2CAP_LM_TRUSTED 0x0008
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
#define L2CAP_LM_FIPS 0x0040
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
#define L2CAP_CONN_RSP 0x03
#define L2CAP_CONF_REQ 0x04
#define L2CAP_CONF_RSP 0x05
#define L2CAP_DISCONN_REQ 0x06
#define L2CAP_DISCONN_RSP 0x07
#define L2CAP_ECHO_REQ 0x08
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b
#define L2CAP_CREATE_CHAN_REQ 0x0c
#define L2CAP_CREATE_CHAN_RSP 0x0d
#define L2CAP_MOVE_CHAN_REQ 0x0e
#define L2CAP_MOVE_CHAN_RSP 0x0f
#define L2CAP_MOVE_CHAN_CFM 0x10
#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
#define L2CAP_LE_CONN_REQ 0x14
#define L2CAP_LE_CONN_RSP 0x15
#define L2CAP_LE_CREDITS 0x16
/* L2CAP extended feature mask */
#define L2CAP_FEAT_FLOWCTL 0x00000001
#define L2CAP_FEAT_RETRANS 0x00000002
#define L2CAP_FEAT_BIDIR_QOS 0x00000004
#define L2CAP_FEAT_ERTM 0x00000008
#define L2CAP_FEAT_STREAMING 0x00000010
#define L2CAP_FEAT_FCS 0x00000020
#define L2CAP_FEAT_EXT_FLOW 0x00000040
#define L2CAP_FEAT_FIXED_CHAN 0x00000080
#define L2CAP_FEAT_EXT_WINDOW 0x00000100
#define L2CAP_FEAT_UCD 0x00000200
/* L2CAP checksum option */
#define L2CAP_FCS_NONE 0x00
#define L2CAP_FCS_CRC16 0x01
/* L2CAP fixed channels */
#define L2CAP_FC_SIG_BREDR 0x02
#define L2CAP_FC_CONNLESS 0x04
#define L2CAP_FC_A2MP 0x08
#define L2CAP_FC_ATT 0x10
#define L2CAP_FC_SIG_LE 0x20
#define L2CAP_FC_SMP_LE 0x40
/* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR 0xC000
#define L2CAP_CTRL_REQSEQ 0x3F00
#define L2CAP_CTRL_TXSEQ 0x007E
#define L2CAP_CTRL_SUPERVISE 0x000C
#define L2CAP_CTRL_RETRANS 0x0080
#define L2CAP_CTRL_FINAL 0x0080
#define L2CAP_CTRL_POLL 0x0010
#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
#define L2CAP_CTRL_TXSEQ_SHIFT 1
#define L2CAP_CTRL_SUPER_SHIFT 2
#define L2CAP_CTRL_POLL_SHIFT 4
#define L2CAP_CTRL_FINAL_SHIFT 7
#define L2CAP_CTRL_REQSEQ_SHIFT 8
#define L2CAP_CTRL_SAR_SHIFT 14
/* L2CAP Extended Control Field bit mask */
#define L2CAP_EXT_CTRL_TXSEQ 0xFFFC0000
#define L2CAP_EXT_CTRL_SAR 0x00030000
#define L2CAP_EXT_CTRL_SUPERVISE 0x00030000
#define L2CAP_EXT_CTRL_REQSEQ 0x0000FFFC
#define L2CAP_EXT_CTRL_POLL 0x00040000
#define L2CAP_EXT_CTRL_FINAL 0x00000002
#define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */
#define L2CAP_EXT_CTRL_FINAL_SHIFT 1
#define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2
#define L2CAP_EXT_CTRL_SAR_SHIFT 16
#define L2CAP_EXT_CTRL_SUPER_SHIFT 16
#define L2CAP_EXT_CTRL_POLL_SHIFT 18
#define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18
/* L2CAP Supervisory Function */
#define L2CAP_SUPER_RR 0x00
#define L2CAP_SUPER_REJ 0x01
#define L2CAP_SUPER_RNR 0x02
#define L2CAP_SUPER_SREJ 0x03
/* L2CAP Segmentation and Reassembly */
#define L2CAP_SAR_UNSEGMENTED 0x00
#define L2CAP_SAR_START 0x01
#define L2CAP_SAR_END 0x02
#define L2CAP_SAR_CONTINUE 0x03
/* L2CAP Command rej. reasons */
#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
#define L2CAP_REJ_MTU_EXCEEDED 0x0001
#define L2CAP_REJ_INVALID_CID 0x0002
/* L2CAP structures */
struct l2cap_hdr {
__le16 len;
__le16 cid;
} __packed;
#define L2CAP_HDR_SIZE 4
#define L2CAP_ENH_HDR_SIZE 6
#define L2CAP_EXT_HDR_SIZE 8
#define L2CAP_FCS_SIZE 2
#define L2CAP_SDULEN_SIZE 2
#define L2CAP_PSMLEN_SIZE 2
#define L2CAP_ENH_CTRL_SIZE 2
#define L2CAP_EXT_CTRL_SIZE 4
struct l2cap_cmd_hdr {
__u8 code;
__u8 ident;
__le16 len;
} __packed;
#define L2CAP_CMD_HDR_SIZE 4
struct l2cap_cmd_rej_unk {
__le16 reason;
} __packed;
struct l2cap_cmd_rej_mtu {
__le16 reason;
__le16 max_mtu;
} __packed;
struct l2cap_cmd_rej_cid {
__le16 reason;
__le16 scid;
__le16 dcid;
} __packed;
struct l2cap_conn_req {
__le16 psm;
__le16 scid;
} __packed;
struct l2cap_conn_rsp {
__le16 dcid;
__le16 scid;
__le16 result;
__le16 status;
} __packed;
/* protocol/service multiplexer (PSM) */
#define L2CAP_PSM_SDP 0x0001
#define L2CAP_PSM_RFCOMM 0x0003
#define L2CAP_PSM_3DSP 0x0021
/* channel identifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
#define L2CAP_CID_A2MP 0x0003
#define L2CAP_CID_ATT 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
#define L2CAP_CID_LE_DYN_END 0x007f
/* connect/create channel results */
#define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001
#define L2CAP_CR_BAD_PSM 0x0002
#define L2CAP_CR_SEC_BLOCK 0x0003
#define L2CAP_CR_NO_MEM 0x0004
#define L2CAP_CR_BAD_AMP 0x0005
#define L2CAP_CR_AUTHENTICATION 0x0005
#define L2CAP_CR_AUTHORIZATION 0x0006
#define L2CAP_CR_BAD_KEY_SIZE 0x0007
#define L2CAP_CR_ENCRYPTION 0x0008
/* connect/create channel status */
#define L2CAP_CS_NO_INFO 0x0000
#define L2CAP_CS_AUTHEN_PEND 0x0001
#define L2CAP_CS_AUTHOR_PEND 0x0002
struct l2cap_conf_req {
__le16 dcid;
__le16 flags;
__u8 data[0];
} __packed;
struct l2cap_conf_rsp {
__le16 scid;
__le16 flags;
__le16 result;
__u8 data[0];
} __packed;
#define L2CAP_CONF_SUCCESS 0x0000
#define L2CAP_CONF_UNACCEPT 0x0001
#define L2CAP_CONF_REJECT 0x0002
#define L2CAP_CONF_UNKNOWN 0x0003
#define L2CAP_CONF_PENDING 0x0004
#define L2CAP_CONF_EFS_REJECT 0x0005
/* configuration req/rsp continuation flag */
#define L2CAP_CONF_FLAG_CONTINUATION 0x0001
struct l2cap_conf_opt {
__u8 type;
__u8 len;
__u8 val[0];
} __packed;
#define L2CAP_CONF_OPT_SIZE 2
#define L2CAP_CONF_HINT 0x80
#define L2CAP_CONF_MASK 0x7f
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
#define L2CAP_CONF_EFS 0x06
#define L2CAP_CONF_EWS 0x07
#define L2CAP_CONF_MAX_SIZE 22
struct l2cap_conf_rfc {
__u8 mode;
__u8 txwin_size;
__u8 max_transmit;
__le16 retrans_timeout;
__le16 monitor_timeout;
__le16 max_pdu_size;
} __packed;
#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAMING 0x04
/* Unlike the above this one doesn't actually map to anything that would
* ever be sent over the air. Therefore, use a value that's unlikely to
* ever be used in the BR/EDR configuration phase.
*/
#define L2CAP_MODE_LE_FLOWCTL 0x80
struct l2cap_conf_efs {
__u8 id;
__u8 stype;
__le16 msdu;
__le32 sdu_itime;
__le32 acc_lat;
__le32 flush_to;
} __packed;
#define L2CAP_SERV_NOTRAFIC 0x00
#define L2CAP_SERV_BESTEFFORT 0x01
#define L2CAP_SERV_GUARANTEED 0x02
#define L2CAP_BESTEFFORT_ID 0x01
struct l2cap_disconn_req {
__le16 dcid;
__le16 scid;
} __packed;
struct l2cap_disconn_rsp {
__le16 dcid;
__le16 scid;
} __packed;
struct l2cap_info_req {
__le16 type;
} __packed;
struct l2cap_info_rsp {
__le16 type;
__le16 result;
__u8 data[0];
} __packed;
struct l2cap_create_chan_req {
__le16 psm;
__le16 scid;
__u8 amp_id;
} __packed;
struct l2cap_create_chan_rsp {
__le16 dcid;
__le16 scid;
__le16 result;
__le16 status;
} __packed;
struct l2cap_move_chan_req {
__le16 icid;
__u8 dest_amp_id;
} __packed;
struct l2cap_move_chan_rsp {
__le16 icid;
__le16 result;
} __packed;
#define L2CAP_MR_SUCCESS 0x0000
#define L2CAP_MR_PEND 0x0001
#define L2CAP_MR_BAD_ID 0x0002
#define L2CAP_MR_SAME_ID 0x0003
#define L2CAP_MR_NOT_SUPP 0x0004
#define L2CAP_MR_COLLISION 0x0005
#define L2CAP_MR_NOT_ALLOWED 0x0006
struct l2cap_move_chan_cfm {
__le16 icid;
__le16 result;
} __packed;
#define L2CAP_MC_CONFIRMED 0x0000
#define L2CAP_MC_UNCONFIRMED 0x0001
struct l2cap_move_chan_cfm_rsp {
__le16 icid;
} __packed;
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
#define L2CAP_IT_FEAT_MASK 0x0002
#define L2CAP_IT_FIXED_CHAN 0x0003
/* info result */
#define L2CAP_IR_SUCCESS 0x0000
#define L2CAP_IR_NOTSUPP 0x0001
struct l2cap_conn_param_update_req {
__le16 min;
__le16 max;
__le16 latency;
__le16 to_multiplier;
} __packed;
struct l2cap_conn_param_update_rsp {
__le16 result;
} __packed;
/* Connection Parameters result */
#define L2CAP_CONN_PARAM_ACCEPTED 0x0000
#define L2CAP_CONN_PARAM_REJECTED 0x0001
#define L2CAP_LE_MAX_CREDITS 10
#define L2CAP_LE_DEFAULT_MPS 230
struct l2cap_le_conn_req {
__le16 psm;
__le16 scid;
__le16 mtu;
__le16 mps;
__le16 credits;
} __packed;
struct l2cap_le_conn_rsp {
__le16 dcid;
__le16 mtu;
__le16 mps;
__le16 credits;
__le16 result;
} __packed;
struct l2cap_le_credits {
__le16 cid;
__le16 credits;
} __packed;
/* ----- L2CAP channels and connections ----- */
struct l2cap_seq_list {
__u16 head;
__u16 tail;
__u16 mask;
__u16 *list;
};
#define L2CAP_SEQ_LIST_CLEAR 0xFFFF
#define L2CAP_SEQ_LIST_TAIL 0x8000
struct l2cap_chan {
struct l2cap_conn *conn;
struct hci_conn *hs_hcon;
struct hci_chan *hs_hchan;
struct kref kref;
__u8 state;
bdaddr_t dst;
__u8 dst_type;
bdaddr_t src;
__u8 src_type;
__le16 psm;
__le16 sport;
__u16 dcid;
__u16 scid;
__u16 imtu;
__u16 omtu;
__u16 flush_to;
__u8 mode;
__u8 chan_type;
__u8 chan_policy;
__u8 sec_level;
__u8 ident;
__u8 conf_req[64];
__u8 conf_len;
__u8 num_conf_req;
__u8 num_conf_rsp;
__u8 fcs;
__u16 tx_win;
__u16 tx_win_max;
__u16 ack_win;
__u8 max_tx;
__u16 retrans_timeout;
__u16 monitor_timeout;
__u16 mps;
__u16 tx_credits;
__u16 rx_credits;
__u8 tx_state;
__u8 rx_state;
unsigned long conf_state;
unsigned long conn_state;
unsigned long flags;
__u8 remote_amp_id;
__u8 local_amp_id;
__u8 move_id;
__u8 move_state;
__u8 move_role;
__u16 next_tx_seq;
__u16 expected_ack_seq;
__u16 expected_tx_seq;
__u16 buffer_seq;
__u16 srej_save_reqseq;
__u16 last_acked_seq;
__u16 frames_sent;
__u16 unacked_frames;
__u8 retry_count;
__u16 sdu_len;
struct sk_buff *sdu;
struct sk_buff *sdu_last_frag;
__u16 remote_tx_win;
__u8 remote_max_tx;
__u16 remote_mps;
__u8 local_id;
__u8 local_stype;
__u16 local_msdu;
__u32 local_sdu_itime;
__u32 local_acc_lat;
__u32 local_flush_to;
__u8 remote_id;
__u8 remote_stype;
__u16 remote_msdu;
__u32 remote_sdu_itime;
__u32 remote_acc_lat;
__u32 remote_flush_to;
struct delayed_work chan_timer;
struct delayed_work retrans_timer;
struct delayed_work monitor_timer;
struct delayed_work ack_timer;
struct sk_buff *tx_send_head;
struct sk_buff_head tx_q;
struct sk_buff_head srej_q;
struct l2cap_seq_list srej_list;
struct l2cap_seq_list retrans_list;
struct list_head list;
struct list_head global_l;
void *data;
const struct l2cap_ops *ops;
struct mutex lock;
};
struct l2cap_ops {
char *name;
struct l2cap_chan *(*new_connection) (struct l2cap_chan *chan);
int (*recv) (struct l2cap_chan * chan,
struct sk_buff *skb);
void (*teardown) (struct l2cap_chan *chan, int err);
void (*close) (struct l2cap_chan *chan);
void (*state_change) (struct l2cap_chan *chan,
int state, int err);
void (*ready) (struct l2cap_chan *chan);
void (*defer) (struct l2cap_chan *chan);
void (*resume) (struct l2cap_chan *chan);
void (*suspend) (struct l2cap_chan *chan);
void (*set_shutdown) (struct l2cap_chan *chan);
long (*get_sndtimeo) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb);
int (*memcpy_fromiovec) (struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov,
int len);
};
struct l2cap_conn {
struct hci_conn *hcon;
struct hci_chan *hchan;
unsigned int mtu;
__u32 feat_mask;
__u8 fixed_chan_mask;
bool hs_enabled;
__u8 info_state;
__u8 info_ident;
struct delayed_work info_timer;
struct sk_buff *rx_skb;
__u32 rx_len;
__u8 tx_ident;
struct mutex ident_lock;
struct sk_buff_head pending_rx;
struct work_struct pending_rx_work;
struct work_struct id_addr_update_work;
__u8 disc_reason;
struct l2cap_chan *smp;
struct list_head chan_l;
struct mutex chan_lock;
struct kref ref;
struct list_head users;
};
struct l2cap_user {
struct list_head list;
int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user);
void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user);
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
#define L2CAP_CHAN_RAW 1
#define L2CAP_CHAN_CONN_LESS 2
#define L2CAP_CHAN_CONN_ORIENTED 3
#define L2CAP_CHAN_FIXED 4
/* ----- L2CAP socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
struct l2cap_pinfo {
struct bt_sock bt;
struct l2cap_chan *chan;
struct sk_buff *rx_busy_skb;
};
enum {
CONF_REQ_SENT,
CONF_INPUT_DONE,
CONF_OUTPUT_DONE,
CONF_MTU_DONE,
CONF_MODE_DONE,
CONF_CONNECT_PEND,
CONF_RECV_NO_FCS,
CONF_STATE2_DEVICE,
CONF_EWS_RECV,
CONF_LOC_CONF_PEND,
CONF_REM_CONF_PEND,
CONF_NOT_COMPLETE,
};
#define L2CAP_CONF_MAX_CONF_REQ 2
#define L2CAP_CONF_MAX_CONF_RSP 2
enum {
CONN_SREJ_SENT,
CONN_WAIT_F,
CONN_SREJ_ACT,
CONN_SEND_PBIT,
CONN_REMOTE_BUSY,
CONN_LOCAL_BUSY,
CONN_REJ_ACT,
CONN_SEND_FBIT,
CONN_RNR_SENT,
};
/* Definitions for flags in l2cap_chan */
enum {
FLAG_ROLE_SWITCH,
FLAG_FORCE_ACTIVE,
FLAG_FORCE_RELIABLE,
FLAG_FLUSHABLE,
FLAG_EXT_CTRL,
FLAG_EFS_ENABLE,
FLAG_DEFER_SETUP,
FLAG_LE_CONN_REQ_SENT,
FLAG_PENDING_SECURITY,
FLAG_HOLD_HCI_CONN,
};
enum {
L2CAP_TX_STATE_XMIT,
L2CAP_TX_STATE_WAIT_F,
};
enum {
L2CAP_RX_STATE_RECV,
L2CAP_RX_STATE_SREJ_SENT,
L2CAP_RX_STATE_MOVE,
L2CAP_RX_STATE_WAIT_P,
L2CAP_RX_STATE_WAIT_F,
};
enum {
L2CAP_TXSEQ_EXPECTED,
L2CAP_TXSEQ_EXPECTED_SREJ,
L2CAP_TXSEQ_UNEXPECTED,
L2CAP_TXSEQ_UNEXPECTED_SREJ,
L2CAP_TXSEQ_DUPLICATE,
L2CAP_TXSEQ_DUPLICATE_SREJ,
L2CAP_TXSEQ_INVALID,
L2CAP_TXSEQ_INVALID_IGNORE,
};
enum {
L2CAP_EV_DATA_REQUEST,
L2CAP_EV_LOCAL_BUSY_DETECTED,
L2CAP_EV_LOCAL_BUSY_CLEAR,
L2CAP_EV_RECV_REQSEQ_AND_FBIT,
L2CAP_EV_RECV_FBIT,
L2CAP_EV_RETRANS_TO,
L2CAP_EV_MONITOR_TO,
L2CAP_EV_EXPLICIT_POLL,
L2CAP_EV_RECV_IFRAME,
L2CAP_EV_RECV_RR,
L2CAP_EV_RECV_REJ,
L2CAP_EV_RECV_RNR,
L2CAP_EV_RECV_SREJ,
L2CAP_EV_RECV_FRAME,
};
enum {
L2CAP_MOVE_ROLE_NONE,
L2CAP_MOVE_ROLE_INITIATOR,
L2CAP_MOVE_ROLE_RESPONDER,
};
enum {
L2CAP_MOVE_STABLE,
L2CAP_MOVE_WAIT_REQ,
L2CAP_MOVE_WAIT_RSP,
L2CAP_MOVE_WAIT_RSP_SUCCESS,
L2CAP_MOVE_WAIT_CONFIRM,
L2CAP_MOVE_WAIT_CONFIRM_RSP,
L2CAP_MOVE_WAIT_LOGICAL_COMP,
L2CAP_MOVE_WAIT_LOGICAL_CFM,
L2CAP_MOVE_WAIT_LOCAL_BUSY,
L2CAP_MOVE_WAIT_PREPARE,
};
void l2cap_chan_hold(struct l2cap_chan *c);
void l2cap_chan_put(struct l2cap_chan *c);
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
{
mutex_lock(&chan->lock);
}
static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
{
mutex_unlock(&chan->lock);
}
static inline void l2cap_set_timer(struct l2cap_chan *chan,
struct delayed_work *work, long timeout)
{
BT_DBG("chan %p state %s timeout %ld", chan,
state_to_string(chan->state), timeout);
/* If delayed work cancelled do not hold(chan)
since it is already done with previous set_timer */
if (!cancel_delayed_work(work))
l2cap_chan_hold(chan);
schedule_delayed_work(work, timeout);
}
static inline bool l2cap_clear_timer(struct l2cap_chan *chan,
struct delayed_work *work)
{
bool ret;
/* put(chan) if delayed work cancelled otherwise it
is done in delayed work function */
ret = cancel_delayed_work(work);
if (ret)
l2cap_chan_put(chan);
return ret;
}
#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
{
if (seq1 >= seq2)
return seq1 - seq2;
else
return chan->tx_win_max + 1 - seq2 + seq1;
}
static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
{
return (seq + 1) % (chan->tx_win_max + 1);
}
static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
{
return NULL;
}
static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
{
return -ENOSYS;
}
static inline struct sk_buff *l2cap_chan_no_alloc_skb(struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb)
{
return ERR_PTR(-ENOSYS);
}
static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err)
{
}
static inline void l2cap_chan_no_close(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_state_change(struct l2cap_chan *chan,
int state, int err)
{
}
static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_suspend(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_set_shutdown(struct l2cap_chan *chan)
{
}
static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
{
return 0;
}
static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov,
int len)
{
/* Following is safe since for compiler definitions of kvec and
* iovec are identical, yielding the same in-core layout and alignment
*/
struct kvec *vec = (struct kvec *)iov;
while (len > 0) {
if (vec->iov_len) {
int copy = min_t(unsigned int, len, vec->iov_len);
memcpy(kdata, vec->iov_base, copy);
len -= copy;
kdata += copy;
vec->iov_base += copy;
vec->iov_len -= copy;
}
vec++;
}
return 0;
}
extern bool disable_ertm;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
bool l2cap_is_socket(struct socket *sock);
void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan);
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct l2cap_chan *l2cap_chan_create(void);
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type);
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
void l2cap_send_conn_req(struct l2cap_chan *chan);
void l2cap_move_start(struct l2cap_chan *chan);
void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
u8 status);
void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn);
void l2cap_conn_put(struct l2cap_conn *conn);
int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user);
void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user);
#endif /* __L2CAP_H */

View file

@ -0,0 +1,679 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2010 Nokia Corporation
Copyright (C) 2011-2012 Intel Corporation
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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#define MGMT_INDEX_NONE 0xFFFF
#define MGMT_STATUS_SUCCESS 0x00
#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
#define MGMT_STATUS_NOT_CONNECTED 0x02
#define MGMT_STATUS_FAILED 0x03
#define MGMT_STATUS_CONNECT_FAILED 0x04
#define MGMT_STATUS_AUTH_FAILED 0x05
#define MGMT_STATUS_NOT_PAIRED 0x06
#define MGMT_STATUS_NO_RESOURCES 0x07
#define MGMT_STATUS_TIMEOUT 0x08
#define MGMT_STATUS_ALREADY_CONNECTED 0x09
#define MGMT_STATUS_BUSY 0x0a
#define MGMT_STATUS_REJECTED 0x0b
#define MGMT_STATUS_NOT_SUPPORTED 0x0c
#define MGMT_STATUS_INVALID_PARAMS 0x0d
#define MGMT_STATUS_DISCONNECTED 0x0e
#define MGMT_STATUS_NOT_POWERED 0x0f
#define MGMT_STATUS_CANCELLED 0x10
#define MGMT_STATUS_INVALID_INDEX 0x11
#define MGMT_STATUS_RFKILLED 0x12
struct mgmt_hdr {
__le16 opcode;
__le16 index;
__le16 len;
} __packed;
struct mgmt_addr_info {
bdaddr_t bdaddr;
__u8 type;
} __packed;
#define MGMT_ADDR_INFO_SIZE 7
#define MGMT_OP_READ_VERSION 0x0001
#define MGMT_READ_VERSION_SIZE 0
struct mgmt_rp_read_version {
__u8 version;
__le16 revision;
} __packed;
#define MGMT_OP_READ_COMMANDS 0x0002
#define MGMT_READ_COMMANDS_SIZE 0
struct mgmt_rp_read_commands {
__le16 num_commands;
__le16 num_events;
__le16 opcodes[0];
} __packed;
#define MGMT_OP_READ_INDEX_LIST 0x0003
#define MGMT_READ_INDEX_LIST_SIZE 0
struct mgmt_rp_read_index_list {
__le16 num_controllers;
__le16 index[0];
} __packed;
/* Reserve one extra byte for names in management messages so that they
* are always guaranteed to be nul-terminated */
#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
#define MGMT_MAX_SHORT_NAME_LENGTH (HCI_MAX_SHORT_NAME_LENGTH + 1)
#define MGMT_SETTING_POWERED 0x00000001
#define MGMT_SETTING_CONNECTABLE 0x00000002
#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
#define MGMT_SETTING_DISCOVERABLE 0x00000008
#define MGMT_SETTING_BONDABLE 0x00000010
#define MGMT_SETTING_LINK_SECURITY 0x00000020
#define MGMT_SETTING_SSP 0x00000040
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
#define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_SETTING_SECURE_CONN 0x00000800
#define MGMT_SETTING_DEBUG_KEYS 0x00001000
#define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_SETTING_CONFIGURATION 0x00004000
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
struct mgmt_rp_read_info {
bdaddr_t bdaddr;
__u8 version;
__le16 manufacturer;
__le32 supported_settings;
__le32 current_settings;
__u8 dev_class[3];
__u8 name[MGMT_MAX_NAME_LENGTH];
__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
struct mgmt_mode {
__u8 val;
} __packed;
#define MGMT_SETTING_SIZE 1
#define MGMT_OP_SET_POWERED 0x0005
#define MGMT_OP_SET_DISCOVERABLE 0x0006
struct mgmt_cp_set_discoverable {
__u8 val;
__le16 timeout;
} __packed;
#define MGMT_SET_DISCOVERABLE_SIZE 3
#define MGMT_OP_SET_CONNECTABLE 0x0007
#define MGMT_OP_SET_FAST_CONNECTABLE 0x0008
#define MGMT_OP_SET_BONDABLE 0x0009
#define MGMT_OP_SET_LINK_SECURITY 0x000A
#define MGMT_OP_SET_SSP 0x000B
#define MGMT_OP_SET_HS 0x000C
#define MGMT_OP_SET_LE 0x000D
#define MGMT_OP_SET_DEV_CLASS 0x000E
struct mgmt_cp_set_dev_class {
__u8 major;
__u8 minor;
} __packed;
#define MGMT_SET_DEV_CLASS_SIZE 2
#define MGMT_OP_SET_LOCAL_NAME 0x000F
struct mgmt_cp_set_local_name {
__u8 name[MGMT_MAX_NAME_LENGTH];
__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
#define MGMT_SET_LOCAL_NAME_SIZE 260
#define MGMT_OP_ADD_UUID 0x0010
struct mgmt_cp_add_uuid {
__u8 uuid[16];
__u8 svc_hint;
} __packed;
#define MGMT_ADD_UUID_SIZE 17
#define MGMT_OP_REMOVE_UUID 0x0011
struct mgmt_cp_remove_uuid {
__u8 uuid[16];
} __packed;
#define MGMT_REMOVE_UUID_SIZE 16
struct mgmt_link_key_info {
struct mgmt_addr_info addr;
__u8 type;
__u8 val[16];
__u8 pin_len;
} __packed;
#define MGMT_OP_LOAD_LINK_KEYS 0x0012
struct mgmt_cp_load_link_keys {
__u8 debug_keys;
__le16 key_count;
struct mgmt_link_key_info keys[0];
} __packed;
#define MGMT_LOAD_LINK_KEYS_SIZE 3
#define MGMT_LTK_UNAUTHENTICATED 0x00
#define MGMT_LTK_AUTHENTICATED 0x01
struct mgmt_ltk_info {
struct mgmt_addr_info addr;
__u8 type;
__u8 master;
__u8 enc_size;
__le16 ediv;
__le64 rand;
__u8 val[16];
} __packed;
#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013
struct mgmt_cp_load_long_term_keys {
__le16 key_count;
struct mgmt_ltk_info keys[0];
} __packed;
#define MGMT_LOAD_LONG_TERM_KEYS_SIZE 2
#define MGMT_OP_DISCONNECT 0x0014
struct mgmt_cp_disconnect {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_DISCONNECT_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_disconnect {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_GET_CONNECTIONS 0x0015
#define MGMT_GET_CONNECTIONS_SIZE 0
struct mgmt_rp_get_connections {
__le16 conn_count;
struct mgmt_addr_info addr[0];
} __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0016
struct mgmt_cp_pin_code_reply {
struct mgmt_addr_info addr;
__u8 pin_len;
__u8 pin_code[16];
} __packed;
#define MGMT_PIN_CODE_REPLY_SIZE (MGMT_ADDR_INFO_SIZE + 17)
struct mgmt_rp_pin_code_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017
struct mgmt_cp_pin_code_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_PIN_CODE_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_SET_IO_CAPABILITY 0x0018
struct mgmt_cp_set_io_capability {
__u8 io_capability;
} __packed;
#define MGMT_SET_IO_CAPABILITY_SIZE 1
#define MGMT_OP_PAIR_DEVICE 0x0019
struct mgmt_cp_pair_device {
struct mgmt_addr_info addr;
__u8 io_cap;
} __packed;
#define MGMT_PAIR_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
struct mgmt_rp_pair_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_CANCEL_PAIR_DEVICE 0x001A
#define MGMT_CANCEL_PAIR_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_UNPAIR_DEVICE 0x001B
struct mgmt_cp_unpair_device {
struct mgmt_addr_info addr;
__u8 disconnect;
} __packed;
#define MGMT_UNPAIR_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
struct mgmt_rp_unpair_device {
struct mgmt_addr_info addr;
};
#define MGMT_OP_USER_CONFIRM_REPLY 0x001C
struct mgmt_cp_user_confirm_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_USER_CONFIRM_REPLY_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_user_confirm_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001D
struct mgmt_cp_user_confirm_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_USER_CONFIRM_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_USER_PASSKEY_REPLY 0x001E
struct mgmt_cp_user_passkey_reply {
struct mgmt_addr_info addr;
__le32 passkey;
} __packed;
#define MGMT_USER_PASSKEY_REPLY_SIZE (MGMT_ADDR_INFO_SIZE + 4)
struct mgmt_rp_user_passkey_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001F
struct mgmt_cp_user_passkey_neg_reply {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_USER_PASSKEY_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020
#define MGMT_READ_LOCAL_OOB_DATA_SIZE 0
struct mgmt_rp_read_local_oob_data {
__u8 hash[16];
__u8 randomizer[16];
} __packed;
struct mgmt_rp_read_local_oob_ext_data {
__u8 hash192[16];
__u8 randomizer192[16];
__u8 hash256[16];
__u8 randomizer256[16];
} __packed;
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021
struct mgmt_cp_add_remote_oob_data {
struct mgmt_addr_info addr;
__u8 hash[16];
__u8 randomizer[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 32)
struct mgmt_cp_add_remote_oob_ext_data {
struct mgmt_addr_info addr;
__u8 hash192[16];
__u8 randomizer192[16];
__u8 hash256[16];
__u8 randomizer256[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 64)
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0022
struct mgmt_cp_remove_remote_oob_data {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_REMOVE_REMOTE_OOB_DATA_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_START_DISCOVERY 0x0023
struct mgmt_cp_start_discovery {
__u8 type;
} __packed;
#define MGMT_START_DISCOVERY_SIZE 1
#define MGMT_OP_STOP_DISCOVERY 0x0024
struct mgmt_cp_stop_discovery {
__u8 type;
} __packed;
#define MGMT_STOP_DISCOVERY_SIZE 1
#define MGMT_OP_CONFIRM_NAME 0x0025
struct mgmt_cp_confirm_name {
struct mgmt_addr_info addr;
__u8 name_known;
} __packed;
#define MGMT_CONFIRM_NAME_SIZE (MGMT_ADDR_INFO_SIZE + 1)
struct mgmt_rp_confirm_name {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_OP_BLOCK_DEVICE 0x0026
struct mgmt_cp_block_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_BLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_UNBLOCK_DEVICE 0x0027
struct mgmt_cp_unblock_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_UNBLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
#define MGMT_OP_SET_DEVICE_ID 0x0028
struct mgmt_cp_set_device_id {
__le16 source;
__le16 vendor;
__le16 product;
__le16 version;
} __packed;
#define MGMT_SET_DEVICE_ID_SIZE 8
#define MGMT_OP_SET_ADVERTISING 0x0029
#define MGMT_OP_SET_BREDR 0x002A
#define MGMT_OP_SET_STATIC_ADDRESS 0x002B
struct mgmt_cp_set_static_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_SET_STATIC_ADDRESS_SIZE 6
#define MGMT_OP_SET_SCAN_PARAMS 0x002C
struct mgmt_cp_set_scan_params {
__le16 interval;
__le16 window;
} __packed;
#define MGMT_SET_SCAN_PARAMS_SIZE 4
#define MGMT_OP_SET_SECURE_CONN 0x002D
#define MGMT_OP_SET_DEBUG_KEYS 0x002E
#define MGMT_OP_SET_PRIVACY 0x002F
struct mgmt_cp_set_privacy {
__u8 privacy;
__u8 irk[16];
} __packed;
#define MGMT_SET_PRIVACY_SIZE 17
struct mgmt_irk_info {
struct mgmt_addr_info addr;
__u8 val[16];
} __packed;
#define MGMT_OP_LOAD_IRKS 0x0030
struct mgmt_cp_load_irks {
__le16 irk_count;
struct mgmt_irk_info irks[0];
} __packed;
#define MGMT_LOAD_IRKS_SIZE 2
#define MGMT_OP_GET_CONN_INFO 0x0031
struct mgmt_cp_get_conn_info {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_GET_CONN_INFO_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_get_conn_info {
struct mgmt_addr_info addr;
__s8 rssi;
__s8 tx_power;
__s8 max_tx_power;
} __packed;
#define MGMT_OP_GET_CLOCK_INFO 0x0032
struct mgmt_cp_get_clock_info {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_GET_CLOCK_INFO_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_rp_get_clock_info {
struct mgmt_addr_info addr;
__le32 local_clock;
__le32 piconet_clock;
__le16 accuracy;
} __packed;
#define MGMT_OP_ADD_DEVICE 0x0033
struct mgmt_cp_add_device {
struct mgmt_addr_info addr;
__u8 action;
} __packed;
#define MGMT_ADD_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1)
#define MGMT_OP_REMOVE_DEVICE 0x0034
struct mgmt_cp_remove_device {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_REMOVE_DEVICE_SIZE MGMT_ADDR_INFO_SIZE
struct mgmt_conn_param {
struct mgmt_addr_info addr;
__le16 min_interval;
__le16 max_interval;
__le16 latency;
__le16 timeout;
} __packed;
#define MGMT_OP_LOAD_CONN_PARAM 0x0035
struct mgmt_cp_load_conn_param {
__le16 param_count;
struct mgmt_conn_param params[0];
} __packed;
#define MGMT_LOAD_CONN_PARAM_SIZE 2
#define MGMT_OP_READ_UNCONF_INDEX_LIST 0x0036
#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0
struct mgmt_rp_read_unconf_index_list {
__le16 num_controllers;
__le16 index[0];
} __packed;
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001
#define MGMT_OPTION_PUBLIC_ADDRESS 0x00000002
#define MGMT_OP_READ_CONFIG_INFO 0x0037
#define MGMT_READ_CONFIG_INFO_SIZE 0
struct mgmt_rp_read_config_info {
__le16 manufacturer;
__le32 supported_options;
__le32 missing_options;
} __packed;
#define MGMT_OP_SET_EXTERNAL_CONFIG 0x0038
struct mgmt_cp_set_external_config {
__u8 config;
} __packed;
#define MGMT_SET_EXTERNAL_CONFIG_SIZE 1
#define MGMT_OP_SET_PUBLIC_ADDRESS 0x0039
struct mgmt_cp_set_public_address {
bdaddr_t bdaddr;
} __packed;
#define MGMT_SET_PUBLIC_ADDRESS_SIZE 6
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
__u8 status;
__u8 data[0];
} __packed;
#define MGMT_EV_CMD_STATUS 0x0002
struct mgmt_ev_cmd_status {
__le16 opcode;
__u8 status;
} __packed;
#define MGMT_EV_CONTROLLER_ERROR 0x0003
struct mgmt_ev_controller_error {
__u8 error_code;
} __packed;
#define MGMT_EV_INDEX_ADDED 0x0004
#define MGMT_EV_INDEX_REMOVED 0x0005
#define MGMT_EV_NEW_SETTINGS 0x0006
#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
struct mgmt_ev_class_of_dev_changed {
__u8 dev_class[3];
};
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008
struct mgmt_ev_local_name_changed {
__u8 name[MGMT_MAX_NAME_LENGTH];
__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
#define MGMT_EV_NEW_LINK_KEY 0x0009
struct mgmt_ev_new_link_key {
__u8 store_hint;
struct mgmt_link_key_info key;
} __packed;
#define MGMT_EV_NEW_LONG_TERM_KEY 0x000A
struct mgmt_ev_new_long_term_key {
__u8 store_hint;
struct mgmt_ltk_info key;
} __packed;
#define MGMT_EV_DEVICE_CONNECTED 0x000B
struct mgmt_ev_device_connected {
struct mgmt_addr_info addr;
__le32 flags;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_DEV_DISCONN_UNKNOWN 0x00
#define MGMT_DEV_DISCONN_TIMEOUT 0x01
#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02
#define MGMT_DEV_DISCONN_REMOTE 0x03
#define MGMT_EV_DEVICE_DISCONNECTED 0x000C
struct mgmt_ev_device_disconnected {
struct mgmt_addr_info addr;
__u8 reason;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D
struct mgmt_ev_connect_failed {
struct mgmt_addr_info addr;
__u8 status;
} __packed;
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct mgmt_ev_pin_code_request {
struct mgmt_addr_info addr;
__u8 secure;
} __packed;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct mgmt_ev_user_confirm_request {
struct mgmt_addr_info addr;
__u8 confirm_hint;
__le32 value;
} __packed;
#define MGMT_EV_USER_PASSKEY_REQUEST 0x0010
struct mgmt_ev_user_passkey_request {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_AUTH_FAILED 0x0011
struct mgmt_ev_auth_failed {
struct mgmt_addr_info addr;
__u8 status;
} __packed;
#define MGMT_DEV_FOUND_CONFIRM_NAME 0x01
#define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02
#define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04
#define MGMT_EV_DEVICE_FOUND 0x0012
struct mgmt_ev_device_found {
struct mgmt_addr_info addr;
__s8 rssi;
__le32 flags;
__le16 eir_len;
__u8 eir[0];
} __packed;
#define MGMT_EV_DISCOVERING 0x0013
struct mgmt_ev_discovering {
__u8 type;
__u8 discovering;
} __packed;
#define MGMT_EV_DEVICE_BLOCKED 0x0014
struct mgmt_ev_device_blocked {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_DEVICE_UNBLOCKED 0x0015
struct mgmt_ev_device_unblocked {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_DEVICE_UNPAIRED 0x0016
struct mgmt_ev_device_unpaired {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_PASSKEY_NOTIFY 0x0017
struct mgmt_ev_passkey_notify {
struct mgmt_addr_info addr;
__le32 passkey;
__u8 entered;
} __packed;
#define MGMT_EV_NEW_IRK 0x0018
struct mgmt_ev_new_irk {
__u8 store_hint;
bdaddr_t rpa;
struct mgmt_irk_info irk;
} __packed;
struct mgmt_csrk_info {
struct mgmt_addr_info addr;
__u8 master;
__u8 val[16];
} __packed;
#define MGMT_EV_NEW_CSRK 0x0019
struct mgmt_ev_new_csrk {
__u8 store_hint;
struct mgmt_csrk_info key;
} __packed;
#define MGMT_EV_DEVICE_ADDED 0x001a
struct mgmt_ev_device_added {
struct mgmt_addr_info addr;
__u8 action;
} __packed;
#define MGMT_EV_DEVICE_REMOVED 0x001b
struct mgmt_ev_device_removed {
struct mgmt_addr_info addr;
} __packed;
#define MGMT_EV_NEW_CONN_PARAM 0x001c
struct mgmt_ev_new_conn_param {
struct mgmt_addr_info addr;
__u8 store_hint;
__le16 min_interval;
__le16 max_interval;
__le16 latency;
__le16 timeout;
} __packed;
#define MGMT_EV_UNCONF_INDEX_ADDED 0x001d
#define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e
#define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f

View file

@ -0,0 +1,376 @@
/*
RFCOMM implementation for Linux Bluetooth stack (BlueZ)
Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __RFCOMM_H
#define __RFCOMM_H
#define RFCOMM_PSM 3
#define RFCOMM_CONN_TIMEOUT (HZ * 30)
#define RFCOMM_DISC_TIMEOUT (HZ * 20)
#define RFCOMM_AUTH_TIMEOUT (HZ * 25)
#define RFCOMM_IDLE_TIMEOUT (HZ * 2)
#define RFCOMM_DEFAULT_MTU 127
#define RFCOMM_DEFAULT_CREDITS 7
#define RFCOMM_MAX_L2CAP_MTU 1013
#define RFCOMM_MAX_CREDITS 40
#define RFCOMM_SKB_HEAD_RESERVE 8
#define RFCOMM_SKB_TAIL_RESERVE 2
#define RFCOMM_SKB_RESERVE (RFCOMM_SKB_HEAD_RESERVE + RFCOMM_SKB_TAIL_RESERVE)
#define RFCOMM_SABM 0x2f
#define RFCOMM_DISC 0x43
#define RFCOMM_UA 0x63
#define RFCOMM_DM 0x0f
#define RFCOMM_UIH 0xef
#define RFCOMM_TEST 0x08
#define RFCOMM_FCON 0x28
#define RFCOMM_FCOFF 0x18
#define RFCOMM_MSC 0x38
#define RFCOMM_RPN 0x24
#define RFCOMM_RLS 0x14
#define RFCOMM_PN 0x20
#define RFCOMM_NSC 0x04
#define RFCOMM_V24_FC 0x02
#define RFCOMM_V24_RTC 0x04
#define RFCOMM_V24_RTR 0x08
#define RFCOMM_V24_IC 0x40
#define RFCOMM_V24_DV 0x80
#define RFCOMM_RPN_BR_2400 0x0
#define RFCOMM_RPN_BR_4800 0x1
#define RFCOMM_RPN_BR_7200 0x2
#define RFCOMM_RPN_BR_9600 0x3
#define RFCOMM_RPN_BR_19200 0x4
#define RFCOMM_RPN_BR_38400 0x5
#define RFCOMM_RPN_BR_57600 0x6
#define RFCOMM_RPN_BR_115200 0x7
#define RFCOMM_RPN_BR_230400 0x8
#define RFCOMM_RPN_DATA_5 0x0
#define RFCOMM_RPN_DATA_6 0x1
#define RFCOMM_RPN_DATA_7 0x2
#define RFCOMM_RPN_DATA_8 0x3
#define RFCOMM_RPN_STOP_1 0
#define RFCOMM_RPN_STOP_15 1
#define RFCOMM_RPN_PARITY_NONE 0x0
#define RFCOMM_RPN_PARITY_ODD 0x1
#define RFCOMM_RPN_PARITY_EVEN 0x3
#define RFCOMM_RPN_PARITY_MARK 0x5
#define RFCOMM_RPN_PARITY_SPACE 0x7
#define RFCOMM_RPN_FLOW_NONE 0x00
#define RFCOMM_RPN_XON_CHAR 0x11
#define RFCOMM_RPN_XOFF_CHAR 0x13
#define RFCOMM_RPN_PM_BITRATE 0x0001
#define RFCOMM_RPN_PM_DATA 0x0002
#define RFCOMM_RPN_PM_STOP 0x0004
#define RFCOMM_RPN_PM_PARITY 0x0008
#define RFCOMM_RPN_PM_PARITY_TYPE 0x0010
#define RFCOMM_RPN_PM_XON 0x0020
#define RFCOMM_RPN_PM_XOFF 0x0040
#define RFCOMM_RPN_PM_FLOW 0x3F00
#define RFCOMM_RPN_PM_ALL 0x3F7F
struct rfcomm_hdr {
u8 addr;
u8 ctrl;
u8 len; /* Actual size can be 2 bytes */
} __packed;
struct rfcomm_cmd {
u8 addr;
u8 ctrl;
u8 len;
u8 fcs;
} __packed;
struct rfcomm_mcc {
u8 type;
u8 len;
} __packed;
struct rfcomm_pn {
u8 dlci;
u8 flow_ctrl;
u8 priority;
u8 ack_timer;
__le16 mtu;
u8 max_retrans;
u8 credits;
} __packed;
struct rfcomm_rpn {
u8 dlci;
u8 bit_rate;
u8 line_settings;
u8 flow_ctrl;
u8 xon_char;
u8 xoff_char;
__le16 param_mask;
} __packed;
struct rfcomm_rls {
u8 dlci;
u8 status;
} __packed;
struct rfcomm_msc {
u8 dlci;
u8 v24_sig;
} __packed;
/* ---- Core structures, flags etc ---- */
struct rfcomm_session {
struct list_head list;
struct socket *sock;
struct timer_list timer;
unsigned long state;
unsigned long flags;
int initiator;
/* Default DLC parameters */
int cfc;
uint mtu;
struct list_head dlcs;
};
struct rfcomm_dlc {
struct list_head list;
struct rfcomm_session *session;
struct sk_buff_head tx_queue;
struct timer_list timer;
struct mutex lock;
unsigned long state;
unsigned long flags;
atomic_t refcnt;
u8 dlci;
u8 addr;
u8 priority;
u8 v24_sig;
u8 remote_v24_sig;
u8 mscex;
u8 out;
u8 sec_level;
u8 role_switch;
u32 defer_setup;
uint mtu;
uint cfc;
uint rx_credits;
uint tx_credits;
void *owner;
void (*data_ready)(struct rfcomm_dlc *d, struct sk_buff *skb);
void (*state_change)(struct rfcomm_dlc *d, int err);
void (*modem_status)(struct rfcomm_dlc *d, u8 v24_sig);
};
/* DLC and session flags */
#define RFCOMM_RX_THROTTLED 0
#define RFCOMM_TX_THROTTLED 1
#define RFCOMM_TIMED_OUT 2
#define RFCOMM_MSC_PENDING 3
#define RFCOMM_SEC_PENDING 4
#define RFCOMM_AUTH_PENDING 5
#define RFCOMM_AUTH_ACCEPT 6
#define RFCOMM_AUTH_REJECT 7
#define RFCOMM_DEFER_SETUP 8
#define RFCOMM_ENC_DROP 9
/* Scheduling flags and events */
#define RFCOMM_SCHED_WAKEUP 31
/* MSC exchange flags */
#define RFCOMM_MSCEX_TX 1
#define RFCOMM_MSCEX_RX 2
#define RFCOMM_MSCEX_OK (RFCOMM_MSCEX_TX + RFCOMM_MSCEX_RX)
/* CFC states */
#define RFCOMM_CFC_UNKNOWN -1
#define RFCOMM_CFC_DISABLED 0
#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
/* ---- RFCOMM SEND RPN ---- */
int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 bit_rate, u8 data_bits, u8 stop_bits,
u8 parity, u8 flow_ctrl_settings,
u8 xon_char, u8 xoff_char, u16 param_mask);
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb);
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
void rfcomm_dlc_accept(struct rfcomm_dlc *d);
struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
#define rfcomm_dlc_lock(d) mutex_lock(&d->lock)
#define rfcomm_dlc_unlock(d) mutex_unlock(&d->lock)
static inline void rfcomm_dlc_hold(struct rfcomm_dlc *d)
{
atomic_inc(&d->refcnt);
}
static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
{
if (atomic_dec_and_test(&d->refcnt))
rfcomm_dlc_free(d);
}
void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d)
{
if (!test_and_set_bit(RFCOMM_RX_THROTTLED, &d->flags))
__rfcomm_dlc_throttle(d);
}
static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
{
if (test_and_clear_bit(RFCOMM_RX_THROTTLED, &d->flags))
__rfcomm_dlc_unthrottle(d);
}
/* ---- RFCOMM sessions ---- */
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
bdaddr_t *dst);
/* ---- RFCOMM sockets ---- */
struct sockaddr_rc {
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
u8 rc_channel;
};
#define RFCOMM_CONNINFO 0x02
struct rfcomm_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define RFCOMM_LM 0x03
#define RFCOMM_LM_MASTER 0x0001
#define RFCOMM_LM_AUTH 0x0002
#define RFCOMM_LM_ENCRYPT 0x0004
#define RFCOMM_LM_TRUSTED 0x0008
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
#define RFCOMM_LM_FIPS 0x0040
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
struct rfcomm_pinfo {
struct bt_sock bt;
bdaddr_t src;
bdaddr_t dst;
struct rfcomm_dlc *dlc;
u8 channel;
u8 sec_level;
u8 role_switch;
};
int rfcomm_init_sockets(void);
void rfcomm_cleanup_sockets(void);
int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
struct rfcomm_dlc **d);
/* ---- RFCOMM TTY ---- */
#define RFCOMM_MAX_DEV 256
#define RFCOMMCREATEDEV _IOW('R', 200, int)
#define RFCOMMRELEASEDEV _IOW('R', 201, int)
#define RFCOMMGETDEVLIST _IOR('R', 210, int)
#define RFCOMMGETDEVINFO _IOR('R', 211, int)
#define RFCOMMSTEALDLC _IOW('R', 220, int)
/* rfcomm_dev.flags bit definitions */
#define RFCOMM_REUSE_DLC 0
#define RFCOMM_RELEASE_ONHUP 1
#define RFCOMM_HANGUP_NOW 2
#define RFCOMM_TTY_ATTACHED 3
#define RFCOMM_DEFUNCT_BIT4 4 /* don't reuse this bit - userspace visible */
/* rfcomm_dev.status bit definitions */
#define RFCOMM_DEV_RELEASED 0
#define RFCOMM_TTY_OWNED 1
struct rfcomm_dev_req {
s16 dev_id;
u32 flags;
bdaddr_t src;
bdaddr_t dst;
u8 channel;
};
struct rfcomm_dev_info {
s16 id;
u32 flags;
u16 state;
bdaddr_t src;
bdaddr_t dst;
u8 channel;
};
struct rfcomm_dev_list_req {
u16 dev_num;
struct rfcomm_dev_info dev_info[0];
};
int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
#ifdef CONFIG_BT_RFCOMM_TTY
int rfcomm_init_ttys(void);
void rfcomm_cleanup_ttys(void);
#else
static inline int rfcomm_init_ttys(void)
{
return 0;
}
static inline void rfcomm_cleanup_ttys(void)
{
}
#endif
#endif /* __RFCOMM_H */

View file

@ -0,0 +1,49 @@
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
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;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __SCO_H
#define __SCO_H
/* SCO defaults */
#define SCO_DEFAULT_MTU 500
/* SCO socket address */
struct sockaddr_sco {
sa_family_t sco_family;
bdaddr_t sco_bdaddr;
};
/* SCO socket options */
#define SCO_OPTIONS 0x01
struct sco_options {
__u16 mtu;
};
#define SCO_CONNINFO 0x02
struct sco_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#endif /* __SCO_H */

169
include/net/busy_poll.h Normal file
View file

@ -0,0 +1,169 @@
/*
* net busy poll support
* Copyright(c) 2013 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Author: Eliezer Tamir
*
* Contact Information:
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
*/
#ifndef _LINUX_NET_BUSY_POLL_H
#define _LINUX_NET_BUSY_POLL_H
#include <linux/netdevice.h>
#include <net/ip.h>
#ifdef CONFIG_NET_RX_BUSY_POLL
struct napi_struct;
extern unsigned int sysctl_net_busy_read __read_mostly;
extern unsigned int sysctl_net_busy_poll __read_mostly;
/* return values from ndo_ll_poll */
#define LL_FLUSH_FAILED -1
#define LL_FLUSH_BUSY -2
static inline bool net_busy_loop_on(void)
{
return sysctl_net_busy_poll;
}
static inline u64 busy_loop_us_clock(void)
{
return local_clock() >> 10;
}
static inline unsigned long sk_busy_loop_end_time(struct sock *sk)
{
return busy_loop_us_clock() + ACCESS_ONCE(sk->sk_ll_usec);
}
/* in poll/select we use the global sysctl_net_ll_poll value */
static inline unsigned long busy_loop_end_time(void)
{
return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_busy_poll);
}
static inline bool sk_can_busy_loop(struct sock *sk)
{
return sk->sk_ll_usec && sk->sk_napi_id &&
!need_resched() && !signal_pending(current);
}
static inline bool busy_loop_timeout(unsigned long end_time)
{
unsigned long now = busy_loop_us_clock();
return time_after(now, end_time);
}
/* when used in sock_poll() nonblock is known at compile time to be true
* so the loop and end_time will be optimized out
*/
static inline bool sk_busy_loop(struct sock *sk, int nonblock)
{
unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0;
const struct net_device_ops *ops;
struct napi_struct *napi;
int rc = false;
/*
* rcu read lock for napi hash
* bh so we don't race with net_rx_action
*/
rcu_read_lock_bh();
napi = napi_by_id(sk->sk_napi_id);
if (!napi)
goto out;
ops = napi->dev->netdev_ops;
if (!ops->ndo_busy_poll)
goto out;
do {
rc = ops->ndo_busy_poll(napi);
if (rc == LL_FLUSH_FAILED)
break; /* permanent failure */
if (rc > 0)
/* local bh are disabled so it is ok to use _BH */
NET_ADD_STATS_BH(sock_net(sk),
LINUX_MIB_BUSYPOLLRXPACKETS, rc);
cpu_relax();
} while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) &&
!need_resched() && !busy_loop_timeout(end_time));
rc = !skb_queue_empty(&sk->sk_receive_queue);
out:
rcu_read_unlock_bh();
return rc;
}
/* used in the NIC receive handler to mark the skb */
static inline void skb_mark_napi_id(struct sk_buff *skb,
struct napi_struct *napi)
{
skb->napi_id = napi->napi_id;
}
/* used in the protocol hanlder to propagate the napi_id to the socket */
static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
{
sk->sk_napi_id = skb->napi_id;
}
#else /* CONFIG_NET_RX_BUSY_POLL */
static inline unsigned long net_busy_loop_on(void)
{
return 0;
}
static inline unsigned long busy_loop_end_time(void)
{
return 0;
}
static inline bool sk_can_busy_loop(struct sock *sk)
{
return false;
}
static inline void skb_mark_napi_id(struct sk_buff *skb,
struct napi_struct *napi)
{
}
static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
{
}
static inline bool busy_loop_timeout(unsigned long end_time)
{
return true;
}
static inline bool sk_busy_loop(struct sock *sk, int nonblock)
{
return false;
}
#endif /* CONFIG_NET_RX_BUSY_POLL */
#endif /* _LINUX_NET_BUSY_POLL_H */

128
include/net/caif/caif_dev.h Normal file
View file

@ -0,0 +1,128 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_DEV_H_
#define CAIF_DEV_H_
#include <net/caif/caif_layer.h>
#include <net/caif/cfcnfg.h>
#include <net/caif/caif_device.h>
#include <linux/caif/caif_socket.h>
#include <linux/if.h>
#include <linux/net.h>
/**
* struct caif_param - CAIF parameters.
* @size: Length of data
* @data: Binary Data Blob
*/
struct caif_param {
u16 size;
u8 data[256];
};
/**
* struct caif_connect_request - Request data for CAIF channel setup.
* @protocol: Type of CAIF protocol to use (at, datagram etc)
* @sockaddr: Socket address to connect.
* @priority: Priority of the connection.
* @link_selector: Link selector (high bandwidth or low latency)
* @ifindex: kernel index of the interface.
* @param: Connect Request parameters (CAIF_SO_REQ_PARAM).
*
* This struct is used when connecting a CAIF channel.
* It contains all CAIF channel configuration options.
*/
struct caif_connect_request {
enum caif_protocol_type protocol;
struct sockaddr_caif sockaddr;
enum caif_channel_priority priority;
enum caif_link_selector link_selector;
int ifindex;
struct caif_param param;
};
/**
* caif_connect_client - Connect a client to CAIF Core Stack.
* @config: Channel setup parameters, specifying what address
* to connect on the Modem.
* @client_layer: User implementation of client layer. This layer
* MUST have receive and control callback functions
* implemented.
* @ifindex: Link layer interface index used for this connection.
* @headroom: Head room needed by CAIF protocol.
* @tailroom: Tail room needed by CAIF protocol.
*
* This function connects a CAIF channel. The Client must implement
* the struct cflayer. This layer represents the Client layer and holds
* receive functions and control callback functions. Control callback
* function will receive information about connect/disconnect responses,
* flow control etc (see enum caif_control).
* E.g. CAIF Socket will call this function for each socket it connects
* and have one client_layer instance for each socket.
*/
int caif_connect_client(struct net *net,
struct caif_connect_request *conn_req,
struct cflayer *client_layer, int *ifindex,
int *headroom, int *tailroom);
/**
* caif_disconnect_client - Disconnects a client from the CAIF stack.
*
* @client_layer: Client layer to be disconnected.
*/
int caif_disconnect_client(struct net *net, struct cflayer *client_layer);
/**
* caif_client_register_refcnt - register ref-count functions provided by client.
*
* @adapt_layer: Client layer using CAIF Stack.
* @hold: Function provided by client layer increasing ref-count
* @put: Function provided by client layer decreasing ref-count
*
* Client of the CAIF Stack must register functions for reference counting.
* These functions are called by the CAIF Stack for every upstream packet,
* and must therefore be implemented efficiently.
*
* Client should call caif_free_client when reference count degrease to zero.
*/
void caif_client_register_refcnt(struct cflayer *adapt_layer,
void (*hold)(struct cflayer *lyr),
void (*put)(struct cflayer *lyr));
/**
* caif_free_client - Free memory used to manage the client in the CAIF Stack.
*
* @client_layer: Client layer to be removed.
*
* This function must be called from client layer in order to free memory.
* Caller must guarantee that no packets are in flight upstream when calling
* this function.
*/
void caif_free_client(struct cflayer *adap_layer);
/**
* struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer
* @dev: Network device to enroll.
* @caifdev: Configuration information from CAIF Link Layer
* @link_support: Link layer support layer
* @head_room: Head room needed by link support layer
* @layer: Lowest layer in CAIF stack
* @rcv_fun: Receive function for CAIF stack.
*
* This function enroll a CAIF link layer into CAIF Stack and
* expects the interface to be able to handle CAIF payload.
* The link_support layer is used to add any Link Layer specific
* framing.
*/
void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
struct cflayer *link_support, int head_room,
struct cflayer **layer, int (**rcv_func)(
struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *));
#endif /* CAIF_DEV_H_ */

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_DEVICE_H_
#define CAIF_DEVICE_H_
#include <linux/kernel.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/caif/caif_socket.h>
#include <net/caif/caif_device.h>
/**
* struct caif_dev_common - data shared between CAIF drivers and stack.
* @flowctrl: Flow Control callback function. This function is
* supplied by CAIF Core Stack and is used by CAIF
* Link Layer to send flow-stop to CAIF Core.
* The flow information will be distributed to all
* clients of CAIF.
*
* @link_select: Profile of device, either high-bandwidth or
* low-latency. This member is set by CAIF Link
* Layer Device in order to indicate if this device
* is a high bandwidth or low latency device.
*
* @use_frag: CAIF Frames may be fragmented.
* Is set by CAIF Link Layer in order to indicate if the
* interface receives fragmented frames that must be
* assembled by CAIF Core Layer.
*
* @use_fcs: Indicate if Frame CheckSum (fcs) is used.
* Is set if the physical interface is
* using Frame Checksum on the CAIF Frames.
*
* @use_stx: Indicate STart of frame eXtension (stx) in use.
* Is set if the CAIF Link Layer expects
* CAIF Frames to start with the STX byte.
*
* This structure is shared between the CAIF drivers and the CAIF stack.
* It is used by the device to register its behavior.
* CAIF Core layer must set the member flowctrl in order to supply
* CAIF Link Layer with the flow control function.
*
*/
struct caif_dev_common {
void (*flowctrl)(struct net_device *net, int on);
enum caif_link_selector link_select;
int use_frag;
int use_fcs;
int use_stx;
};
#endif /* CAIF_DEVICE_H_ */

200
include/net/caif/caif_hsi.h Normal file
View file

@ -0,0 +1,200 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Daniel Martensson / daniel.martensson@stericsson.com
* Dmitry.Tarnyagin / dmitry.tarnyagin@stericsson.com
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_HSI_H_
#define CAIF_HSI_H_
#include <net/caif/caif_layer.h>
#include <net/caif/caif_device.h>
#include <linux/atomic.h>
/*
* Maximum number of CAIF frames that can reside in the same HSI frame.
*/
#define CFHSI_MAX_PKTS 15
/*
* Maximum number of bytes used for the frame that can be embedded in the
* HSI descriptor.
*/
#define CFHSI_MAX_EMB_FRM_SZ 96
/*
* Decides if HSI buffers should be prefilled with 0xFF pattern for easier
* debugging. Both TX and RX buffers will be filled before the transfer.
*/
#define CFHSI_DBG_PREFILL 0
/* Structure describing a HSI packet descriptor. */
#pragma pack(1) /* Byte alignment. */
struct cfhsi_desc {
u8 header;
u8 offset;
u16 cffrm_len[CFHSI_MAX_PKTS];
u8 emb_frm[CFHSI_MAX_EMB_FRM_SZ];
};
#pragma pack() /* Default alignment. */
/* Size of the complete HSI packet descriptor. */
#define CFHSI_DESC_SZ (sizeof(struct cfhsi_desc))
/*
* Size of the complete HSI packet descriptor excluding the optional embedded
* CAIF frame.
*/
#define CFHSI_DESC_SHORT_SZ (CFHSI_DESC_SZ - CFHSI_MAX_EMB_FRM_SZ)
/*
* Maximum bytes transferred in one transfer.
*/
#define CFHSI_MAX_CAIF_FRAME_SZ 4096
#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * CFHSI_MAX_CAIF_FRAME_SZ)
/* Size of the complete HSI TX buffer. */
#define CFHSI_BUF_SZ_TX (CFHSI_DESC_SZ + CFHSI_MAX_PAYLOAD_SZ)
/* Size of the complete HSI RX buffer. */
#define CFHSI_BUF_SZ_RX ((2 * CFHSI_DESC_SZ) + CFHSI_MAX_PAYLOAD_SZ)
/* Bitmasks for the HSI descriptor. */
#define CFHSI_PIGGY_DESC (0x01 << 7)
#define CFHSI_TX_STATE_IDLE 0
#define CFHSI_TX_STATE_XFER 1
#define CFHSI_RX_STATE_DESC 0
#define CFHSI_RX_STATE_PAYLOAD 1
/* Bitmasks for power management. */
#define CFHSI_WAKE_UP 0
#define CFHSI_WAKE_UP_ACK 1
#define CFHSI_WAKE_DOWN_ACK 2
#define CFHSI_AWAKE 3
#define CFHSI_WAKELOCK_HELD 4
#define CFHSI_SHUTDOWN 5
#define CFHSI_FLUSH_FIFO 6
#ifndef CFHSI_INACTIVITY_TOUT
#define CFHSI_INACTIVITY_TOUT (1 * HZ)
#endif /* CFHSI_INACTIVITY_TOUT */
#ifndef CFHSI_WAKE_TOUT
#define CFHSI_WAKE_TOUT (3 * HZ)
#endif /* CFHSI_WAKE_TOUT */
#ifndef CFHSI_MAX_RX_RETRIES
#define CFHSI_MAX_RX_RETRIES (10 * HZ)
#endif
/* Structure implemented by the CAIF HSI driver. */
struct cfhsi_cb_ops {
void (*tx_done_cb) (struct cfhsi_cb_ops *drv);
void (*rx_done_cb) (struct cfhsi_cb_ops *drv);
void (*wake_up_cb) (struct cfhsi_cb_ops *drv);
void (*wake_down_cb) (struct cfhsi_cb_ops *drv);
};
/* Structure implemented by HSI device. */
struct cfhsi_ops {
int (*cfhsi_up) (struct cfhsi_ops *dev);
int (*cfhsi_down) (struct cfhsi_ops *dev);
int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_ops *dev);
int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_ops *dev);
int (*cfhsi_wake_up) (struct cfhsi_ops *dev);
int (*cfhsi_wake_down) (struct cfhsi_ops *dev);
int (*cfhsi_get_peer_wake) (struct cfhsi_ops *dev, bool *status);
int (*cfhsi_fifo_occupancy) (struct cfhsi_ops *dev, size_t *occupancy);
int (*cfhsi_rx_cancel)(struct cfhsi_ops *dev);
struct cfhsi_cb_ops *cb_ops;
};
/* Structure holds status of received CAIF frames processing */
struct cfhsi_rx_state {
int state;
int nfrms;
int pld_len;
int retries;
bool piggy_desc;
};
/* Priority mapping */
enum {
CFHSI_PRIO_CTL = 0,
CFHSI_PRIO_VI,
CFHSI_PRIO_VO,
CFHSI_PRIO_BEBK,
CFHSI_PRIO_LAST,
};
struct cfhsi_config {
u32 inactivity_timeout;
u32 aggregation_timeout;
u32 head_align;
u32 tail_align;
u32 q_high_mark;
u32 q_low_mark;
};
/* Structure implemented by CAIF HSI drivers. */
struct cfhsi {
struct caif_dev_common cfdev;
struct net_device *ndev;
struct platform_device *pdev;
struct sk_buff_head qhead[CFHSI_PRIO_LAST];
struct cfhsi_cb_ops cb_ops;
struct cfhsi_ops *ops;
int tx_state;
struct cfhsi_rx_state rx_state;
struct cfhsi_config cfg;
int rx_len;
u8 *rx_ptr;
u8 *tx_buf;
u8 *rx_buf;
u8 *rx_flip_buf;
spinlock_t lock;
int flow_off_sent;
struct list_head list;
struct work_struct wake_up_work;
struct work_struct wake_down_work;
struct work_struct out_of_sync_work;
struct workqueue_struct *wq;
wait_queue_head_t wake_up_wait;
wait_queue_head_t wake_down_wait;
wait_queue_head_t flush_fifo_wait;
struct timer_list inactivity_timer;
struct timer_list rx_slowpath_timer;
/* TX aggregation */
int aggregation_len;
struct timer_list aggregation_timer;
unsigned long bits;
};
extern struct platform_driver cfhsi_driver;
/**
* enum ifla_caif_hsi - CAIF HSI NetlinkRT parameters.
* @IFLA_CAIF_HSI_INACTIVITY_TOUT: Inactivity timeout before
* taking the HSI wakeline down, in milliseconds.
* When using RT Netlink to create, destroy or configure a CAIF HSI interface,
* enum ifla_caif_hsi is used to specify the configuration attributes.
*/
enum ifla_caif_hsi {
__IFLA_CAIF_HSI_UNSPEC,
__IFLA_CAIF_HSI_INACTIVITY_TOUT,
__IFLA_CAIF_HSI_AGGREGATION_TOUT,
__IFLA_CAIF_HSI_HEAD_ALIGN,
__IFLA_CAIF_HSI_TAIL_ALIGN,
__IFLA_CAIF_HSI_QHIGH_WATERMARK,
__IFLA_CAIF_HSI_QLOW_WATERMARK,
__IFLA_CAIF_HSI_MAX
};
struct cfhsi_ops *cfhsi_get_ops(void);
#endif /* CAIF_HSI_H_ */

View file

@ -0,0 +1,279 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_LAYER_H_
#define CAIF_LAYER_H_
#include <linux/list.h>
struct cflayer;
struct cfpkt;
struct cfpktq;
struct caif_payload_info;
struct caif_packet_funcs;
#define CAIF_LAYER_NAME_SZ 16
/**
* caif_assert() - Assert function for CAIF.
* @assert: expression to evaluate.
*
* This function will print a error message and a do WARN_ON if the
* assertion failes. Normally this will do a stack up at the current location.
*/
#define caif_assert(assert) \
do { \
if (!(assert)) { \
pr_err("caif:Assert detected:'%s'\n", #assert); \
WARN_ON(!(assert)); \
} \
} while (0)
/**
* enum caif_ctrlcmd - CAIF Stack Control Signaling sent in layer.ctrlcmd().
*
* @CAIF_CTRLCMD_FLOW_OFF_IND: Flow Control is OFF, transmit function
* should stop sending data
*
* @CAIF_CTRLCMD_FLOW_ON_IND: Flow Control is ON, transmit function
* can start sending data
*
* @CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: Remote end modem has decided to close
* down channel
*
* @CAIF_CTRLCMD_INIT_RSP: Called initially when the layer below
* has finished initialization
*
* @CAIF_CTRLCMD_DEINIT_RSP: Called when de-initialization is
* complete
*
* @CAIF_CTRLCMD_INIT_FAIL_RSP: Called if initialization fails
*
* @_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: CAIF Link layer temporarily cannot
* send more packets.
* @_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND: Called if CAIF Link layer is able
* to send packets again.
* @_CAIF_CTRLCMD_PHYIF_DOWN_IND: Called if CAIF Link layer is going
* down.
*
* These commands are sent upwards in the CAIF stack to the CAIF Client.
* They are used for signaling originating from the modem or CAIF Link Layer.
* These are either responses (*_RSP) or events (*_IND).
*/
enum caif_ctrlcmd {
CAIF_CTRLCMD_FLOW_OFF_IND,
CAIF_CTRLCMD_FLOW_ON_IND,
CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND,
CAIF_CTRLCMD_INIT_RSP,
CAIF_CTRLCMD_DEINIT_RSP,
CAIF_CTRLCMD_INIT_FAIL_RSP,
_CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND,
_CAIF_CTRLCMD_PHYIF_FLOW_ON_IND,
_CAIF_CTRLCMD_PHYIF_DOWN_IND,
};
/**
* enum caif_modemcmd - Modem Control Signaling, sent from CAIF Client
* to the CAIF Link Layer or modem.
*
* @CAIF_MODEMCMD_FLOW_ON_REQ: Flow Control is ON, transmit function
* can start sending data.
*
* @CAIF_MODEMCMD_FLOW_OFF_REQ: Flow Control is OFF, transmit function
* should stop sending data.
*
* @_CAIF_MODEMCMD_PHYIF_USEFULL: Notify physical layer that it is in use
*
* @_CAIF_MODEMCMD_PHYIF_USELESS: Notify physical layer that it is
* no longer in use.
*
* These are requests sent 'downwards' in the stack.
* Flow ON, OFF can be indicated to the modem.
*/
enum caif_modemcmd {
CAIF_MODEMCMD_FLOW_ON_REQ = 0,
CAIF_MODEMCMD_FLOW_OFF_REQ = 1,
_CAIF_MODEMCMD_PHYIF_USEFULL = 3,
_CAIF_MODEMCMD_PHYIF_USELESS = 4
};
/**
* enum caif_direction - CAIF Packet Direction.
* Indicate if a packet is to be sent out or to be received in.
* @CAIF_DIR_IN: Incoming packet received.
* @CAIF_DIR_OUT: Outgoing packet to be transmitted.
*/
enum caif_direction {
CAIF_DIR_IN = 0,
CAIF_DIR_OUT = 1
};
/**
* struct cflayer - CAIF Stack layer.
* Defines the framework for the CAIF Core Stack.
* @up: Pointer up to the layer above.
* @dn: Pointer down to the layer below.
* @node: List node used when layer participate in a list.
* @receive: Packet receive function.
* @transmit: Packet transmit funciton.
* @ctrlcmd: Used for control signalling upwards in the stack.
* @modemcmd: Used for control signaling downwards in the stack.
* @id: The identity of this layer
* @name: Name of the layer.
*
* This structure defines the layered structure in CAIF.
*
* It defines CAIF layering structure, used by all CAIF Layers and the
* layers interfacing CAIF.
*
* In order to integrate with CAIF an adaptation layer on top of the CAIF stack
* and PHY layer below the CAIF stack
* must be implemented. These layer must follow the design principles below.
*
* Principles for layering of protocol layers:
* - All layers must use this structure. If embedding it, then place this
* structure first in the layer specific structure.
*
* - Each layer should not depend on any others layer's private data.
*
* - In order to send data upwards do
* layer->up->receive(layer->up, packet);
*
* - In order to send data downwards do
* layer->dn->transmit(layer->dn, info, packet);
*/
struct cflayer {
struct cflayer *up;
struct cflayer *dn;
struct list_head node;
/*
* receive() - Receive Function (non-blocking).
* Contract: Each layer must implement a receive function passing the
* CAIF packets upwards in the stack.
* Packet handling rules:
* - The CAIF packet (cfpkt) ownership is passed to the
* called receive function. This means that the the
* packet cannot be accessed after passing it to the
* above layer using up->receive().
*
* - If parsing of the packet fails, the packet must be
* destroyed and negative error code returned
* from the function.
* EXCEPTION: If the framing layer (cffrml) returns
* -EILSEQ, the packet is not freed.
*
* - If parsing succeeds (and above layers return OK) then
* the function must return a value >= 0.
*
* Returns result < 0 indicates an error, 0 or positive value
* indicates success.
*
* @layr: Pointer to the current layer the receive function is
* implemented for (this pointer).
* @cfpkt: Pointer to CaifPacket to be handled.
*/
int (*receive)(struct cflayer *layr, struct cfpkt *cfpkt);
/*
* transmit() - Transmit Function (non-blocking).
* Contract: Each layer must implement a transmit function passing the
* CAIF packet downwards in the stack.
* Packet handling rules:
* - The CAIF packet (cfpkt) ownership is passed to the
* transmit function. This means that the the packet
* cannot be accessed after passing it to the below
* layer using dn->transmit().
*
* - Upon error the packet ownership is still passed on,
* so the packet shall be freed where error is detected.
* Callers of the transmit function shall not free packets,
* but errors shall be returned.
*
* - Return value less than zero means error, zero or
* greater than zero means OK.
*
* Returns result < 0 indicates an error, 0 or positive value
* indicates success.
*
* @layr: Pointer to the current layer the receive function
* isimplemented for (this pointer).
* @cfpkt: Pointer to CaifPacket to be handled.
*/
int (*transmit) (struct cflayer *layr, struct cfpkt *cfpkt);
/*
* cttrlcmd() - Control Function upwards in CAIF Stack (non-blocking).
* Used for signaling responses (CAIF_CTRLCMD_*_RSP)
* and asynchronous events from the modem (CAIF_CTRLCMD_*_IND)
*
* @layr: Pointer to the current layer the receive function
* is implemented for (this pointer).
* @ctrl: Control Command.
*/
void (*ctrlcmd) (struct cflayer *layr, enum caif_ctrlcmd ctrl,
int phyid);
/*
* modemctrl() - Control Function used for controlling the modem.
* Used to signal down-wards in the CAIF stack.
* Returns 0 on success, < 0 upon failure.
*
* @layr: Pointer to the current layer the receive function
* is implemented for (this pointer).
* @ctrl: Control Command.
*/
int (*modemcmd) (struct cflayer *layr, enum caif_modemcmd ctrl);
unsigned int id;
char name[CAIF_LAYER_NAME_SZ];
};
/**
* layer_set_up() - Set the up pointer for a specified layer.
* @layr: Layer where up pointer shall be set.
* @above: Layer above.
*/
#define layer_set_up(layr, above) ((layr)->up = (struct cflayer *)(above))
/**
* layer_set_dn() - Set the down pointer for a specified layer.
* @layr: Layer where down pointer shall be set.
* @below: Layer below.
*/
#define layer_set_dn(layr, below) ((layr)->dn = (struct cflayer *)(below))
/**
* struct dev_info - Physical Device info information about physical layer.
* @dev: Pointer to native physical device.
* @id: Physical ID of the physical connection used by the
* logical CAIF connection. Used by service layers to
* identify their physical id to Caif MUX (CFMUXL)so
* that the MUX can add the correct physical ID to the
* packet.
*/
struct dev_info {
void *dev;
unsigned int id;
};
/**
* struct caif_payload_info - Payload information embedded in packet (sk_buff).
*
* @dev_info: Information about the receiving device.
*
* @hdr_len: Header length, used to align pay load on 32bit boundary.
*
* @channel_id: Channel ID of the logical CAIF connection.
* Used by mux to insert channel id into the caif packet.
*/
struct caif_payload_info {
struct dev_info *dev_info;
unsigned short hdr_len;
unsigned short channel_id;
};
#endif /* CAIF_LAYER_H_ */

155
include/net/caif/caif_spi.h Normal file
View file

@ -0,0 +1,155 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CAIF_SPI_H_
#define CAIF_SPI_H_
#include <net/caif/caif_device.h>
#define SPI_CMD_WR 0x00
#define SPI_CMD_RD 0x01
#define SPI_CMD_EOT 0x02
#define SPI_CMD_IND 0x04
#define SPI_DMA_BUF_LEN 8192
#define WL_SZ 2 /* 16 bits. */
#define SPI_CMD_SZ 4 /* 32 bits. */
#define SPI_IND_SZ 4 /* 32 bits. */
#define SPI_XFER 0
#define SPI_SS_ON 1
#define SPI_SS_OFF 2
#define SPI_TERMINATE 3
/* Minimum time between different levels is 50 microseconds. */
#define MIN_TRANSITION_TIME_USEC 50
/* Defines for calculating duration of SPI transfers for a particular
* number of bytes.
*/
#define SPI_MASTER_CLK_MHZ 13
#define SPI_XFER_TIME_USEC(bytes, clk) (((bytes) * 8) / clk)
/* Normally this should be aligned on the modem in order to benefit from full
* duplex transfers. However a size of 8188 provokes errors when running with
* the modem. These errors occur when packet sizes approaches 4 kB of data.
*/
#define CAIF_MAX_SPI_FRAME 4092
/* Maximum number of uplink CAIF frames that can reside in the same SPI frame.
* This number should correspond with the modem setting. The application side
* CAIF accepts any number of embedded downlink CAIF frames.
*/
#define CAIF_MAX_SPI_PKTS 9
/* Decides if SPI buffers should be prefilled with 0xFF pattern for easier
* debugging. Both TX and RX buffers will be filled before the transfer.
*/
#define CFSPI_DBG_PREFILL 0
/* Structure describing a SPI transfer. */
struct cfspi_xfer {
u16 tx_dma_len;
u16 rx_dma_len;
void *va_tx[2];
dma_addr_t pa_tx[2];
void *va_rx;
dma_addr_t pa_rx;
};
/* Structure implemented by the SPI interface. */
struct cfspi_ifc {
void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
void (*xfer_done_cb) (struct cfspi_ifc *ifc);
void *priv;
};
/* Structure implemented by SPI clients. */
struct cfspi_dev {
int (*init_xfer) (struct cfspi_xfer *xfer, struct cfspi_dev *dev);
void (*sig_xfer) (bool xfer, struct cfspi_dev *dev);
struct cfspi_ifc *ifc;
char *name;
u32 clk_mhz;
void *priv;
};
/* Enumeration describing the CAIF SPI state. */
enum cfspi_state {
CFSPI_STATE_WAITING = 0,
CFSPI_STATE_AWAKE,
CFSPI_STATE_FETCH_PKT,
CFSPI_STATE_GET_NEXT,
CFSPI_STATE_INIT_XFER,
CFSPI_STATE_WAIT_ACTIVE,
CFSPI_STATE_SIG_ACTIVE,
CFSPI_STATE_WAIT_XFER_DONE,
CFSPI_STATE_XFER_DONE,
CFSPI_STATE_WAIT_INACTIVE,
CFSPI_STATE_SIG_INACTIVE,
CFSPI_STATE_DELIVER_PKT,
CFSPI_STATE_MAX,
};
/* Structure implemented by SPI physical interfaces. */
struct cfspi {
struct caif_dev_common cfdev;
struct net_device *ndev;
struct platform_device *pdev;
struct sk_buff_head qhead;
struct sk_buff_head chead;
u16 cmd;
u16 tx_cpck_len;
u16 tx_npck_len;
u16 rx_cpck_len;
u16 rx_npck_len;
struct cfspi_ifc ifc;
struct cfspi_xfer xfer;
struct cfspi_dev *dev;
unsigned long state;
struct work_struct work;
struct workqueue_struct *wq;
struct list_head list;
int flow_off_sent;
u32 qd_low_mark;
u32 qd_high_mark;
struct completion comp;
wait_queue_head_t wait;
spinlock_t lock;
bool flow_stop;
bool slave;
bool slave_talked;
#ifdef CONFIG_DEBUG_FS
enum cfspi_state dbg_state;
u16 pcmd;
u16 tx_ppck_len;
u16 rx_ppck_len;
struct dentry *dbgfs_dir;
struct dentry *dbgfs_state;
struct dentry *dbgfs_frame;
#endif /* CONFIG_DEBUG_FS */
};
extern int spi_frm_align;
extern int spi_up_head_align;
extern int spi_up_tail_align;
extern int spi_down_head_align;
extern int spi_down_tail_align;
extern struct platform_driver cfspi_spi_driver;
void cfspi_dbg_state(struct cfspi *cfspi, int state);
int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
int cfspi_xmitlen(struct cfspi *cfspi);
int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
int cfspi_spi_remove(struct platform_device *pdev);
int cfspi_spi_probe(struct platform_device *pdev);
int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
int cfspi_xmitlen(struct cfspi *cfspi);
int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
void cfspi_xfer(struct work_struct *work);
#endif /* CAIF_SPI_H_ */

90
include/net/caif/cfcnfg.h Normal file
View file

@ -0,0 +1,90 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFCNFG_H_
#define CFCNFG_H_
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <net/caif/caif_layer.h>
#include <net/caif/cfctrl.h>
struct cfcnfg;
/**
* enum cfcnfg_phy_preference - Physical preference HW Abstraction
*
* @CFPHYPREF_UNSPECIFIED: Default physical interface
*
* @CFPHYPREF_LOW_LAT: Default physical interface for low-latency
* traffic
* @CFPHYPREF_HIGH_BW: Default physical interface for high-bandwidth
* traffic
* @CFPHYPREF_LOOP: TEST only Loopback interface simulating modem
* responses.
*
*/
enum cfcnfg_phy_preference {
CFPHYPREF_UNSPECIFIED,
CFPHYPREF_LOW_LAT,
CFPHYPREF_HIGH_BW,
CFPHYPREF_LOOP
};
/**
* cfcnfg_create() - Get the CAIF configuration object given network.
* @net: Network for the CAIF configuration object.
*/
struct cfcnfg *get_cfcnfg(struct net *net);
/**
* cfcnfg_create() - Create the CAIF configuration object.
*/
struct cfcnfg *cfcnfg_create(void);
/**
* cfcnfg_remove() - Remove the CFCNFG object
* @cfg: config object
*/
void cfcnfg_remove(struct cfcnfg *cfg);
/**
* cfcnfg_add_phy_layer() - Adds a physical layer to the CAIF stack.
* @cnfg: Pointer to a CAIF configuration object, created by
* cfcnfg_create().
* @dev: Pointer to link layer device
* @phy_layer: Specify the physical layer. The transmit function
* MUST be set in the structure.
* @pref: The phy (link layer) preference.
* @link_support: Protocol implementation for link layer specific protocol.
* @fcs: Specify if checksum is used in CAIF Framing Layer.
* @head_room: Head space needed by link specific protocol.
*/
void
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
struct net_device *dev, struct cflayer *phy_layer,
enum cfcnfg_phy_preference pref,
struct cflayer *link_support,
bool fcs, int head_room);
/**
* cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
*
* @cnfg: Pointer to a CAIF configuration object, created by
* cfcnfg_create().
* @phy_layer: Adaptation layer to be removed.
*/
int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
/**
* cfcnfg_set_phy_state() - Set the state of the physical interface device.
* @cnfg: Configuration object
* @phy_layer: Physical Layer representation
* @up: State of device
*/
int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
bool up);
#endif /* CFCNFG_H_ */

130
include/net/caif/cfctrl.h Normal file
View file

@ -0,0 +1,130 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFCTRL_H_
#define CFCTRL_H_
#include <net/caif/caif_layer.h>
#include <net/caif/cfsrvl.h>
/* CAIF Control packet commands */
enum cfctrl_cmd {
CFCTRL_CMD_LINK_SETUP = 0,
CFCTRL_CMD_LINK_DESTROY = 1,
CFCTRL_CMD_LINK_ERR = 2,
CFCTRL_CMD_ENUM = 3,
CFCTRL_CMD_SLEEP = 4,
CFCTRL_CMD_WAKE = 5,
CFCTRL_CMD_LINK_RECONF = 6,
CFCTRL_CMD_START_REASON = 7,
CFCTRL_CMD_RADIO_SET = 8,
CFCTRL_CMD_MODEM_SET = 9,
CFCTRL_CMD_MASK = 0xf
};
/* Channel types */
enum cfctrl_srv {
CFCTRL_SRV_DECM = 0,
CFCTRL_SRV_VEI = 1,
CFCTRL_SRV_VIDEO = 2,
CFCTRL_SRV_DBG = 3,
CFCTRL_SRV_DATAGRAM = 4,
CFCTRL_SRV_RFM = 5,
CFCTRL_SRV_UTIL = 6,
CFCTRL_SRV_MASK = 0xf
};
#define CFCTRL_RSP_BIT 0x20
#define CFCTRL_ERR_BIT 0x10
struct cfctrl_rsp {
void (*linksetup_rsp)(struct cflayer *layer, u8 linkid,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid);
void (*linkerror_ind)(void);
void (*enum_rsp)(void);
void (*sleep_rsp)(void);
void (*wake_rsp)(void);
void (*restart_rsp)(void);
void (*radioset_rsp)(void);
void (*reject_rsp)(struct cflayer *layer, u8 linkid,
struct cflayer *client_layer);
};
/* Link Setup Parameters for CAIF-Links. */
struct cfctrl_link_param {
enum cfctrl_srv linktype;/* (T3,T0) Type of Channel */
u8 priority; /* (P4,P0) Priority of the channel */
u8 phyid; /* (U2-U0) Physical interface to connect */
u8 endpoint; /* (E1,E0) Endpoint for data channels */
u8 chtype; /* (H1,H0) Channel-Type, applies to
* VEI, DEBUG */
union {
struct {
u8 connid; /* (D7,D0) Video LinkId */
} video;
struct {
u32 connid; /* (N31,Ngit0) Connection ID used
* for Datagram */
} datagram;
struct {
u32 connid; /* Connection ID used for RFM */
char volume[20]; /* Volume to mount for RFM */
} rfm; /* Configuration for RFM */
struct {
u16 fifosize_kb; /* Psock FIFO size in KB */
u16 fifosize_bufs; /* Psock # signal buffers */
char name[16]; /* Name of the PSOCK service */
u8 params[255]; /* Link setup Parameters> */
u16 paramlen; /* Length of Link Setup
* Parameters */
} utility; /* Configuration for Utility Links (Psock) */
} u;
};
/* This structure is used internally in CFCTRL */
struct cfctrl_request_info {
int sequence_no;
enum cfctrl_cmd cmd;
u8 channel_id;
struct cfctrl_link_param param;
struct cflayer *client_layer;
struct list_head list;
};
struct cfctrl {
struct cfsrvl serv;
struct cfctrl_rsp res;
atomic_t req_seq_no;
atomic_t rsp_seq_no;
struct list_head list;
/* Protects from simultaneous access to first_req list */
spinlock_t info_list_lock;
#ifndef CAIF_NO_LOOP
u8 loop_linkid;
int loop_linkused[256];
/* Protects simultaneous access to loop_linkid and loop_linkused */
spinlock_t loop_linkid_lock;
#endif
};
void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid);
int cfctrl_linkup_request(struct cflayer *cfctrl,
struct cfctrl_link_param *param,
struct cflayer *user_layer);
int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid,
struct cflayer *client);
struct cflayer *cfctrl_create(void);
struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer);
int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer);
void cfctrl_remove(struct cflayer *layr);
#endif /* CFCTRL_H_ */

21
include/net/caif/cffrml.h Normal file
View file

@ -0,0 +1,21 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFFRML_H_
#define CFFRML_H_
#include <net/caif/caif_layer.h>
#include <linux/netdevice.h>
struct cffrml;
struct cflayer *cffrml_create(u16 phyid, bool use_fcs);
void cffrml_free(struct cflayer *layr);
void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up);
void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn);
void cffrml_put(struct cflayer *layr);
void cffrml_hold(struct cflayer *layr);
int cffrml_refcnt_read(struct cflayer *layr);
#endif /* CFFRML_H_ */

20
include/net/caif/cfmuxl.h Normal file
View file

@ -0,0 +1,20 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFMUXL_H_
#define CFMUXL_H_
#include <net/caif/caif_layer.h>
struct cfsrvl;
struct cffrml;
struct cflayer *cfmuxl_create(void);
int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid);
struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid);
int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *up, u8 phyid);
struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 linkid);
#endif /* CFMUXL_H_ */

205
include/net/caif/cfpkt.h Normal file
View file

@ -0,0 +1,205 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFPKT_H_
#define CFPKT_H_
#include <net/caif/caif_layer.h>
#include <linux/types.h>
struct cfpkt;
/* Create a CAIF packet.
* len: Length of packet to be created
* @return New packet.
*/
struct cfpkt *cfpkt_create(u16 len);
/*
* Destroy a CAIF Packet.
* pkt Packet to be destoyed.
*/
void cfpkt_destroy(struct cfpkt *pkt);
/*
* Extract header from packet.
*
* pkt Packet to extract header data from.
* data Pointer to copy the header data into.
* len Length of head data to copy.
* @return zero on success and error code upon failure
*/
int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len);
/*
* Peek header from packet.
* Reads data from packet without changing packet.
*
* pkt Packet to extract header data from.
* data Pointer to copy the header data into.
* len Length of head data to copy.
* @return zero on success and error code upon failure
*/
int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len);
/*
* Extract header from trailer (end of packet).
*
* pkt Packet to extract header data from.
* data Pointer to copy the trailer data into.
* len Length of header data to copy.
* @return zero on success and error code upon failure
*/
int cfpkt_extr_trail(struct cfpkt *pkt, void *data, u16 len);
/*
* Add header to packet.
*
*
* pkt Packet to add header data to.
* data Pointer to data to copy into the header.
* len Length of header data to copy.
* @return zero on success and error code upon failure
*/
int cfpkt_add_head(struct cfpkt *pkt, const void *data, u16 len);
/*
* Add trailer to packet.
*
*
* pkt Packet to add trailer data to.
* data Pointer to data to copy into the trailer.
* len Length of trailer data to copy.
* @return zero on success and error code upon failure
*/
int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len);
/*
* Pad trailer on packet.
* Moves data pointer in packet, no content copied.
*
* pkt Packet in which to pad trailer.
* len Length of padding to add.
* @return zero on success and error code upon failure
*/
int cfpkt_pad_trail(struct cfpkt *pkt, u16 len);
/*
* Add a single byte to packet body (tail).
*
* pkt Packet in which to add byte.
* data Byte to add.
* @return zero on success and error code upon failure
*/
int cfpkt_addbdy(struct cfpkt *pkt, const u8 data);
/*
* Add a data to packet body (tail).
*
* pkt Packet in which to add data.
* data Pointer to data to copy into the packet body.
* len Length of data to add.
* @return zero on success and error code upon failure
*/
int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len);
/*
* Checks whether there are more data to process in packet.
* pkt Packet to check.
* @return true if more data are available in packet false otherwise
*/
bool cfpkt_more(struct cfpkt *pkt);
/*
* Checks whether the packet is erroneous,
* i.e. if it has been attempted to extract more data than available in packet
* or writing more data than has been allocated in cfpkt_create().
* pkt Packet to check.
* @return true on error false otherwise
*/
bool cfpkt_erroneous(struct cfpkt *pkt);
/*
* Get the packet length.
* pkt Packet to get length from.
* @return Number of bytes in packet.
*/
u16 cfpkt_getlen(struct cfpkt *pkt);
/*
* Set the packet length, by adjusting the trailer pointer according to length.
* pkt Packet to set length.
* len Packet length.
* @return Number of bytes in packet.
*/
int cfpkt_setlen(struct cfpkt *pkt, u16 len);
/*
* cfpkt_append - Appends a packet's data to another packet.
* dstpkt: Packet to append data into, WILL BE FREED BY THIS FUNCTION
* addpkt: Packet to be appended and automatically released,
* WILL BE FREED BY THIS FUNCTION.
* expectlen: Packet's expected total length. This should be considered
* as a hint.
* NB: Input packets will be destroyed after appending and cannot be used
* after calling this function.
* @return The new appended packet.
*/
struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, struct cfpkt *addpkt,
u16 expectlen);
/*
* cfpkt_split - Split a packet into two packets at the specified split point.
* pkt: Packet to be split (will contain the first part of the data on exit)
* pos: Position to split packet in two parts.
* @return The new packet, containing the second part of the data.
*/
struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos);
/*
* Iteration function, iterates the packet buffers from start to end.
*
* Checksum iteration function used to iterate buffers
* (we may have packets consisting of a chain of buffers)
* pkt: Packet to calculate checksum for
* iter_func: Function pointer to iteration function
* chks: Checksum calculated so far.
* buf: Pointer to the buffer to checksum
* len: Length of buf.
* data: Initial checksum value.
* @return Checksum of buffer.
*/
u16 cfpkt_iterate(struct cfpkt *pkt,
u16 (*iter_func)(u16 chks, void *buf, u16 len),
u16 data);
/* Map from a "native" packet (e.g. Linux Socket Buffer) to a CAIF packet.
* dir - Direction indicating whether this packet is to be sent or received.
* nativepkt - The native packet to be transformed to a CAIF packet
* @return The mapped CAIF Packet CFPKT.
*/
struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt);
/* Map from a CAIF packet to a "native" packet (e.g. Linux Socket Buffer).
* pkt - The CAIF packet to be transformed into a "native" packet.
* @return The native packet transformed from a CAIF packet.
*/
void *cfpkt_tonative(struct cfpkt *pkt);
/*
* Returns packet information for a packet.
* pkt Packet to get info from;
* @return Packet information
*/
struct caif_payload_info *cfpkt_info(struct cfpkt *pkt);
/** cfpkt_set_prio - set priority for a CAIF packet.
*
* @pkt: The CAIF packet to be adjusted.
* @prio: one of TC_PRIO_ constants.
*/
void cfpkt_set_prio(struct cfpkt *pkt, int prio);
#endif /* CFPKT_H_ */

12
include/net/caif/cfserl.h Normal file
View file

@ -0,0 +1,12 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFSERL_H_
#define CFSERL_H_
#include <net/caif/caif_layer.h>
struct cflayer *cfserl_create(int instance, bool use_stx);
#endif

65
include/net/caif/cfsrvl.h Normal file
View file

@ -0,0 +1,65 @@
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Sjur Brendeland
* License terms: GNU General Public License (GPL) version 2
*/
#ifndef CFSRVL_H_
#define CFSRVL_H_
#include <linux/list.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/kref.h>
#include <linux/rculist.h>
struct cfsrvl {
struct cflayer layer;
bool open;
bool phy_flow_on;
bool modem_flow_on;
bool supports_flowctrl;
void (*release)(struct cflayer *layer);
struct dev_info dev_info;
void (*hold)(struct cflayer *lyr);
void (*put)(struct cflayer *lyr);
struct rcu_head rcu;
};
struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info,
int mtu_size);
struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info);
void cfsrvl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
int phyid);
bool cfsrvl_phyid_match(struct cflayer *layer, int phyid);
void cfsrvl_init(struct cfsrvl *service,
u8 channel_id,
struct dev_info *dev_info,
bool supports_flowctrl);
bool cfsrvl_ready(struct cfsrvl *service, int *err);
u8 cfsrvl_getphyid(struct cflayer *layer);
static inline void cfsrvl_get(struct cflayer *layr)
{
struct cfsrvl *s = container_of(layr, struct cfsrvl, layer);
if (layr == NULL || layr->up == NULL || s->hold == NULL)
return;
s->hold(layr->up);
}
static inline void cfsrvl_put(struct cflayer *layr)
{
struct cfsrvl *s = container_of(layr, struct cfsrvl, layer);
if (layr == NULL || layr->up == NULL || s->hold == NULL)
return;
s->put(layr->up);
}
#endif /* CFSRVL_H_ */

View file

@ -0,0 +1,55 @@
#ifndef __NET_CFG80211_WEXT_H
#define __NET_CFG80211_WEXT_H
/*
* 802.11 device and configuration interface -- wext handlers
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
*
* 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/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
/*
* Temporary wext handlers & helper functions
*
* These are used only by drivers that aren't yet fully
* converted to cfg80211.
*/
int cfg80211_wext_giwname(struct net_device *dev,
struct iw_request_info *info,
char *name, char *extra);
int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
u32 *mode, char *extra);
int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
u32 *mode, char *extra);
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwscan(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
int cfg80211_wext_giwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
int cfg80211_wext_siwfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frag, char *extra);
int cfg80211_wext_giwfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frag, char *extra);
int cfg80211_wext_giwretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *retry, char *extra);
#endif /* __NET_CFG80211_WEXT_H */

4921
include/net/cfg80211.h Normal file

File diff suppressed because it is too large Load diff

154
include/net/checksum.h Normal file
View file

@ -0,0 +1,154 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Checksumming functions for IP, TCP, UDP and so on
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Borrows very liberally from tcp.c and ip.c, see those
* files for more names.
*
* 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.
*/
#ifndef _CHECKSUM_H
#define _CHECKSUM_H
#include <linux/errno.h>
#include <asm/types.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <asm/checksum.h>
#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
__wsum csum_and_copy_from_user (const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
{
if (access_ok(VERIFY_READ, src, len))
return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
if (len)
*err_ptr = -EFAULT;
return sum;
}
#endif
#ifndef HAVE_CSUM_COPY_USER
static __inline__ __wsum csum_and_copy_to_user
(const void *src, void __user *dst, int len, __wsum sum, int *err_ptr)
{
sum = csum_partial(src, len, sum);
if (access_ok(VERIFY_WRITE, dst, len)) {
if (copy_to_user(dst, src, len) == 0)
return sum;
}
if (len)
*err_ptr = -EFAULT;
return (__force __wsum)-1; /* invalid checksum */
}
#endif
#ifndef HAVE_ARCH_CSUM_ADD
static inline __wsum csum_add(__wsum csum, __wsum addend)
{
u32 res = (__force u32)csum;
res += (__force u32)addend;
return (__force __wsum)(res + (res < (__force u32)addend));
}
#endif
static inline __wsum csum_sub(__wsum csum, __wsum addend)
{
return csum_add(csum, ~addend);
}
static inline __sum16 csum16_add(__sum16 csum, __be16 addend)
{
u16 res = (__force u16)csum;
res += (__force u16)addend;
return (__force __sum16)(res + (res < (__force u16)addend));
}
static inline __sum16 csum16_sub(__sum16 csum, __be16 addend)
{
return csum16_add(csum, ~addend);
}
static inline __wsum
csum_block_add(__wsum csum, __wsum csum2, int offset)
{
u32 sum = (__force u32)csum2;
if (offset&1)
sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
return csum_add(csum, (__force __wsum)sum);
}
static inline __wsum
csum_block_add_ext(__wsum csum, __wsum csum2, int offset, int len)
{
return csum_block_add(csum, csum2, offset);
}
static inline __wsum
csum_block_sub(__wsum csum, __wsum csum2, int offset)
{
u32 sum = (__force u32)csum2;
if (offset&1)
sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
return csum_sub(csum, (__force __wsum)sum);
}
static inline __wsum csum_unfold(__sum16 n)
{
return (__force __wsum)n;
}
static inline __wsum csum_partial_ext(const void *buff, int len, __wsum sum)
{
return csum_partial(buff, len, sum);
}
#define CSUM_MANGLED_0 ((__force __sum16)0xffff)
static inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to)
{
*sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), from), to));
}
/* Implements RFC 1624 (Incremental Internet Checksum)
* 3. Discussion states :
* HC' = ~(~HC + ~m + m')
* m : old value of a 16bit field
* m' : new value of a 16bit field
*/
static inline void csum_replace2(__sum16 *sum, __be16 old, __be16 new)
{
*sum = ~csum16_add(csum16_sub(~(*sum), old), new);
}
struct sk_buff;
void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
__be32 from, __be32 to, int pseudohdr);
void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
const __be32 *from, const __be32 *to,
int pseudohdr);
static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
__be16 from, __be16 to,
int pseudohdr)
{
inet_proto_csum_replace4(sum, skb, (__force __be32)from,
(__force __be32)to, pseudohdr);
}
#endif

327
include/net/cipso_ipv4.h Normal file
View file

@ -0,0 +1,327 @@
/*
* CIPSO - Commercial IP Security Option
*
* This is an implementation of the CIPSO 2.2 protocol as specified in
* draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
* FIPS-188, copies of both documents can be found in the Documentation
* directory. While CIPSO never became a full IETF RFC standard many vendors
* have chosen to adopt the protocol and over the years it has become a
* de-facto standard for labeled networking.
*
* Author: Paul Moore <paul@paul-moore.com>
*
*/
/*
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _CIPSO_IPV4_H
#define _CIPSO_IPV4_H
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <net/netlabel.h>
#include <net/request_sock.h>
#include <linux/atomic.h>
#include <asm/unaligned.h>
/* known doi values */
#define CIPSO_V4_DOI_UNKNOWN 0x00000000
/* standard tag types */
#define CIPSO_V4_TAG_INVALID 0
#define CIPSO_V4_TAG_RBITMAP 1
#define CIPSO_V4_TAG_ENUM 2
#define CIPSO_V4_TAG_RANGE 5
#define CIPSO_V4_TAG_PBITMAP 6
#define CIPSO_V4_TAG_FREEFORM 7
/* non-standard tag types (tags > 127) */
#define CIPSO_V4_TAG_LOCAL 128
/* doi mapping types */
#define CIPSO_V4_MAP_UNKNOWN 0
#define CIPSO_V4_MAP_TRANS 1
#define CIPSO_V4_MAP_PASS 2
#define CIPSO_V4_MAP_LOCAL 3
/* limits */
#define CIPSO_V4_MAX_REM_LVLS 255
#define CIPSO_V4_INV_LVL 0x80000000
#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1)
#define CIPSO_V4_MAX_REM_CATS 65534
#define CIPSO_V4_INV_CAT 0x80000000
#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1)
/*
* CIPSO DOI definitions
*/
/* DOI definition struct */
#define CIPSO_V4_TAG_MAXCNT 5
struct cipso_v4_doi {
u32 doi;
u32 type;
union {
struct cipso_v4_std_map_tbl *std;
} map;
u8 tags[CIPSO_V4_TAG_MAXCNT];
atomic_t refcount;
struct list_head list;
struct rcu_head rcu;
};
/* Standard CIPSO mapping table */
/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
* bit is set then consider that value as unspecified, meaning the
* mapping for that particular level/category is invalid */
struct cipso_v4_std_map_tbl {
struct {
u32 *cipso;
u32 *local;
u32 cipso_size;
u32 local_size;
} lvl;
struct {
u32 *cipso;
u32 *local;
u32 cipso_size;
u32 local_size;
} cat;
};
/*
* Sysctl Variables
*/
#ifdef CONFIG_NETLABEL
extern int cipso_v4_cache_enabled;
extern int cipso_v4_cache_bucketsize;
extern int cipso_v4_rbm_optfmt;
extern int cipso_v4_rbm_strictvalid;
#endif
/*
* DOI List Functions
*/
#ifdef CONFIG_NETLABEL
int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
struct netlbl_audit *audit_info);
void cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def);
int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg);
#else
static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
struct netlbl_audit *audit_info)
{
return -ENOSYS;
}
static inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
{
return;
}
static inline int cipso_v4_doi_remove(u32 doi,
struct netlbl_audit *audit_info)
{
return 0;
}
static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
{
return NULL;
}
static inline int cipso_v4_doi_walk(u32 *skip_cnt,
int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
void *cb_arg)
{
return 0;
}
static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
const char *domain)
{
return -ENOSYS;
}
static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
const char *domain)
{
return 0;
}
#endif /* CONFIG_NETLABEL */
/*
* Label Mapping Cache Functions
*/
#ifdef CONFIG_NETLABEL
void cipso_v4_cache_invalidate(void);
int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr);
#else
static inline void cipso_v4_cache_invalidate(void)
{
return;
}
static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr)
{
return 0;
}
#endif /* CONFIG_NETLABEL */
/*
* Protocol Handling Functions
*/
#ifdef CONFIG_NETLABEL
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
int cipso_v4_getattr(const unsigned char *cipso,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
void cipso_v4_sock_delattr(struct sock *sk);
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
int cipso_v4_req_setattr(struct request_sock *req,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
void cipso_v4_req_delattr(struct request_sock *req);
int cipso_v4_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_delattr(struct sk_buff *skb);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
unsigned char *cipso_v4_optptr(const struct sk_buff *skb);
int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
#else
static inline void cipso_v4_error(struct sk_buff *skb,
int error,
u32 gateway)
{
return;
}
static inline int cipso_v4_getattr(const unsigned char *cipso,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_sock_setattr(struct sock *sk,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline void cipso_v4_sock_delattr(struct sock *sk)
{
}
static inline int cipso_v4_sock_getattr(struct sock *sk,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_req_setattr(struct request_sock *req,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline void cipso_v4_req_delattr(struct request_sock *req)
{
return;
}
static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
const struct cipso_v4_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
{
return -ENOSYS;
}
static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
{
return NULL;
}
static inline int cipso_v4_validate(const struct sk_buff *skb,
unsigned char **option)
{
unsigned char *opt = *option;
unsigned char err_offset = 0;
u8 opt_len = opt[1];
u8 opt_iter;
u8 tag_len;
if (opt_len < 8) {
err_offset = 1;
goto out;
}
if (get_unaligned_be32(&opt[2]) == 0) {
err_offset = 2;
goto out;
}
for (opt_iter = 6; opt_iter < opt_len;) {
tag_len = opt[opt_iter + 1];
if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
err_offset = opt_iter + 1;
goto out;
}
opt_iter += tag_len;
}
out:
*option = opt + err_offset;
return err_offset;
}
#endif /* CONFIG_NETLABEL */
#endif /* _CIPSO_IPV4_H */

57
include/net/cls_cgroup.h Normal file
View file

@ -0,0 +1,57 @@
/*
* cls_cgroup.h Control Group Classifier
*
* Authors: Thomas Graf <tgraf@suug.ch>
*
* 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.
*
*/
#ifndef _NET_CLS_CGROUP_H
#define _NET_CLS_CGROUP_H
#include <linux/cgroup.h>
#include <linux/hardirq.h>
#include <linux/rcupdate.h>
#include <net/sock.h>
#ifdef CONFIG_CGROUP_NET_CLASSID
struct cgroup_cls_state {
struct cgroup_subsys_state css;
u32 classid;
};
struct cgroup_cls_state *task_cls_state(struct task_struct *p);
static inline u32 task_cls_classid(struct task_struct *p)
{
u32 classid;
if (in_interrupt())
return 0;
rcu_read_lock();
classid = container_of(task_css(p, net_cls_cgrp_id),
struct cgroup_cls_state, css)->classid;
rcu_read_unlock();
return classid;
}
static inline void sock_update_classid(struct sock *sk)
{
u32 classid;
classid = task_cls_classid(current);
if (classid != sk->sk_classid)
sk->sk_classid = classid;
}
#else /* !CONFIG_CGROUP_NET_CLASSID */
static inline void sock_update_classid(struct sock *sk)
{
}
#endif /* CONFIG_CGROUP_NET_CLASSID */
#endif /* _NET_CLS_CGROUP_H */

355
include/net/codel.h Normal file
View file

@ -0,0 +1,355 @@
#ifndef __NET_SCHED_CODEL_H
#define __NET_SCHED_CODEL_H
/*
* Codel - The Controlled-Delay Active Queue Management algorithm
*
* Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
* Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
* Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
* Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#include <linux/types.h>
#include <linux/ktime.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>
#include <net/inet_ecn.h>
/* Controlling Queue Delay (CoDel) algorithm
* =========================================
* Source : Kathleen Nichols and Van Jacobson
* http://queue.acm.org/detail.cfm?id=2209336
*
* Implemented on linux by Dave Taht and Eric Dumazet
*/
/* CoDel uses a 1024 nsec clock, encoded in u32
* This gives a range of 2199 seconds, because of signed compares
*/
typedef u32 codel_time_t;
typedef s32 codel_tdiff_t;
#define CODEL_SHIFT 10
#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT)
static inline codel_time_t codel_get_time(void)
{
u64 ns = ktime_get_ns();
return ns >> CODEL_SHIFT;
}
/* Dealing with timer wrapping, according to RFC 1982, as desc in wikipedia:
* https://en.wikipedia.org/wiki/Serial_number_arithmetic#General_Solution
* codel_time_after(a,b) returns true if the time a is after time b.
*/
#define codel_time_after(a, b) \
(typecheck(codel_time_t, a) && \
typecheck(codel_time_t, b) && \
((s32)((a) - (b)) > 0))
#define codel_time_before(a, b) codel_time_after(b, a)
#define codel_time_after_eq(a, b) \
(typecheck(codel_time_t, a) && \
typecheck(codel_time_t, b) && \
((s32)((a) - (b)) >= 0))
#define codel_time_before_eq(a, b) codel_time_after_eq(b, a)
/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */
struct codel_skb_cb {
codel_time_t enqueue_time;
};
static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb)
{
qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb));
return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data;
}
static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb)
{
return get_codel_cb(skb)->enqueue_time;
}
static void codel_set_enqueue_time(struct sk_buff *skb)
{
get_codel_cb(skb)->enqueue_time = codel_get_time();
}
static inline u32 codel_time_to_us(codel_time_t val)
{
u64 valns = ((u64)val << CODEL_SHIFT);
do_div(valns, NSEC_PER_USEC);
return (u32)valns;
}
/**
* struct codel_params - contains codel parameters
* @target: target queue size (in time units)
* @interval: width of moving time window
* @ecn: is Explicit Congestion Notification enabled
*/
struct codel_params {
codel_time_t target;
codel_time_t interval;
bool ecn;
};
/**
* struct codel_vars - contains codel variables
* @count: how many drops we've done since the last time we
* entered dropping state
* @lastcount: count at entry to dropping state
* @dropping: set to true if in dropping state
* @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1
* @first_above_time: when we went (or will go) continuously above target
* for interval
* @drop_next: time to drop next packet, or when we dropped last
* @ldelay: sojourn time of last dequeued packet
*/
struct codel_vars {
u32 count;
u32 lastcount;
bool dropping;
u16 rec_inv_sqrt;
codel_time_t first_above_time;
codel_time_t drop_next;
codel_time_t ldelay;
};
#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
/* needed shift to get a Q0.32 number from rec_inv_sqrt */
#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
/**
* struct codel_stats - contains codel shared variables and stats
* @maxpacket: largest packet we've seen so far
* @drop_count: temp count of dropped packets in dequeue()
* ecn_mark: number of packets we ECN marked instead of dropping
*/
struct codel_stats {
u32 maxpacket;
u32 drop_count;
u32 ecn_mark;
};
static void codel_params_init(struct codel_params *params)
{
params->interval = MS2TIME(100);
params->target = MS2TIME(5);
params->ecn = false;
}
static void codel_vars_init(struct codel_vars *vars)
{
memset(vars, 0, sizeof(*vars));
}
static void codel_stats_init(struct codel_stats *stats)
{
stats->maxpacket = 256;
}
/*
* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
* new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
*
* Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
*/
static void codel_Newton_step(struct codel_vars *vars)
{
u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
val >>= 2; /* avoid overflow in following multiply */
val = (val * invsqrt) >> (32 - 2 + 1);
vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
}
/*
* CoDel control_law is t + interval/sqrt(count)
* We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid
* both sqrt() and divide operation.
*/
static codel_time_t codel_control_law(codel_time_t t,
codel_time_t interval,
u32 rec_inv_sqrt)
{
return t + reciprocal_scale(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
}
static bool codel_should_drop(const struct sk_buff *skb,
struct Qdisc *sch,
struct codel_vars *vars,
struct codel_params *params,
struct codel_stats *stats,
codel_time_t now)
{
bool ok_to_drop;
if (!skb) {
vars->first_above_time = 0;
return false;
}
vars->ldelay = now - codel_get_enqueue_time(skb);
sch->qstats.backlog -= qdisc_pkt_len(skb);
if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
stats->maxpacket = qdisc_pkt_len(skb);
if (codel_time_before(vars->ldelay, params->target) ||
sch->qstats.backlog <= stats->maxpacket) {
/* went below - stay below for at least interval */
vars->first_above_time = 0;
return false;
}
ok_to_drop = false;
if (vars->first_above_time == 0) {
/* just went above from below. If we stay above
* for at least interval we'll say it's ok to drop
*/
vars->first_above_time = now + params->interval;
} else if (codel_time_after(now, vars->first_above_time)) {
ok_to_drop = true;
}
return ok_to_drop;
}
typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars,
struct Qdisc *sch);
static struct sk_buff *codel_dequeue(struct Qdisc *sch,
struct codel_params *params,
struct codel_vars *vars,
struct codel_stats *stats,
codel_skb_dequeue_t dequeue_func)
{
struct sk_buff *skb = dequeue_func(vars, sch);
codel_time_t now;
bool drop;
if (!skb) {
vars->dropping = false;
return skb;
}
now = codel_get_time();
drop = codel_should_drop(skb, sch, vars, params, stats, now);
if (vars->dropping) {
if (!drop) {
/* sojourn time below target - leave dropping state */
vars->dropping = false;
} else if (codel_time_after_eq(now, vars->drop_next)) {
/* It's time for the next drop. Drop the current
* packet and dequeue the next. The dequeue might
* take us out of dropping state.
* If not, schedule the next drop.
* A large backlog might result in drop rates so high
* that the next drop should happen now,
* hence the while loop.
*/
while (vars->dropping &&
codel_time_after_eq(now, vars->drop_next)) {
vars->count++; /* dont care of possible wrap
* since there is no more divide
*/
codel_Newton_step(vars);
if (params->ecn && INET_ECN_set_ce(skb)) {
stats->ecn_mark++;
vars->drop_next =
codel_control_law(vars->drop_next,
params->interval,
vars->rec_inv_sqrt);
goto end;
}
qdisc_drop(skb, sch);
stats->drop_count++;
skb = dequeue_func(vars, sch);
if (!codel_should_drop(skb, sch,
vars, params, stats, now)) {
/* leave dropping state */
vars->dropping = false;
} else {
/* and schedule the next drop */
vars->drop_next =
codel_control_law(vars->drop_next,
params->interval,
vars->rec_inv_sqrt);
}
}
}
} else if (drop) {
u32 delta;
if (params->ecn && INET_ECN_set_ce(skb)) {
stats->ecn_mark++;
} else {
qdisc_drop(skb, sch);
stats->drop_count++;
skb = dequeue_func(vars, sch);
drop = codel_should_drop(skb, sch, vars, params,
stats, now);
}
vars->dropping = true;
/* if min went above target close to when we last went below it
* assume that the drop rate that controlled the queue on the
* last cycle is a good starting point to control it now.
*/
delta = vars->count - vars->lastcount;
if (delta > 1 &&
codel_time_before(now - vars->drop_next,
16 * params->interval)) {
vars->count = delta;
/* we dont care if rec_inv_sqrt approximation
* is not very precise :
* Next Newton steps will correct it quadratically.
*/
codel_Newton_step(vars);
} else {
vars->count = 1;
vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
}
vars->lastcount = vars->count;
vars->drop_next = codel_control_law(now, params->interval,
vars->rec_inv_sqrt);
}
end:
return skb;
}
#endif

69
include/net/compat.h Normal file
View file

@ -0,0 +1,69 @@
#ifndef NET_COMPAT_H
#define NET_COMPAT_H
struct sock;
#if defined(CONFIG_COMPAT)
#include <linux/compat.h>
struct compat_msghdr {
compat_uptr_t msg_name; /* void * */
compat_int_t msg_namelen;
compat_uptr_t msg_iov; /* struct compat_iovec * */
compat_size_t msg_iovlen;
compat_uptr_t msg_control; /* void * */
compat_size_t msg_controllen;
compat_uint_t msg_flags;
};
struct compat_mmsghdr {
struct compat_msghdr msg_hdr;
compat_uint_t msg_len;
};
struct compat_cmsghdr {
compat_size_t cmsg_len;
compat_int_t cmsg_level;
compat_int_t cmsg_type;
};
int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#else /* defined(CONFIG_COMPAT) */
/*
* To avoid compiler warnings:
*/
#define compat_msghdr msghdr
#define compat_mmsghdr mmsghdr
#endif /* defined(CONFIG_COMPAT) */
int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *);
int verify_compat_iovec(struct msghdr *, struct iovec *,
struct sockaddr_storage *, int);
asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
unsigned int);
asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
unsigned int, unsigned int);
asmlinkage long compat_sys_recvmsg(int, struct compat_msghdr __user *,
unsigned int);
asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *,
unsigned int, unsigned int,
struct compat_timespec __user *);
asmlinkage long compat_sys_getsockopt(int, int, int, char __user *,
int __user *);
int put_cmsg_compat(struct msghdr*, int, int, int, void *);
int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *,
unsigned char *, int);
int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
int (*)(struct sock *, int, int, char __user *,
unsigned int));
int compat_mc_getsockopt(struct sock *, int, int, char __user *, int __user *,
int (*)(struct sock *, int, int, char __user *,
int __user *));
#endif /* NET_COMPAT_H */

20
include/net/datalink.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef _NET_INET_DATALINK_H_
#define _NET_INET_DATALINK_H_
struct datalink_proto {
unsigned char type[8];
struct llc_sap *sap;
unsigned short header_length;
int (*rcvfunc)(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
int (*request)(struct datalink_proto *, struct sk_buff *,
unsigned char *);
struct list_head node;
};
struct datalink_proto *make_EII_client(void);
void destroy_EII_client(struct datalink_proto *dl);
#endif

48
include/net/dcbevent.h Normal file
View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2010, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*
* Author: John Fastabend <john.r.fastabend@intel.com>
*/
#ifndef _DCB_EVENT_H
#define _DCB_EVENT_H
enum dcbevent_notif_type {
DCB_APP_EVENT = 1,
};
#ifdef CONFIG_DCB
int register_dcbevent_notifier(struct notifier_block *nb);
int unregister_dcbevent_notifier(struct notifier_block *nb);
int call_dcbevent_notifiers(unsigned long val, void *v);
#else
static inline int
register_dcbevent_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int unregister_dcbevent_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int call_dcbevent_notifiers(unsigned long val, void *v)
{
return 0;
}
#endif /* CONFIG_DCB */
#endif

103
include/net/dcbnl.h Normal file
View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2008, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*
* Author: Lucy Liu <lucy.liu@intel.com>
*/
#ifndef __NET_DCBNL_H__
#define __NET_DCBNL_H__
#include <linux/dcbnl.h>
struct dcb_app_type {
int ifindex;
struct dcb_app app;
struct list_head list;
u8 dcbx;
};
int dcb_setapp(struct net_device *, struct dcb_app *);
u8 dcb_getapp(struct net_device *, struct dcb_app *);
int dcb_ieee_setapp(struct net_device *, struct dcb_app *);
int dcb_ieee_delapp(struct net_device *, struct dcb_app *);
u8 dcb_ieee_getapp_mask(struct net_device *, struct dcb_app *);
int dcbnl_ieee_notify(struct net_device *dev, int event, int cmd,
u32 seq, u32 pid);
int dcbnl_cee_notify(struct net_device *dev, int event, int cmd,
u32 seq, u32 pid);
/*
* Ops struct for the netlink callbacks. Used by DCB-enabled drivers through
* the netdevice struct.
*/
struct dcbnl_rtnl_ops {
/* IEEE 802.1Qaz std */
int (*ieee_getets) (struct net_device *, struct ieee_ets *);
int (*ieee_setets) (struct net_device *, struct ieee_ets *);
int (*ieee_getmaxrate) (struct net_device *, struct ieee_maxrate *);
int (*ieee_setmaxrate) (struct net_device *, struct ieee_maxrate *);
int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
int (*ieee_getapp) (struct net_device *, struct dcb_app *);
int (*ieee_setapp) (struct net_device *, struct dcb_app *);
int (*ieee_delapp) (struct net_device *, struct dcb_app *);
int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);
/* CEE std */
u8 (*getstate)(struct net_device *);
u8 (*setstate)(struct net_device *, u8);
void (*getpermhwaddr)(struct net_device *, u8 *);
void (*setpgtccfgtx)(struct net_device *, int, u8, u8, u8, u8);
void (*setpgbwgcfgtx)(struct net_device *, int, u8);
void (*setpgtccfgrx)(struct net_device *, int, u8, u8, u8, u8);
void (*setpgbwgcfgrx)(struct net_device *, int, u8);
void (*getpgtccfgtx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
void (*getpgbwgcfgtx)(struct net_device *, int, u8 *);
void (*getpgtccfgrx)(struct net_device *, int, u8 *, u8 *, u8 *, u8 *);
void (*getpgbwgcfgrx)(struct net_device *, int, u8 *);
void (*setpfccfg)(struct net_device *, int, u8);
void (*getpfccfg)(struct net_device *, int, u8 *);
u8 (*setall)(struct net_device *);
u8 (*getcap)(struct net_device *, int, u8 *);
int (*getnumtcs)(struct net_device *, int, u8 *);
int (*setnumtcs)(struct net_device *, int, u8);
u8 (*getpfcstate)(struct net_device *);
void (*setpfcstate)(struct net_device *, u8);
void (*getbcncfg)(struct net_device *, int, u32 *);
void (*setbcncfg)(struct net_device *, int, u32);
void (*getbcnrp)(struct net_device *, int, u8 *);
void (*setbcnrp)(struct net_device *, int, u8);
int (*setapp)(struct net_device *, u8, u16, u8);
int (*getapp)(struct net_device *, u8, u16);
u8 (*getfeatcfg)(struct net_device *, int, u8 *);
u8 (*setfeatcfg)(struct net_device *, int, u8);
/* DCBX configuration */
u8 (*getdcbx)(struct net_device *);
u8 (*setdcbx)(struct net_device *, u8);
/* peer apps */
int (*peer_getappinfo)(struct net_device *, struct dcb_peer_app_info *,
u16 *);
int (*peer_getapptable)(struct net_device *, struct dcb_app *);
/* CEE peer */
int (*cee_peer_getpg) (struct net_device *, struct cee_pg *);
int (*cee_peer_getpfc) (struct net_device *, struct cee_pfc *);
};
#endif /* __NET_DCBNL_H__ */

237
include/net/dn.h Normal file
View file

@ -0,0 +1,237 @@
#ifndef _NET_DN_H
#define _NET_DN_H
#include <linux/dn.h>
#include <net/sock.h>
#include <net/flow.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
struct dn_scp /* Session Control Port */
{
unsigned char state;
#define DN_O 1 /* Open */
#define DN_CR 2 /* Connect Receive */
#define DN_DR 3 /* Disconnect Reject */
#define DN_DRC 4 /* Discon. Rej. Complete*/
#define DN_CC 5 /* Connect Confirm */
#define DN_CI 6 /* Connect Initiate */
#define DN_NR 7 /* No resources */
#define DN_NC 8 /* No communication */
#define DN_CD 9 /* Connect Delivery */
#define DN_RJ 10 /* Rejected */
#define DN_RUN 11 /* Running */
#define DN_DI 12 /* Disconnect Initiate */
#define DN_DIC 13 /* Disconnect Complete */
#define DN_DN 14 /* Disconnect Notificat */
#define DN_CL 15 /* Closed */
#define DN_CN 16 /* Closed Notification */
__le16 addrloc;
__le16 addrrem;
__u16 numdat;
__u16 numoth;
__u16 numoth_rcv;
__u16 numdat_rcv;
__u16 ackxmt_dat;
__u16 ackxmt_oth;
__u16 ackrcv_dat;
__u16 ackrcv_oth;
__u8 flowrem_sw;
__u8 flowloc_sw;
#define DN_SEND 2
#define DN_DONTSEND 1
#define DN_NOCHANGE 0
__u16 flowrem_dat;
__u16 flowrem_oth;
__u16 flowloc_dat;
__u16 flowloc_oth;
__u8 services_rem;
__u8 services_loc;
__u8 info_rem;
__u8 info_loc;
__u16 segsize_rem;
__u16 segsize_loc;
__u8 nonagle;
__u8 multi_ireq;
__u8 accept_mode;
unsigned long seg_total; /* Running total of current segment */
struct optdata_dn conndata_in;
struct optdata_dn conndata_out;
struct optdata_dn discdata_in;
struct optdata_dn discdata_out;
struct accessdata_dn accessdata;
struct sockaddr_dn addr; /* Local address */
struct sockaddr_dn peer; /* Remote address */
/*
* In this case the RTT estimation is not specified in the
* docs, nor is any back off algorithm. Here we follow well
* known tcp algorithms with a few small variations.
*
* snd_window: Max number of packets we send before we wait for
* an ack to come back. This will become part of a
* more complicated scheme when we support flow
* control.
*
* nsp_srtt: Round-Trip-Time (x8) in jiffies. This is a rolling
* average.
* nsp_rttvar: Round-Trip-Time-Varience (x4) in jiffies. This is the
* varience of the smoothed average (but calculated in
* a simpler way than for normal statistical varience
* calculations).
*
* nsp_rxtshift: Backoff counter. Value is zero normally, each time
* a packet is lost is increases by one until an ack
* is received. Its used to index an array of backoff
* multipliers.
*/
#define NSP_MIN_WINDOW 1
#define NSP_MAX_WINDOW (0x07fe)
unsigned long max_window;
unsigned long snd_window;
#define NSP_INITIAL_SRTT (HZ)
unsigned long nsp_srtt;
#define NSP_INITIAL_RTTVAR (HZ*3)
unsigned long nsp_rttvar;
#define NSP_MAXRXTSHIFT 12
unsigned long nsp_rxtshift;
/*
* Output queues, one for data, one for otherdata/linkservice
*/
struct sk_buff_head data_xmit_queue;
struct sk_buff_head other_xmit_queue;
/*
* Input queue for other data
*/
struct sk_buff_head other_receive_queue;
int other_report;
/*
* Stuff to do with the slow timer
*/
unsigned long stamp; /* time of last transmit */
unsigned long persist;
int (*persist_fxn)(struct sock *sk);
unsigned long keepalive;
void (*keepalive_fxn)(struct sock *sk);
/*
* This stuff is for the fast timer for delayed acks
*/
struct timer_list delack_timer;
int delack_pending;
void (*delack_fxn)(struct sock *sk);
};
static inline struct dn_scp *DN_SK(struct sock *sk)
{
return (struct dn_scp *)(sk + 1);
}
/*
* src,dst : Source and Destination DECnet addresses
* hops : Number of hops through the network
* dst_port, src_port : NSP port numbers
* services, info : Useful data extracted from conninit messages
* rt_flags : Routing flags byte
* nsp_flags : NSP layer flags byte
* segsize : Size of segment
* segnum : Number, for data, otherdata and linkservice
* xmit_count : Number of times we've transmitted this skb
* stamp : Time stamp of most recent transmission, used in RTT calculations
* iif: Input interface number
*
* As a general policy, this structure keeps all addresses in network
* byte order, and all else in host byte order. Thus dst, src, dst_port
* and src_port are in network order. All else is in host order.
*
*/
#define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb)
struct dn_skb_cb {
__le16 dst;
__le16 src;
__u16 hops;
__le16 dst_port;
__le16 src_port;
__u8 services;
__u8 info;
__u8 rt_flags;
__u8 nsp_flags;
__u16 segsize;
__u16 segnum;
__u16 xmit_count;
unsigned long stamp;
int iif;
};
static inline __le16 dn_eth2dn(unsigned char *ethaddr)
{
return get_unaligned((__le16 *)(ethaddr + 4));
}
static inline __le16 dn_saddr2dn(struct sockaddr_dn *saddr)
{
return *(__le16 *)saddr->sdn_nodeaddr;
}
static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr)
{
__u16 a = le16_to_cpu(addr);
ethaddr[0] = 0xAA;
ethaddr[1] = 0x00;
ethaddr[2] = 0x04;
ethaddr[3] = 0x00;
ethaddr[4] = (__u8)(a & 0xff);
ethaddr[5] = (__u8)(a >> 8);
}
static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
{
fld->fld_sport = scp->addrloc;
fld->fld_dport = scp->addrrem;
}
unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
void dn_register_sysctl(void);
void dn_unregister_sysctl(void);
#define DN_MENUVER_ACC 0x01
#define DN_MENUVER_USR 0x02
#define DN_MENUVER_PRX 0x04
#define DN_MENUVER_UIC 0x08
struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
struct sock *dn_find_by_skb(struct sk_buff *skb);
#define DN_ASCBUF_LEN 9
char *dn_addr2asc(__u16, char *);
int dn_destroy_timer(struct sock *sk);
int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf,
unsigned char type);
int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr,
unsigned char *type);
void dn_start_slow_timer(struct sock *sk);
void dn_stop_slow_timer(struct sock *sk);
extern __le16 decnet_address;
extern int decnet_debug_level;
extern int decnet_time_wait;
extern int decnet_dn_count;
extern int decnet_di_count;
extern int decnet_dr_count;
extern int decnet_no_fc_max_cwnd;
extern long sysctl_decnet_mem[3];
extern int sysctl_decnet_wmem[3];
extern int sysctl_decnet_rmem[3];
#endif /* _NET_DN_H */

198
include/net/dn_dev.h Normal file
View file

@ -0,0 +1,198 @@
#ifndef _NET_DN_DEV_H
#define _NET_DN_DEV_H
struct dn_dev;
struct dn_ifaddr {
struct dn_ifaddr __rcu *ifa_next;
struct dn_dev *ifa_dev;
__le16 ifa_local;
__le16 ifa_address;
__u32 ifa_flags;
__u8 ifa_scope;
char ifa_label[IFNAMSIZ];
struct rcu_head rcu;
};
#define DN_DEV_S_RU 0 /* Run - working normally */
#define DN_DEV_S_CR 1 /* Circuit Rejected */
#define DN_DEV_S_DS 2 /* Data Link Start */
#define DN_DEV_S_RI 3 /* Routing Layer Initialize */
#define DN_DEV_S_RV 4 /* Routing Layer Verify */
#define DN_DEV_S_RC 5 /* Routing Layer Complete */
#define DN_DEV_S_OF 6 /* Off */
#define DN_DEV_S_HA 7 /* Halt */
/*
* The dn_dev_parms structure contains the set of parameters
* for each device (hence inclusion in the dn_dev structure)
* and an array is used to store the default types of supported
* device (in dn_dev.c).
*
* The type field matches the ARPHRD_ constants and is used in
* searching the list for supported devices when new devices
* come up.
*
* The mode field is used to find out if a device is broadcast,
* multipoint, or pointopoint. Please note that DECnet thinks
* different ways about devices to the rest of the kernel
* so the normal IFF_xxx flags are invalid here. For devices
* which can be any combination of the previously mentioned
* attributes, you can set this on a per device basis by
* installing an up() routine.
*
* The device state field, defines the initial state in which the
* device will come up. In the dn_dev structure, it is the actual
* state.
*
* Things have changed here. I've killed timer1 since it's a user space
* issue for a user space routing deamon to sort out. The kernel does
* not need to be bothered with it.
*
* Timers:
* t2 - Rate limit timer, min time between routing and hello messages
* t3 - Hello timer, send hello messages when it expires
*
* Callbacks:
* up() - Called to initialize device, return value can veto use of
* device with DECnet.
* down() - Called to turn device off when it goes down
* timer3() - Called once for each ifaddr when timer 3 goes off
*
* sysctl - Hook for sysctl things
*
*/
struct dn_dev_parms {
int type; /* ARPHRD_xxx */
int mode; /* Broadcast, Unicast, Mulitpoint */
#define DN_DEV_BCAST 1
#define DN_DEV_UCAST 2
#define DN_DEV_MPOINT 4
int state; /* Initial state */
int forwarding; /* 0=EndNode, 1=L1Router, 2=L2Router */
unsigned long t2; /* Default value of t2 */
unsigned long t3; /* Default value of t3 */
int priority; /* Priority to be a router */
char *name; /* Name for sysctl */
int (*up)(struct net_device *);
void (*down)(struct net_device *);
void (*timer3)(struct net_device *, struct dn_ifaddr *ifa);
void *sysctl;
};
struct dn_dev {
struct dn_ifaddr __rcu *ifa_list;
struct net_device *dev;
struct dn_dev_parms parms;
char use_long;
struct timer_list timer;
unsigned long t3;
struct neigh_parms *neigh_parms;
__u8 addr[ETH_ALEN];
struct neighbour *router; /* Default router on circuit */
struct neighbour *peer; /* Peer on pointopoint links */
unsigned long uptime; /* Time device went up in jiffies */
};
struct dn_short_packet {
__u8 msgflg;
__le16 dstnode;
__le16 srcnode;
__u8 forward;
} __packed;
struct dn_long_packet {
__u8 msgflg;
__u8 d_area;
__u8 d_subarea;
__u8 d_id[6];
__u8 s_area;
__u8 s_subarea;
__u8 s_id[6];
__u8 nl2;
__u8 visit_ct;
__u8 s_class;
__u8 pt;
} __packed;
/*------------------------- DRP - Routing messages ---------------------*/
struct endnode_hello_message {
__u8 msgflg;
__u8 tiver[3];
__u8 id[6];
__u8 iinfo;
__le16 blksize;
__u8 area;
__u8 seed[8];
__u8 neighbor[6];
__le16 timer;
__u8 mpd;
__u8 datalen;
__u8 data[2];
} __packed;
struct rtnode_hello_message {
__u8 msgflg;
__u8 tiver[3];
__u8 id[6];
__u8 iinfo;
__le16 blksize;
__u8 priority;
__u8 area;
__le16 timer;
__u8 mpd;
} __packed;
void dn_dev_init(void);
void dn_dev_cleanup(void);
int dn_dev_ioctl(unsigned int cmd, void __user *arg);
void dn_dev_devices_off(void);
void dn_dev_devices_on(void);
void dn_dev_init_pkt(struct sk_buff *skb);
void dn_dev_veri_pkt(struct sk_buff *skb);
void dn_dev_hello(struct sk_buff *skb);
void dn_dev_up(struct net_device *);
void dn_dev_down(struct net_device *);
int dn_dev_set_default(struct net_device *dev, int force);
struct net_device *dn_dev_get_default(void);
int dn_dev_bind_default(__le16 *addr);
int register_dnaddr_notifier(struct notifier_block *nb);
int unregister_dnaddr_notifier(struct notifier_block *nb);
static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
{
struct dn_dev *dn_db;
struct dn_ifaddr *ifa;
int res = 0;
rcu_read_lock();
dn_db = rcu_dereference(dev->dn_ptr);
if (dn_db == NULL) {
printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
goto out;
}
for (ifa = rcu_dereference(dn_db->ifa_list);
ifa != NULL;
ifa = rcu_dereference(ifa->ifa_next))
if ((addr ^ ifa->ifa_local) == 0) {
res = 1;
break;
}
out:
rcu_read_unlock();
return res;
}
#endif /* _NET_DN_DEV_H */

165
include/net/dn_fib.h Normal file
View file

@ -0,0 +1,165 @@
#ifndef _NET_DN_FIB_H
#define _NET_DN_FIB_H
#include <linux/netlink.h>
extern const struct nla_policy rtm_dn_policy[];
struct dn_fib_res {
struct fib_rule *r;
struct dn_fib_info *fi;
unsigned char prefixlen;
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
};
struct dn_fib_nh {
struct net_device *nh_dev;
unsigned int nh_flags;
unsigned char nh_scope;
int nh_weight;
int nh_power;
int nh_oif;
__le16 nh_gw;
};
struct dn_fib_info {
struct dn_fib_info *fib_next;
struct dn_fib_info *fib_prev;
int fib_treeref;
atomic_t fib_clntref;
int fib_dead;
unsigned int fib_flags;
int fib_protocol;
__le16 fib_prefsrc;
__u32 fib_priority;
__u32 fib_metrics[RTAX_MAX];
int fib_nhs;
int fib_power;
struct dn_fib_nh fib_nh[0];
#define dn_fib_dev fib_nh[0].nh_dev
};
#define DN_FIB_RES_RESET(res) ((res).nh_sel = 0)
#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
#define DN_FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res))
#define DN_FIB_RES_GW(res) (DN_FIB_RES_NH(res).nh_gw)
#define DN_FIB_RES_DEV(res) (DN_FIB_RES_NH(res).nh_dev)
#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif)
typedef struct {
__le16 datum;
} dn_fib_key_t;
typedef struct {
__le16 datum;
} dn_fib_hash_t;
typedef struct {
__u16 datum;
} dn_fib_idx_t;
struct dn_fib_node {
struct dn_fib_node *fn_next;
struct dn_fib_info *fn_info;
#define DN_FIB_INFO(f) ((f)->fn_info)
dn_fib_key_t fn_key;
u8 fn_type;
u8 fn_scope;
u8 fn_state;
};
struct dn_fib_table {
struct hlist_node hlist;
u32 n;
int (*insert)(struct dn_fib_table *t, struct rtmsg *r,
struct nlattr *attrs[], struct nlmsghdr *n,
struct netlink_skb_parms *req);
int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
struct nlattr *attrs[], struct nlmsghdr *n,
struct netlink_skb_parms *req);
int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
struct dn_fib_res *res);
int (*flush)(struct dn_fib_table *t);
int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
unsigned char data[0];
};
#ifdef CONFIG_DECNET_ROUTER
/*
* dn_fib.c
*/
void dn_fib_init(void);
void dn_fib_cleanup(void);
int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
struct nlattr *attrs[],
const struct nlmsghdr *nlh, int *errp);
int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
const struct flowidn *fld, struct dn_fib_res *res);
void dn_fib_release_info(struct dn_fib_info *fi);
void dn_fib_flush(void);
void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res);
/*
* dn_tables.c
*/
struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
struct dn_fib_table *dn_fib_empty_table(void);
void dn_fib_table_init(void);
void dn_fib_table_cleanup(void);
/*
* dn_rules.c
*/
void dn_fib_rules_init(void);
void dn_fib_rules_cleanup(void);
unsigned int dnet_addr_type(__le16 addr);
int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
void dn_fib_free_info(struct dn_fib_info *fi);
static inline void dn_fib_info_put(struct dn_fib_info *fi)
{
if (atomic_dec_and_test(&fi->fib_clntref))
dn_fib_free_info(fi);
}
static inline void dn_fib_res_put(struct dn_fib_res *res)
{
if (res->fi)
dn_fib_info_put(res->fi);
if (res->r)
fib_rule_put(res->r);
}
#else /* Endnode */
#define dn_fib_init() do { } while(0)
#define dn_fib_cleanup() do { } while(0)
#define dn_fib_lookup(fl, res) (-ESRCH)
#define dn_fib_info_put(fi) do { } while(0)
#define dn_fib_select_multipath(fl, res) do { } while(0)
#define dn_fib_rules_policy(saddr,res,flags) (0)
#define dn_fib_res_put(res) do { } while(0)
#endif /* CONFIG_DECNET_ROUTER */
static inline __le16 dnet_make_mask(int n)
{
if (n)
return cpu_to_le16(~((1 << (16 - n)) - 1));
return cpu_to_le16(0);
}
#endif /* _NET_DN_FIB_H */

28
include/net/dn_neigh.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef _NET_DN_NEIGH_H
#define _NET_DN_NEIGH_H
/*
* The position of the first two fields of
* this structure are critical - SJW
*/
struct dn_neigh {
struct neighbour n;
__le16 addr;
unsigned long flags;
#define DN_NDFLAG_R1 0x0001 /* Router L1 */
#define DN_NDFLAG_R2 0x0002 /* Router L2 */
#define DN_NDFLAG_P3 0x0004 /* Phase III Node */
unsigned long blksize;
__u8 priority;
};
void dn_neigh_init(void);
void dn_neigh_cleanup(void);
int dn_neigh_router_hello(struct sk_buff *skb);
int dn_neigh_endnode_hello(struct sk_buff *skb);
void dn_neigh_pointopoint_hello(struct sk_buff *skb);
int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
extern struct neigh_table dn_neigh_table;
#endif /* _NET_DN_NEIGH_H */

204
include/net/dn_nsp.h Normal file
View file

@ -0,0 +1,204 @@
#ifndef _NET_DN_NSP_H
#define _NET_DN_NSP_H
/******************************************************************************
(c) 1995-1998 E.M. Serrat emserrat@geocities.com
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
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.
*******************************************************************************/
/* dn_nsp.c functions prototyping */
void dn_nsp_send_data_ack(struct sock *sk);
void dn_nsp_send_oth_ack(struct sock *sk);
void dn_nsp_delayed_ack(struct sock *sk);
void dn_send_conn_ack(struct sock *sk);
void dn_send_conn_conf(struct sock *sk, gfp_t gfp);
void dn_nsp_send_disc(struct sock *sk, unsigned char type,
unsigned short reason, gfp_t gfp);
void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
unsigned short reason);
void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval);
void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
void dn_nsp_output(struct sock *sk);
int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb,
struct sk_buff_head *q, unsigned short acknum);
void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp,
int oob);
unsigned long dn_nsp_persist(struct sock *sk);
int dn_nsp_xmit_timeout(struct sock *sk);
int dn_nsp_rx(struct sk_buff *);
int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock,
long timeo, int *err);
#define NSP_REASON_OK 0 /* No error */
#define NSP_REASON_NR 1 /* No resources */
#define NSP_REASON_UN 2 /* Unrecognised node name */
#define NSP_REASON_SD 3 /* Node shutting down */
#define NSP_REASON_ID 4 /* Invalid destination end user */
#define NSP_REASON_ER 5 /* End user lacks resources */
#define NSP_REASON_OB 6 /* Object too busy */
#define NSP_REASON_US 7 /* Unspecified error */
#define NSP_REASON_TP 8 /* Third-Party abort */
#define NSP_REASON_EA 9 /* End user has aborted the link */
#define NSP_REASON_IF 10 /* Invalid node name format */
#define NSP_REASON_LS 11 /* Local node shutdown */
#define NSP_REASON_LL 32 /* Node lacks logical-link resources */
#define NSP_REASON_LE 33 /* End user lacks logical-link resources */
#define NSP_REASON_UR 34 /* Unacceptable RQSTRID or PASSWORD field */
#define NSP_REASON_UA 36 /* Unacceptable ACCOUNT field */
#define NSP_REASON_TM 38 /* End user timed out logical link */
#define NSP_REASON_NU 39 /* Node unreachable */
#define NSP_REASON_NL 41 /* No-link message */
#define NSP_REASON_DC 42 /* Disconnect confirm */
#define NSP_REASON_IO 43 /* Image data field overflow */
#define NSP_DISCINIT 0x38
#define NSP_DISCCONF 0x48
/*------------------------- NSP - messages ------------------------------*/
/* Data Messages */
/*---------------*/
/* Data Messages (data segment/interrupt/link service) */
struct nsp_data_seg_msg {
__u8 msgflg;
__le16 dstaddr;
__le16 srcaddr;
} __packed;
struct nsp_data_opt_msg {
__le16 acknum;
__le16 segnum;
__le16 lsflgs;
} __packed;
struct nsp_data_opt_msg1 {
__le16 acknum;
__le16 segnum;
} __packed;
/* Acknowledgment Message (data/other data) */
struct nsp_data_ack_msg {
__u8 msgflg;
__le16 dstaddr;
__le16 srcaddr;
__le16 acknum;
} __packed;
/* Connect Acknowledgment Message */
struct nsp_conn_ack_msg {
__u8 msgflg;
__le16 dstaddr;
} __packed;
/* Connect Initiate/Retransmit Initiate/Connect Confirm */
struct nsp_conn_init_msg {
__u8 msgflg;
#define NSP_CI 0x18 /* Connect Initiate */
#define NSP_RCI 0x68 /* Retrans. Conn Init */
__le16 dstaddr;
__le16 srcaddr;
__u8 services;
#define NSP_FC_NONE 0x00 /* Flow Control None */
#define NSP_FC_SRC 0x04 /* Seg Req. Count */
#define NSP_FC_SCMC 0x08 /* Sess. Control Mess */
#define NSP_FC_MASK 0x0c /* FC type mask */
__u8 info;
__le16 segsize;
} __packed;
/* Disconnect Initiate/Disconnect Confirm */
struct nsp_disconn_init_msg {
__u8 msgflg;
__le16 dstaddr;
__le16 srcaddr;
__le16 reason;
} __packed;
struct srcobj_fmt {
__u8 format;
__u8 task;
__le16 grpcode;
__le16 usrcode;
__u8 dlen;
} __packed;
/*
* A collection of functions for manipulating the sequence
* numbers used in NSP. Similar in operation to the functions
* of the same name in TCP.
*/
static __inline__ int dn_before(__u16 seq1, __u16 seq2)
{
seq1 &= 0x0fff;
seq2 &= 0x0fff;
return (int)((seq1 - seq2) & 0x0fff) > 2048;
}
static __inline__ int dn_after(__u16 seq1, __u16 seq2)
{
seq1 &= 0x0fff;
seq2 &= 0x0fff;
return (int)((seq2 - seq1) & 0x0fff) > 2048;
}
static __inline__ int dn_equal(__u16 seq1, __u16 seq2)
{
return ((seq1 ^ seq2) & 0x0fff) == 0;
}
static __inline__ int dn_before_or_equal(__u16 seq1, __u16 seq2)
{
return (dn_before(seq1, seq2) || dn_equal(seq1, seq2));
}
static __inline__ void seq_add(__u16 *seq, __u16 off)
{
(*seq) += off;
(*seq) &= 0x0fff;
}
static __inline__ int seq_next(__u16 seq1, __u16 seq2)
{
return dn_equal(seq1 + 1, seq2);
}
/*
* Can we delay the ack ?
*/
static __inline__ int sendack(__u16 seq)
{
return (int)((seq & 0x1000) ? 0 : 1);
}
/*
* Is socket congested ?
*/
static __inline__ int dn_congested(struct sock *sk)
{
return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
}
#define DN_MAX_NSP_DATA_HEADER (11)
#endif /* _NET_DN_NSP_H */

122
include/net/dn_route.h Normal file
View file

@ -0,0 +1,122 @@
#ifndef _NET_DN_ROUTE_H
#define _NET_DN_ROUTE_H
/******************************************************************************
(c) 1995-1998 E.M. Serrat emserrat@geocities.com
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
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.
*******************************************************************************/
struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *,
struct sock *sk, int flags);
int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
void dn_rt_cache_flush(int delay);
int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);
/* Masks for flags field */
#define DN_RT_F_PID 0x07 /* Mask for packet type */
#define DN_RT_F_PF 0x80 /* Padding Follows */
#define DN_RT_F_VER 0x40 /* Version =0 discard packet if ==1 */
#define DN_RT_F_IE 0x20 /* Intra Ethernet, Reserved in short pkt */
#define DN_RT_F_RTS 0x10 /* Packet is being returned to sender */
#define DN_RT_F_RQR 0x08 /* Return packet to sender upon non-delivery */
/* Mask for types of routing packets */
#define DN_RT_PKT_MSK 0x06
/* Types of routing packets */
#define DN_RT_PKT_SHORT 0x02 /* Short routing packet */
#define DN_RT_PKT_LONG 0x06 /* Long routing packet */
/* Mask for control/routing selection */
#define DN_RT_PKT_CNTL 0x01 /* Set to 1 if a control packet */
/* Types of control packets */
#define DN_RT_CNTL_MSK 0x0f /* Mask for control packets */
#define DN_RT_PKT_INIT 0x01 /* Initialisation packet */
#define DN_RT_PKT_VERI 0x03 /* Verification Message */
#define DN_RT_PKT_HELO 0x05 /* Hello and Test Message */
#define DN_RT_PKT_L1RT 0x07 /* Level 1 Routing Message */
#define DN_RT_PKT_L2RT 0x09 /* Level 2 Routing Message */
#define DN_RT_PKT_ERTH 0x0b /* Ethernet Router Hello */
#define DN_RT_PKT_EEDH 0x0d /* Ethernet EndNode Hello */
/* Values for info field in hello message */
#define DN_RT_INFO_TYPE 0x03 /* Type mask */
#define DN_RT_INFO_L1RT 0x02 /* L1 Router */
#define DN_RT_INFO_L2RT 0x01 /* L2 Router */
#define DN_RT_INFO_ENDN 0x03 /* EndNode */
#define DN_RT_INFO_VERI 0x04 /* Verification Reqd. */
#define DN_RT_INFO_RJCT 0x08 /* Reject Flag, Reserved */
#define DN_RT_INFO_VFLD 0x10 /* Verification Failed, Reserved */
#define DN_RT_INFO_NOML 0x20 /* No Multicast traffic accepted */
#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested */
/*
* The fl structure is what we used to look up the route.
* The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
* except for local input routes, where the rt_saddr = fl.fld_dst and
* rt_daddr = fl.fld_src to allow the route to be used for returning
* packets to the originating host.
*/
struct dn_route {
struct dst_entry dst;
struct neighbour *n;
struct flowidn fld;
__le16 rt_saddr;
__le16 rt_daddr;
__le16 rt_gateway;
__le16 rt_local_src; /* Source used for forwarding packets */
__le16 rt_src_map;
__le16 rt_dst_map;
unsigned int rt_flags;
unsigned int rt_type;
};
static inline bool dn_is_input_route(struct dn_route *rt)
{
return rt->fld.flowidn_iif != 0;
}
static inline bool dn_is_output_route(struct dn_route *rt)
{
return rt->fld.flowidn_iif == 0;
}
void dn_route_init(void);
void dn_route_cleanup(void);
#include <net/sock.h>
#include <linux/if_arp.h>
static inline void dn_rt_send(struct sk_buff *skb)
{
dev_queue_xmit(skb);
}
static inline void dn_rt_finish_output(struct sk_buff *skb, char *dst, char *src)
{
struct net_device *dev = skb->dev;
if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
dst = NULL;
if (dev_hard_header(skb, dev, ETH_P_DNA_RT, dst, src, skb->len) >= 0)
dn_rt_send(skb);
else
kfree_skb(skb);
}
#endif /* _NET_DN_ROUTE_H */

260
include/net/dsa.h Normal file
View file

@ -0,0 +1,260 @@
/*
* include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
* Copyright (c) 2008-2009 Marvell Semiconductor
*
* 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.
*/
#ifndef __LINUX_NET_DSA_H
#define __LINUX_NET_DSA_H
#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/ethtool.h>
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = 0,
DSA_TAG_PROTO_DSA,
DSA_TAG_PROTO_TRAILER,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
};
#define DSA_MAX_SWITCHES 4
#define DSA_MAX_PORTS 12
struct dsa_chip_data {
/*
* How to access the switch configuration registers.
*/
struct device *host_dev;
int sw_addr;
/* Device tree node pointer for this specific switch chip
* used during switch setup in case additional properties
* and resources needs to be used
*/
struct device_node *of_node;
/*
* The names of the switch's ports. Use "cpu" to
* designate the switch port that the cpu is connected to,
* "dsa" to indicate that this port is a DSA link to
* another switch, NULL to indicate the port is unused,
* or any other string to indicate this is a physical port.
*/
char *port_names[DSA_MAX_PORTS];
struct device_node *port_dn[DSA_MAX_PORTS];
/*
* An array (with nr_chips elements) of which element [a]
* indicates which port on this switch should be used to
* send packets to that are destined for switch a. Can be
* NULL if there is only one switch chip.
*/
s8 *rtable;
};
struct dsa_platform_data {
/*
* Reference to a Linux network interface that connects
* to the root switch chip of the tree.
*/
struct device *netdev;
/*
* Info structs describing each of the switch chips
* connected via this network interface.
*/
int nr_chips;
struct dsa_chip_data *chip;
};
struct packet_type;
struct dsa_switch_tree {
/*
* Configuration data for the platform device that owns
* this dsa switch tree instance.
*/
struct dsa_platform_data *pd;
/*
* Reference to network device to use, and which tagging
* protocol to use.
*/
struct net_device *master_netdev;
int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt,
struct net_device *orig_dev);
enum dsa_tag_protocol tag_protocol;
/*
* The switch and port to which the CPU is attached.
*/
s8 cpu_switch;
s8 cpu_port;
/*
* Link state polling.
*/
int link_poll_needed;
struct work_struct link_poll_work;
struct timer_list link_poll_timer;
/*
* Data for the individual switch chips.
*/
struct dsa_switch *ds[DSA_MAX_SWITCHES];
};
struct dsa_switch {
/*
* Parent switch tree, and switch index.
*/
struct dsa_switch_tree *dst;
int index;
/*
* Configuration data for this switch.
*/
struct dsa_chip_data *pd;
/*
* The used switch driver.
*/
struct dsa_switch_driver *drv;
/*
* Reference to host device to use.
*/
struct device *master_dev;
/*
* Slave mii_bus and devices for the individual ports.
*/
u32 dsa_port_mask;
u32 phys_port_mask;
u32 phys_mii_mask;
struct mii_bus *slave_mii_bus;
struct net_device *ports[DSA_MAX_PORTS];
};
static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
{
return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
}
static inline u8 dsa_upstream_port(struct dsa_switch *ds)
{
struct dsa_switch_tree *dst = ds->dst;
/*
* If this is the root switch (i.e. the switch that connects
* to the CPU), return the cpu port number on this switch.
* Else return the (DSA) port number that connects to the
* switch that is one hop closer to the cpu.
*/
if (dst->cpu_switch == ds->index)
return dst->cpu_port;
else
return ds->pd->rtable[dst->cpu_switch];
}
struct dsa_switch_driver {
struct list_head list;
enum dsa_tag_protocol tag_protocol;
int priv_size;
/*
* Probing and setup.
*/
char *(*probe)(struct device *host_dev, int sw_addr);
int (*setup)(struct dsa_switch *ds);
int (*set_addr)(struct dsa_switch *ds, u8 *addr);
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
/*
* Access to the switch's PHY registers.
*/
int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
int (*phy_write)(struct dsa_switch *ds, int port,
int regnum, u16 val);
/*
* Link state polling and IRQ handling.
*/
void (*poll_link)(struct dsa_switch *ds);
/*
* Link state adjustment (called from libphy)
*/
void (*adjust_link)(struct dsa_switch *ds, int port,
struct phy_device *phydev);
void (*fixed_link_update)(struct dsa_switch *ds, int port,
struct fixed_phy_status *st);
/*
* ethtool hardware statistics.
*/
void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data);
void (*get_ethtool_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
int (*get_sset_count)(struct dsa_switch *ds);
/*
* ethtool Wake-on-LAN
*/
void (*get_wol)(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *w);
int (*set_wol)(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *w);
/*
* Suspend and resume
*/
int (*suspend)(struct dsa_switch *ds);
int (*resume)(struct dsa_switch *ds);
/*
* Port enable/disable
*/
int (*port_enable)(struct dsa_switch *ds, int port,
struct phy_device *phy);
void (*port_disable)(struct dsa_switch *ds, int port,
struct phy_device *phy);
/*
* EEE setttings
*/
int (*set_eee)(struct dsa_switch *ds, int port,
struct phy_device *phydev,
struct ethtool_eee *e);
int (*get_eee)(struct dsa_switch *ds, int port,
struct ethtool_eee *e);
};
void register_switch_driver(struct dsa_switch_driver *type);
void unregister_switch_driver(struct dsa_switch_driver *type);
struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev);
static inline void *ds_to_priv(struct dsa_switch *ds)
{
return (void *)(ds + 1);
}
static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
{
return dst->rcv != NULL;
}
#endif

52
include/net/dsfield.h Normal file
View file

@ -0,0 +1,52 @@
/* include/net/dsfield.h - Manipulation of the Differentiated Services field */
/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
#ifndef __NET_DSFIELD_H
#define __NET_DSFIELD_H
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <asm/byteorder.h>
static inline __u8 ipv4_get_dsfield(const struct iphdr *iph)
{
return iph->tos;
}
static inline __u8 ipv6_get_dsfield(const struct ipv6hdr *ipv6h)
{
return ntohs(*(const __be16 *)ipv6h) >> 4;
}
static inline void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
__u8 value)
{
__u32 check = ntohs((__force __be16)iph->check);
__u8 dsfield;
dsfield = (iph->tos & mask) | value;
check += iph->tos;
if ((check+1) >> 16) check = (check+1) & 0xffff;
check -= dsfield;
check += check >> 16; /* adjust carry */
iph->check = (__force __sum16)htons(check);
iph->tos = dsfield;
}
static inline void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
__u8 value)
{
__be16 *p = (__force __be16 *)ipv6h;
*p = (*p & htons((((u16)mask << 4) | 0xf00f))) | htons((u16)value << 4);
}
#endif

526
include/net/dst.h Normal file
View file

@ -0,0 +1,526 @@
/*
* net/dst.h Protocol independent destination cache definitions.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
*/
#ifndef _NET_DST_H
#define _NET_DST_H
#include <net/dst_ops.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#include <linux/bug.h>
#include <linux/jiffies.h>
#include <net/neighbour.h>
#include <asm/processor.h>
#define DST_GC_MIN (HZ/10)
#define DST_GC_INC (HZ/2)
#define DST_GC_MAX (120*HZ)
/* Each dst_entry has reference count and sits in some parent list(s).
* When it is removed from parent list, it is "freed" (dst_free).
* After this it enters dead state (dst->obsolete > 0) and if its refcnt
* is zero, it can be destroyed immediately, otherwise it is added
* to gc list and garbage collector periodically checks the refcnt.
*/
struct sk_buff;
struct dst_entry {
struct rcu_head rcu_head;
struct dst_entry *child;
struct net_device *dev;
struct dst_ops *ops;
unsigned long _metrics;
unsigned long expires;
struct dst_entry *path;
struct dst_entry *from;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
#else
void *__pad1;
#endif
int (*input)(struct sk_buff *);
int (*output)(struct sock *sk, struct sk_buff *skb);
unsigned short flags;
#define DST_HOST 0x0001
#define DST_NOXFRM 0x0002
#define DST_NOPOLICY 0x0004
#define DST_NOHASH 0x0008
#define DST_NOCACHE 0x0010
#define DST_NOCOUNT 0x0020
#define DST_FAKE_RTABLE 0x0040
#define DST_XFRM_TUNNEL 0x0080
#define DST_XFRM_QUEUE 0x0100
unsigned short pending_confirm;
short error;
/* A non-zero value of dst->obsolete forces by-hand validation
* of the route entry. Positive values are set by the generic
* dst layer to indicate that the entry has been forcefully
* destroyed.
*
* Negative values are used by the implementation layer code to
* force invocation of the dst_ops->check() method.
*/
short obsolete;
#define DST_OBSOLETE_NONE 0
#define DST_OBSOLETE_DEAD 2
#define DST_OBSOLETE_FORCE_CHK -1
#define DST_OBSOLETE_KILL -2
unsigned short header_len; /* more space at head required */
unsigned short trailer_len; /* space to reserve at tail */
#ifdef CONFIG_IP_ROUTE_CLASSID
__u32 tclassid;
#else
__u32 __pad2;
#endif
/*
* Align __refcnt to a 64 bytes alignment
* (L1_CACHE_SIZE would be too much)
*/
#ifdef CONFIG_64BIT
long __pad_to_align_refcnt[2];
#endif
/*
* __refcnt wants to be on a different cache line from
* input/output/ops or performance tanks badly
*/
atomic_t __refcnt; /* client references */
int __use;
unsigned long lastuse;
union {
struct dst_entry *next;
struct rtable __rcu *rt_next;
struct rt6_info *rt6_next;
struct dn_route __rcu *dn_next;
};
};
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
extern const u32 dst_default_metrics[];
#define DST_METRICS_READ_ONLY 0x1UL
#define DST_METRICS_FORCE_OVERWRITE 0x2UL
#define DST_METRICS_FLAGS 0x3UL
#define __DST_METRICS_PTR(Y) \
((u32 *)((Y) & ~DST_METRICS_FLAGS))
#define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics)
static inline bool dst_metrics_read_only(const struct dst_entry *dst)
{
return dst->_metrics & DST_METRICS_READ_ONLY;
}
static inline void dst_metrics_set_force_overwrite(struct dst_entry *dst)
{
dst->_metrics |= DST_METRICS_FORCE_OVERWRITE;
}
void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
static inline void dst_destroy_metrics_generic(struct dst_entry *dst)
{
unsigned long val = dst->_metrics;
if (!(val & DST_METRICS_READ_ONLY))
__dst_destroy_metrics_generic(dst, val);
}
static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst)
{
unsigned long p = dst->_metrics;
BUG_ON(!p);
if (p & DST_METRICS_READ_ONLY)
return dst->ops->cow_metrics(dst, p);
return __DST_METRICS_PTR(p);
}
/* This may only be invoked before the entry has reached global
* visibility.
*/
static inline void dst_init_metrics(struct dst_entry *dst,
const u32 *src_metrics,
bool read_only)
{
dst->_metrics = ((unsigned long) src_metrics) |
(read_only ? DST_METRICS_READ_ONLY : 0);
}
static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
{
u32 *dst_metrics = dst_metrics_write_ptr(dest);
if (dst_metrics) {
u32 *src_metrics = DST_METRICS_PTR(src);
memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32));
}
}
static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
{
return DST_METRICS_PTR(dst);
}
static inline u32
dst_metric_raw(const struct dst_entry *dst, const int metric)
{
u32 *p = DST_METRICS_PTR(dst);
return p[metric-1];
}
static inline u32
dst_metric(const struct dst_entry *dst, const int metric)
{
WARN_ON_ONCE(metric == RTAX_HOPLIMIT ||
metric == RTAX_ADVMSS ||
metric == RTAX_MTU);
return dst_metric_raw(dst, metric);
}
static inline u32
dst_metric_advmss(const struct dst_entry *dst)
{
u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS);
if (!advmss)
advmss = dst->ops->default_advmss(dst);
return advmss;
}
static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
{
u32 *p = dst_metrics_write_ptr(dst);
if (p)
p[metric-1] = val;
}
static inline u32
dst_feature(const struct dst_entry *dst, u32 feature)
{
return dst_metric(dst, RTAX_FEATURES) & feature;
}
static inline u32 dst_mtu(const struct dst_entry *dst)
{
return dst->ops->mtu(dst);
}
/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
{
return msecs_to_jiffies(dst_metric(dst, metric));
}
static inline u32
dst_allfrag(const struct dst_entry *dst)
{
int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG);
return ret;
}
static inline int
dst_metric_locked(const struct dst_entry *dst, int metric)
{
return dst_metric(dst, RTAX_LOCK) & (1<<metric);
}
static inline void dst_hold(struct dst_entry *dst)
{
/*
* If your kernel compilation stops here, please check
* __pad_to_align_refcnt declaration in struct dst_entry
*/
BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
atomic_inc(&dst->__refcnt);
}
static inline void dst_use(struct dst_entry *dst, unsigned long time)
{
dst_hold(dst);
dst->__use++;
dst->lastuse = time;
}
static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
{
dst->__use++;
dst->lastuse = time;
}
static inline struct dst_entry *dst_clone(struct dst_entry *dst)
{
if (dst)
atomic_inc(&dst->__refcnt);
return dst;
}
void dst_release(struct dst_entry *dst);
static inline void refdst_drop(unsigned long refdst)
{
if (!(refdst & SKB_DST_NOREF))
dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK));
}
/**
* skb_dst_drop - drops skb dst
* @skb: buffer
*
* Drops dst reference count if a reference was taken.
*/
static inline void skb_dst_drop(struct sk_buff *skb)
{
if (skb->_skb_refdst) {
refdst_drop(skb->_skb_refdst);
skb->_skb_refdst = 0UL;
}
}
static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb)
{
nskb->_skb_refdst = oskb->_skb_refdst;
if (!(nskb->_skb_refdst & SKB_DST_NOREF))
dst_clone(skb_dst(nskb));
}
/**
* skb_dst_force - makes sure skb dst is refcounted
* @skb: buffer
*
* If dst is not yet refcounted, let's do it
*/
static inline void skb_dst_force(struct sk_buff *skb)
{
if (skb_dst_is_noref(skb)) {
WARN_ON(!rcu_read_lock_held());
skb->_skb_refdst &= ~SKB_DST_NOREF;
dst_clone(skb_dst(skb));
}
}
/**
* __skb_tunnel_rx - prepare skb for rx reinsert
* @skb: buffer
* @dev: tunnel device
* @net: netns for packet i/o
*
* After decapsulation, packet is going to re-enter (netif_rx()) our stack,
* so make some cleanups. (no accounting done)
*/
static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
struct net *net)
{
skb->dev = dev;
/*
* Clear hash so that we can recalulate the hash for the
* encapsulated packet, unless we have already determine the hash
* over the L4 4-tuple.
*/
skb_clear_hash_if_not_l4(skb);
skb_set_queue_mapping(skb, 0);
skb_scrub_packet(skb, !net_eq(net, dev_net(dev)));
}
/**
* skb_tunnel_rx - prepare skb for rx reinsert
* @skb: buffer
* @dev: tunnel device
*
* After decapsulation, packet is going to re-enter (netif_rx()) our stack,
* so make some cleanups, and perform accounting.
* Note: this accounting is not SMP safe.
*/
static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
struct net *net)
{
/* TODO : stats should be SMP safe */
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
__skb_tunnel_rx(skb, dev, net);
}
/* Children define the path of the packet through the
* Linux networking. Thus, destinations are stackable.
*/
static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
{
struct dst_entry *child = dst_clone(skb_dst(skb)->child);
skb_dst_drop(skb);
return child;
}
int dst_discard_sk(struct sock *sk, struct sk_buff *skb);
static inline int dst_discard(struct sk_buff *skb)
{
return dst_discard_sk(skb->sk, skb);
}
void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref,
int initial_obsolete, unsigned short flags);
void __dst_free(struct dst_entry *dst);
struct dst_entry *dst_destroy(struct dst_entry *dst);
static inline void dst_free(struct dst_entry *dst)
{
if (dst->obsolete > 0)
return;
if (!atomic_read(&dst->__refcnt)) {
dst = dst_destroy(dst);
if (!dst)
return;
}
__dst_free(dst);
}
static inline void dst_rcu_free(struct rcu_head *head)
{
struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head);
dst_free(dst);
}
static inline void dst_confirm(struct dst_entry *dst)
{
dst->pending_confirm = 1;
}
static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
struct sk_buff *skb)
{
const struct hh_cache *hh;
if (dst->pending_confirm) {
unsigned long now = jiffies;
dst->pending_confirm = 0;
/* avoid dirtying neighbour */
if (n->confirmed != now)
n->confirmed = now;
}
hh = &n->hh;
if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
return neigh_hh_output(hh, skb);
else
return n->output(n, skb);
}
static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr);
return IS_ERR(n) ? NULL : n;
}
static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
struct sk_buff *skb)
{
struct neighbour *n = dst->ops->neigh_lookup(dst, skb, NULL);
return IS_ERR(n) ? NULL : n;
}
static inline void dst_link_failure(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
if (dst && dst->ops && dst->ops->link_failure)
dst->ops->link_failure(skb);
}
static inline void dst_set_expires(struct dst_entry *dst, int timeout)
{
unsigned long expires = jiffies + timeout;
if (expires == 0)
expires = 1;
if (dst->expires == 0 || time_before(expires, dst->expires))
dst->expires = expires;
}
/* Output packet to network from transport. */
static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb)
{
return skb_dst(skb)->output(sk, skb);
}
static inline int dst_output(struct sk_buff *skb)
{
return dst_output_sk(skb->sk, skb);
}
/* Input packet from network to transport. */
static inline int dst_input(struct sk_buff *skb)
{
return skb_dst(skb)->input(skb);
}
static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
{
if (dst->obsolete)
dst = dst->ops->check(dst, cookie);
return dst;
}
void dst_init(void);
/* Flags for xfrm_lookup flags argument. */
enum {
XFRM_LOOKUP_ICMP = 1 << 0,
XFRM_LOOKUP_QUEUE = 1 << 1,
};
struct flowi;
#ifndef CONFIG_XFRM
static inline struct dst_entry *xfrm_lookup(struct net *net,
struct dst_entry *dst_orig,
const struct flowi *fl, struct sock *sk,
int flags)
{
return dst_orig;
}
static inline struct dst_entry *xfrm_lookup_route(struct net *net,
struct dst_entry *dst_orig,
const struct flowi *fl,
struct sock *sk,
int flags)
{
return dst_orig;
}
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
{
return NULL;
}
#else
struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl, struct sock *sk,
int flags);
struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl, struct sock *sk,
int flags);
/* skb attached with this dst needs transformation if dst->xfrm is valid */
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
{
return dst->xfrm;
}
#endif
#endif /* _NET_DST_H */

74
include/net/dst_ops.h Normal file
View file

@ -0,0 +1,74 @@
#ifndef _NET_DST_OPS_H
#define _NET_DST_OPS_H
#include <linux/types.h>
#include <linux/percpu_counter.h>
#include <linux/cache.h>
struct dst_entry;
struct kmem_cachep;
struct net_device;
struct sk_buff;
struct sock;
struct dst_ops {
unsigned short family;
__be16 protocol;
unsigned int gc_thresh;
int (*gc)(struct dst_ops *ops);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
unsigned int (*default_advmss)(const struct dst_entry *);
unsigned int (*mtu)(const struct dst_entry *);
u32 * (*cow_metrics)(struct dst_entry *, unsigned long);
void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *,
struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu);
void (*redirect)(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb);
int (*local_out)(struct sk_buff *skb);
struct neighbour * (*neigh_lookup)(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr);
struct kmem_cache *kmem_cachep;
struct percpu_counter pcpuc_entries ____cacheline_aligned_in_smp;
};
static inline int dst_entries_get_fast(struct dst_ops *dst)
{
return percpu_counter_read_positive(&dst->pcpuc_entries);
}
static inline int dst_entries_get_slow(struct dst_ops *dst)
{
int res;
local_bh_disable();
res = percpu_counter_sum_positive(&dst->pcpuc_entries);
local_bh_enable();
return res;
}
static inline void dst_entries_add(struct dst_ops *dst, int val)
{
local_bh_disable();
percpu_counter_add(&dst->pcpuc_entries, val);
local_bh_enable();
}
static inline int dst_entries_init(struct dst_ops *dst)
{
return percpu_counter_init(&dst->pcpuc_entries, 0, GFP_KERNEL);
}
static inline void dst_entries_destroy(struct dst_ops *dst)
{
percpu_counter_destroy(&dst->pcpuc_entries);
}
#endif

13
include/net/esp.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef _NET_ESP_H
#define _NET_ESP_H
#include <linux/skbuff.h>
struct ip_esp_hdr;
static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
{
return (struct ip_esp_hdr *)skb_transport_header(skb);
}
#endif

23
include/net/ethoc.h Normal file
View file

@ -0,0 +1,23 @@
/*
* linux/include/net/ethoc.h
*
* Copyright (C) 2008-2009 Avionic Design GmbH
*
* 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.
*
* Written by Thierry Reding <thierry.reding@avionic-design.de>
*/
#ifndef LINUX_NET_ETHOC_H
#define LINUX_NET_ETHOC_H 1
struct ethoc_platform_data {
u8 hwaddr[IFHWADDRLEN];
s8 phy_id;
u32 eth_clkfreq;
};
#endif /* !LINUX_NET_ETHOC_H */

133
include/net/fib_rules.h Normal file
View file

@ -0,0 +1,133 @@
#ifndef __NET_FIB_RULES_H
#define __NET_FIB_RULES_H
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/fib_rules.h>
#include <net/flow.h>
#include <net/rtnetlink.h>
struct fib_rule {
struct list_head list;
int iifindex;
int oifindex;
u32 mark;
u32 mark_mask;
u32 flags;
u32 table;
u8 action;
/* 3 bytes hole, try to use */
u32 target;
struct fib_rule __rcu *ctarget;
struct net *fr_net;
atomic_t refcnt;
u32 pref;
int suppress_ifgroup;
int suppress_prefixlen;
char iifname[IFNAMSIZ];
char oifname[IFNAMSIZ];
kuid_t uid_start;
kuid_t uid_end;
struct rcu_head rcu;
};
struct fib_lookup_arg {
void *lookup_ptr;
void *result;
struct fib_rule *rule;
int flags;
#define FIB_LOOKUP_NOREF 1
};
struct fib_rules_ops {
int family;
struct list_head list;
int rule_size;
int addr_size;
int unresolved_rules;
int nr_goto_rules;
int (*action)(struct fib_rule *,
struct flowi *, int,
struct fib_lookup_arg *);
bool (*suppress)(struct fib_rule *,
struct fib_lookup_arg *);
int (*match)(struct fib_rule *,
struct flowi *, int);
int (*configure)(struct fib_rule *,
struct sk_buff *,
struct fib_rule_hdr *,
struct nlattr **);
void (*delete)(struct fib_rule *);
int (*compare)(struct fib_rule *,
struct fib_rule_hdr *,
struct nlattr **);
int (*fill)(struct fib_rule *, struct sk_buff *,
struct fib_rule_hdr *);
u32 (*default_pref)(struct fib_rules_ops *ops);
size_t (*nlmsg_payload)(struct fib_rule *);
/* Called after modifications to the rules set, must flush
* the route cache if one exists. */
void (*flush_cache)(struct fib_rules_ops *ops);
int nlgroup;
const struct nla_policy *policy;
struct list_head rules_list;
struct module *owner;
struct net *fro_net;
struct rcu_head rcu;
};
#define FRA_GENERIC_POLICY \
[FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
[FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
[FRA_PRIORITY] = { .type = NLA_U32 }, \
[FRA_FWMARK] = { .type = NLA_U32 }, \
[FRA_FWMASK] = { .type = NLA_U32 }, \
[FRA_TABLE] = { .type = NLA_U32 }, \
[FRA_GOTO] = { .type = NLA_U32 }, \
[FRA_UID_START] = { .type = NLA_U32 }, \
[FRA_UID_END] = { .type = NLA_U32 }, \
[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
[FRA_GOTO] = { .type = NLA_U32 }
static inline void fib_rule_get(struct fib_rule *rule)
{
atomic_inc(&rule->refcnt);
}
static inline void fib_rule_put_rcu(struct rcu_head *head)
{
struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
release_net(rule->fr_net);
kfree(rule);
}
static inline void fib_rule_put(struct fib_rule *rule)
{
if (atomic_dec_and_test(&rule->refcnt))
call_rcu(&rule->rcu, fib_rule_put_rcu);
}
static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
{
if (nla[FRA_TABLE])
return nla_get_u32(nla[FRA_TABLE]);
return frh->table;
}
struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
struct net *);
void fib_rules_unregister(struct fib_rules_ops *);
int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags,
struct fib_lookup_arg *);
int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table,
u32 flags);
u32 fib_default_rule_pref(struct fib_rules_ops *ops);
#endif

25
include/net/firewire.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef _NET_FIREWIRE_H
#define _NET_FIREWIRE_H
/* Pseudo L2 address */
#define FWNET_ALEN 16
union fwnet_hwaddr {
u8 u[FWNET_ALEN];
/* "Hardware address" defined in RFC2734/RF3146 */
struct {
__be64 uniq_id; /* EUI-64 */
u8 max_rec; /* max packet size */
u8 sspd; /* max speed */
__be16 fifo_hi; /* hi 16bits of FIFO addr */
__be32 fifo_lo; /* lo 32bits of FIFO addr */
} __packed uc;
};
/* Pseudo L2 Header */
#define FWNET_HLEN 18
struct fwnet_header {
u8 h_dest[FWNET_ALEN]; /* destination address */
__be16 h_proto; /* packet type ID field */
} __packed;
#endif

243
include/net/flow.h Normal file
View file

@ -0,0 +1,243 @@
/*
*
* Generic internet FLOW.
*
*/
#ifndef _NET_FLOW_H
#define _NET_FLOW_H
#include <linux/socket.h>
#include <linux/in6.h>
#include <linux/atomic.h>
#include <linux/uidgid.h>
/*
* ifindex generation is per-net namespace, and loopback is
* always the 1st device in ns (see net_dev_init), thus any
* loopback device should get ifindex 1
*/
#define LOOPBACK_IFINDEX 1
struct flowi_common {
int flowic_oif;
int flowic_iif;
__u32 flowic_mark;
__u8 flowic_tos;
__u8 flowic_scope;
__u8 flowic_proto;
__u8 flowic_flags;
#define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02
__u32 flowic_secid;
kuid_t flowic_uid;
};
union flowi_uli {
struct {
__be16 dport;
__be16 sport;
} ports;
struct {
__u8 type;
__u8 code;
} icmpt;
struct {
__le16 dport;
__le16 sport;
} dnports;
__be32 spi;
__be32 gre_key;
struct {
__u8 type;
} mht;
};
struct flowi4 {
struct flowi_common __fl_common;
#define flowi4_oif __fl_common.flowic_oif
#define flowi4_iif __fl_common.flowic_iif
#define flowi4_mark __fl_common.flowic_mark
#define flowi4_tos __fl_common.flowic_tos
#define flowi4_scope __fl_common.flowic_scope
#define flowi4_proto __fl_common.flowic_proto
#define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid
#define flowi4_uid __fl_common.flowic_uid
/* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr;
__be32 daddr;
union flowi_uli uli;
#define fl4_sport uli.ports.sport
#define fl4_dport uli.ports.dport
#define fl4_icmp_type uli.icmpt.type
#define fl4_icmp_code uli.icmpt.code
#define fl4_ipsec_spi uli.spi
#define fl4_mh_type uli.mht.type
#define fl4_gre_key uli.gre_key
} __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
__u32 mark, __u8 tos, __u8 scope,
__u8 proto, __u8 flags,
__be32 daddr, __be32 saddr,
__be16 dport, __be16 sport,
kuid_t uid)
{
fl4->flowi4_oif = oif;
fl4->flowi4_iif = LOOPBACK_IFINDEX;
fl4->flowi4_mark = mark;
fl4->flowi4_tos = tos;
fl4->flowi4_scope = scope;
fl4->flowi4_proto = proto;
fl4->flowi4_flags = flags;
fl4->flowi4_secid = 0;
fl4->flowi4_uid = uid;
fl4->daddr = daddr;
fl4->saddr = saddr;
fl4->fl4_dport = dport;
fl4->fl4_sport = sport;
}
/* Reset some input parameters after previous lookup */
static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos,
__be32 daddr, __be32 saddr)
{
fl4->flowi4_oif = oif;
fl4->flowi4_tos = tos;
fl4->daddr = daddr;
fl4->saddr = saddr;
}
struct flowi6 {
struct flowi_common __fl_common;
#define flowi6_oif __fl_common.flowic_oif
#define flowi6_iif __fl_common.flowic_iif
#define flowi6_mark __fl_common.flowic_mark
#define flowi6_tos __fl_common.flowic_tos
#define flowi6_scope __fl_common.flowic_scope
#define flowi6_proto __fl_common.flowic_proto
#define flowi6_flags __fl_common.flowic_flags
#define flowi6_secid __fl_common.flowic_secid
#define flowi6_uid __fl_common.flowic_uid
struct in6_addr daddr;
struct in6_addr saddr;
__be32 flowlabel;
union flowi_uli uli;
#define fl6_sport uli.ports.sport
#define fl6_dport uli.ports.dport
#define fl6_icmp_type uli.icmpt.type
#define fl6_icmp_code uli.icmpt.code
#define fl6_ipsec_spi uli.spi
#define fl6_mh_type uli.mht.type
#define fl6_gre_key uli.gre_key
} __attribute__((__aligned__(BITS_PER_LONG/8)));
struct flowidn {
struct flowi_common __fl_common;
#define flowidn_oif __fl_common.flowic_oif
#define flowidn_iif __fl_common.flowic_iif
#define flowidn_mark __fl_common.flowic_mark
#define flowidn_scope __fl_common.flowic_scope
#define flowidn_proto __fl_common.flowic_proto
#define flowidn_flags __fl_common.flowic_flags
__le16 daddr;
__le16 saddr;
union flowi_uli uli;
#define fld_sport uli.ports.sport
#define fld_dport uli.ports.dport
} __attribute__((__aligned__(BITS_PER_LONG/8)));
struct flowi {
union {
struct flowi_common __fl_common;
struct flowi4 ip4;
struct flowi6 ip6;
struct flowidn dn;
} u;
#define flowi_oif u.__fl_common.flowic_oif
#define flowi_iif u.__fl_common.flowic_iif
#define flowi_mark u.__fl_common.flowic_mark
#define flowi_tos u.__fl_common.flowic_tos
#define flowi_scope u.__fl_common.flowic_scope
#define flowi_proto u.__fl_common.flowic_proto
#define flowi_flags u.__fl_common.flowic_flags
#define flowi_secid u.__fl_common.flowic_secid
#define flowi_uid u.__fl_common.flowic_uid
} __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
{
return container_of(fl4, struct flowi, u.ip4);
}
static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
{
return container_of(fl6, struct flowi, u.ip6);
}
static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
{
return container_of(fldn, struct flowi, u.dn);
}
typedef unsigned long flow_compare_t;
static inline size_t flow_key_size(u16 family)
{
switch (family) {
case AF_INET:
BUILD_BUG_ON(sizeof(struct flowi4) % sizeof(flow_compare_t));
return sizeof(struct flowi4) / sizeof(flow_compare_t);
case AF_INET6:
BUILD_BUG_ON(sizeof(struct flowi6) % sizeof(flow_compare_t));
return sizeof(struct flowi6) / sizeof(flow_compare_t);
case AF_DECnet:
BUILD_BUG_ON(sizeof(struct flowidn) % sizeof(flow_compare_t));
return sizeof(struct flowidn) / sizeof(flow_compare_t);
}
return 0;
}
#define FLOW_DIR_IN 0
#define FLOW_DIR_OUT 1
#define FLOW_DIR_FWD 2
struct net;
struct sock;
struct flow_cache_ops;
struct flow_cache_object {
const struct flow_cache_ops *ops;
};
struct flow_cache_ops {
struct flow_cache_object *(*get)(struct flow_cache_object *);
int (*check)(struct flow_cache_object *);
void (*delete)(struct flow_cache_object *);
};
typedef struct flow_cache_object *(*flow_resolve_t)(
struct net *net, const struct flowi *key, u16 family,
u8 dir, struct flow_cache_object *oldobj, void *ctx);
struct flow_cache_object *flow_cache_lookup(struct net *net,
const struct flowi *key, u16 family,
u8 dir, flow_resolve_t resolver,
void *ctx);
int flow_cache_init(struct net *net);
void flow_cache_fini(struct net *net);
void flow_cache_flush(struct net *net);
void flow_cache_flush_deferred(struct net *net);
extern atomic_t flow_cache_genid;
#endif

45
include/net/flow_keys.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef _NET_FLOW_KEYS_H
#define _NET_FLOW_KEYS_H
/* struct flow_keys:
* @src: source ip address in case of IPv4
* For IPv6 it contains 32bit hash of src address
* @dst: destination ip address in case of IPv4
* For IPv6 it contains 32bit hash of dst address
* @ports: port numbers of Transport header
* port16[0]: src port number
* port16[1]: dst port number
* @thoff: Transport header offset
* @n_proto: Network header protocol (eg. IPv4/IPv6)
* @ip_proto: Transport header protocol (eg. TCP/UDP)
* All the members, except thoff, are in network byte order.
*/
struct flow_keys {
/* (src,dst) must be grouped, in the same way than in IP header */
__be32 src;
__be32 dst;
union {
__be32 ports;
__be16 port16[2];
};
u16 thoff;
u16 n_proto;
u8 ip_proto;
};
bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow,
void *data, __be16 proto, int nhoff, int hlen);
static inline bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow)
{
return __skb_flow_dissect(skb, flow, NULL, 0, 0, 0);
}
__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
void *data, int hlen_proto);
static inline __be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto)
{
return __skb_flow_get_ports(skb, thoff, ip_proto, NULL, 0);
}
u32 flow_hash_from_keys(struct flow_keys *keys);
unsigned int flow_get_hlen(const unsigned char *data, unsigned int max_len,
__be16 protocol);
#endif

25
include/net/flowcache.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef _NET_FLOWCACHE_H
#define _NET_FLOWCACHE_H
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/notifier.h>
struct flow_cache_percpu {
struct hlist_head *hash_table;
int hash_count;
u32 hash_rnd;
int hash_rnd_recalc;
struct tasklet_struct flush_tasklet;
};
struct flow_cache {
u32 hash_shift;
struct flow_cache_percpu __percpu *percpu;
struct notifier_block hotcpu_notifier;
int low_watermark;
int high_watermark;
struct timer_list rnd_timer;
};
#endif /* _NET_FLOWCACHE_H */

129
include/net/garp.h Normal file
View file

@ -0,0 +1,129 @@
#ifndef _NET_GARP_H
#define _NET_GARP_H
#include <net/stp.h>
#define GARP_PROTOCOL_ID 0x1
#define GARP_END_MARK 0x0
struct garp_pdu_hdr {
__be16 protocol;
};
struct garp_msg_hdr {
u8 attrtype;
};
enum garp_attr_event {
GARP_LEAVE_ALL,
GARP_JOIN_EMPTY,
GARP_JOIN_IN,
GARP_LEAVE_EMPTY,
GARP_LEAVE_IN,
GARP_EMPTY,
};
struct garp_attr_hdr {
u8 len;
u8 event;
u8 data[];
};
struct garp_skb_cb {
u8 cur_type;
};
static inline struct garp_skb_cb *garp_cb(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct garp_skb_cb) >
FIELD_SIZEOF(struct sk_buff, cb));
return (struct garp_skb_cb *)skb->cb;
}
enum garp_applicant_state {
GARP_APPLICANT_INVALID,
GARP_APPLICANT_VA,
GARP_APPLICANT_AA,
GARP_APPLICANT_QA,
GARP_APPLICANT_LA,
GARP_APPLICANT_VP,
GARP_APPLICANT_AP,
GARP_APPLICANT_QP,
GARP_APPLICANT_VO,
GARP_APPLICANT_AO,
GARP_APPLICANT_QO,
__GARP_APPLICANT_MAX
};
#define GARP_APPLICANT_MAX (__GARP_APPLICANT_MAX - 1)
enum garp_event {
GARP_EVENT_REQ_JOIN,
GARP_EVENT_REQ_LEAVE,
GARP_EVENT_R_JOIN_IN,
GARP_EVENT_R_JOIN_EMPTY,
GARP_EVENT_R_EMPTY,
GARP_EVENT_R_LEAVE_IN,
GARP_EVENT_R_LEAVE_EMPTY,
GARP_EVENT_TRANSMIT_PDU,
__GARP_EVENT_MAX
};
#define GARP_EVENT_MAX (__GARP_EVENT_MAX - 1)
enum garp_action {
GARP_ACTION_NONE,
GARP_ACTION_S_JOIN_IN,
GARP_ACTION_S_LEAVE_EMPTY,
};
struct garp_attr {
struct rb_node node;
enum garp_applicant_state state;
u8 type;
u8 dlen;
unsigned char data[];
};
enum garp_applications {
GARP_APPLICATION_GVRP,
__GARP_APPLICATION_MAX
};
#define GARP_APPLICATION_MAX (__GARP_APPLICATION_MAX - 1)
struct garp_application {
enum garp_applications type;
unsigned int maxattr;
struct stp_proto proto;
};
struct garp_applicant {
struct garp_application *app;
struct net_device *dev;
struct timer_list join_timer;
spinlock_t lock;
struct sk_buff_head queue;
struct sk_buff *pdu;
struct rb_root gid;
struct rcu_head rcu;
};
struct garp_port {
struct garp_applicant __rcu *applicants[GARP_APPLICATION_MAX + 1];
struct rcu_head rcu;
};
int garp_register_application(struct garp_application *app);
void garp_unregister_application(struct garp_application *app);
int garp_init_applicant(struct net_device *dev, struct garp_application *app);
void garp_uninit_applicant(struct net_device *dev,
struct garp_application *app);
int garp_request_join(const struct net_device *dev,
const struct garp_application *app, const void *data,
u8 len, u8 type);
void garp_request_leave(const struct net_device *dev,
const struct garp_application *app,
const void *data, u8 len, u8 type);
#endif /* _NET_GARP_H */

62
include/net/gen_stats.h Normal file
View file

@ -0,0 +1,62 @@
#ifndef __NET_GEN_STATS_H
#define __NET_GEN_STATS_H
#include <linux/gen_stats.h>
#include <linux/socket.h>
#include <linux/rtnetlink.h>
#include <linux/pkt_sched.h>
struct gnet_stats_basic_cpu {
struct gnet_stats_basic_packed bstats;
struct u64_stats_sync syncp;
};
struct gnet_dump {
spinlock_t * lock;
struct sk_buff * skb;
struct nlattr * tail;
/* Backward compatibility */
int compat_tc_stats;
int compat_xstats;
void * xstats;
int xstats_len;
struct tc_stats tc_stats;
};
int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
struct gnet_dump *d);
int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
int tc_stats_type, int xstats_type,
spinlock_t *lock, struct gnet_dump *d);
int gnet_stats_copy_basic(struct gnet_dump *d,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
void __gnet_stats_copy_basic(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
int gnet_stats_copy_rate_est(struct gnet_dump *d,
const struct gnet_stats_basic_packed *b,
struct gnet_stats_rate_est64 *r);
int gnet_stats_copy_queue(struct gnet_dump *d,
struct gnet_stats_queue __percpu *cpu_q,
struct gnet_stats_queue *q, __u32 qlen);
int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
int gnet_stats_finish_copy(struct gnet_dump *d);
int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
struct gnet_stats_rate_est64 *rate_est,
spinlock_t *stats_lock, struct nlattr *opt);
void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_rate_est64 *rate_est);
int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
struct gnet_stats_rate_est64 *rate_est,
spinlock_t *stats_lock, struct nlattr *opt);
bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
const struct gnet_stats_rate_est64 *rate_est);
#endif

405
include/net/genetlink.h Normal file
View file

@ -0,0 +1,405 @@
#ifndef __NET_GENERIC_NETLINK_H
#define __NET_GENERIC_NETLINK_H
#include <linux/genetlink.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
/**
* struct genl_multicast_group - generic netlink multicast group
* @name: name of the multicast group, names are per-family
*/
struct genl_multicast_group {
char name[GENL_NAMSIZ];
};
struct genl_ops;
struct genl_info;
/**
* struct genl_family - generic netlink family
* @id: protocol family idenfitier
* @hdrsize: length of user specific header in bytes
* @name: name of family
* @version: protocol version
* @maxattr: maximum number of attributes supported
* @netnsok: set to true if the family can handle network
* namespaces and should be presented in all of them
* @pre_doit: called before an operation's doit callback, it may
* do additional, common, filtering and return an error
* @post_doit: called after an operation's doit callback, it may
* undo operations done by pre_doit, for example release locks
* @attrbuf: buffer to store parsed attributes
* @family_list: family list
* @mcgrps: multicast groups used by this family (private)
* @n_mcgrps: number of multicast groups (private)
* @mcgrp_offset: starting number of multicast group IDs in this family
* @ops: the operations supported by this family (private)
* @n_ops: number of operations supported by this family (private)
*/
struct genl_family {
unsigned int id;
unsigned int hdrsize;
char name[GENL_NAMSIZ];
unsigned int version;
unsigned int maxattr;
bool netnsok;
bool parallel_ops;
int (*pre_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
void (*post_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
struct nlattr ** attrbuf; /* private */
const struct genl_ops * ops; /* private */
const struct genl_multicast_group *mcgrps; /* private */
unsigned int n_ops; /* private */
unsigned int n_mcgrps; /* private */
unsigned int mcgrp_offset; /* private */
struct list_head family_list; /* private */
struct module *module;
};
/**
* struct genl_info - receiving information
* @snd_seq: sending sequence number
* @snd_portid: netlink portid of sender
* @nlhdr: netlink message header
* @genlhdr: generic netlink message header
* @userhdr: user specific header
* @attrs: netlink attributes
* @_net: network namespace
* @user_ptr: user pointers
* @dst_sk: destination socket
*/
struct genl_info {
u32 snd_seq;
u32 snd_portid;
struct nlmsghdr * nlhdr;
struct genlmsghdr * genlhdr;
void * userhdr;
struct nlattr ** attrs;
#ifdef CONFIG_NET_NS
struct net * _net;
#endif
void * user_ptr[2];
struct sock * dst_sk;
};
static inline struct net *genl_info_net(struct genl_info *info)
{
return read_pnet(&info->_net);
}
static inline void genl_info_net_set(struct genl_info *info, struct net *net)
{
write_pnet(&info->_net, net);
}
/**
* struct genl_ops - generic netlink operations
* @cmd: command identifier
* @internal_flags: flags used by the family
* @flags: flags
* @policy: attribute validation policy
* @doit: standard command callback
* @dumpit: callback for dumpers
* @done: completion callback for dumps
* @ops_list: operations list
*/
struct genl_ops {
const struct nla_policy *policy;
int (*doit)(struct sk_buff *skb,
struct genl_info *info);
int (*dumpit)(struct sk_buff *skb,
struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb);
u8 cmd;
u8 internal_flags;
u8 flags;
};
int __genl_register_family(struct genl_family *family);
static inline int genl_register_family(struct genl_family *family)
{
family->module = THIS_MODULE;
return __genl_register_family(family);
}
/**
* genl_register_family_with_ops - register a generic netlink family with ops
* @family: generic netlink family
* @ops: operations to be registered
* @n_ops: number of elements to register
*
* Registers the specified family and operations from the specified table.
* Only one family may be registered with the same family name or identifier.
*
* The family id may equal GENL_ID_GENERATE causing an unique id to
* be automatically generated and assigned.
*
* Either a doit or dumpit callback must be specified for every registered
* operation or the function will fail. Only one operation structure per
* command identifier may be registered.
*
* See include/net/genetlink.h for more documenation on the operations
* structure.
*
* Return 0 on success or a negative error code.
*/
static inline int
_genl_register_family_with_ops_grps(struct genl_family *family,
const struct genl_ops *ops, size_t n_ops,
const struct genl_multicast_group *mcgrps,
size_t n_mcgrps)
{
family->module = THIS_MODULE;
family->ops = ops;
family->n_ops = n_ops;
family->mcgrps = mcgrps;
family->n_mcgrps = n_mcgrps;
return __genl_register_family(family);
}
#define genl_register_family_with_ops(family, ops) \
_genl_register_family_with_ops_grps((family), \
(ops), ARRAY_SIZE(ops), \
NULL, 0)
#define genl_register_family_with_ops_groups(family, ops, grps) \
_genl_register_family_with_ops_grps((family), \
(ops), ARRAY_SIZE(ops), \
(grps), ARRAY_SIZE(grps))
int genl_unregister_family(struct genl_family *family);
void genl_notify(struct genl_family *family,
struct sk_buff *skb, struct net *net, u32 portid,
u32 group, struct nlmsghdr *nlh, gfp_t flags);
struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
struct genl_family *family, int flags, u8 cmd);
/**
* genlmsg_nlhdr - Obtain netlink header from user specified header
* @user_hdr: user header as returned from genlmsg_put()
* @family: generic netlink family
*
* Returns pointer to netlink header.
*/
static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
struct genl_family *family)
{
return (struct nlmsghdr *)((char *)user_hdr -
family->hdrsize -
GENL_HDRLEN -
NLMSG_HDRLEN);
}
/**
* genl_dump_check_consistent - check if sequence is consistent and advertise if not
* @cb: netlink callback structure that stores the sequence number
* @user_hdr: user header as returned from genlmsg_put()
* @family: generic netlink family
*
* Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
* simpler to use with generic netlink.
*/
static inline void genl_dump_check_consistent(struct netlink_callback *cb,
void *user_hdr,
struct genl_family *family)
{
nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
}
/**
* genlmsg_put_reply - Add generic netlink header to a reply message
* @skb: socket buffer holding the message
* @info: receiver info
* @family: generic netlink family
* @flags: netlink message flags
* @cmd: generic netlink command
*
* Returns pointer to user specific header
*/
static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info,
struct genl_family *family,
int flags, u8 cmd)
{
return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
flags, cmd);
}
/**
* genlmsg_end - Finalize a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: user specific header
*/
static inline int genlmsg_end(struct sk_buff *skb, void *hdr)
{
return nlmsg_end(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_cancel - Cancel construction of a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: generic netlink message header
*/
static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
{
if (hdr)
nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_multicast_netns - multicast a netlink message to a specific netns
* @family: the generic netlink family
* @net: the net namespace
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast_netns(struct genl_family *family,
struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
}
/**
* genlmsg_multicast - multicast a netlink message to the default netns
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast(struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
return genlmsg_multicast_netns(family, &init_net, skb,
portid, group, flags);
}
/**
* genlmsg_multicast_allns - multicast a netlink message to all net namespaces
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
*
* This function must hold the RTNL or rcu_read_lock().
*/
int genlmsg_multicast_allns(struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags);
/**
* genlmsg_unicast - unicast a netlink message
* @skb: netlink message as socket buffer
* @portid: netlink portid of the destination socket
*/
static inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 portid)
{
return nlmsg_unicast(net->genl_sock, skb, portid);
}
/**
* genlmsg_reply - reply to a request
* @skb: netlink message to be sent back
* @info: receiver information
*/
static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
{
return genlmsg_unicast(genl_info_net(info), skb, info->snd_portid);
}
/**
* gennlmsg_data - head of message payload
* @gnlh: genetlink message header
*/
static inline void *genlmsg_data(const struct genlmsghdr *gnlh)
{
return ((unsigned char *) gnlh + GENL_HDRLEN);
}
/**
* genlmsg_len - length of message payload
* @gnlh: genetlink message header
*/
static inline int genlmsg_len(const struct genlmsghdr *gnlh)
{
struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
NLMSG_HDRLEN);
return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_msg_size - length of genetlink message not including padding
* @payload: length of message payload
*/
static inline int genlmsg_msg_size(int payload)
{
return GENL_HDRLEN + payload;
}
/**
* genlmsg_total_size - length of genetlink message including padding
* @payload: length of message payload
*/
static inline int genlmsg_total_size(int payload)
{
return NLMSG_ALIGN(genlmsg_msg_size(payload));
}
/**
* genlmsg_new - Allocate a new generic netlink message
* @payload: size of the message payload
* @flags: the type of memory to allocate.
*/
static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
{
return nlmsg_new(genlmsg_total_size(payload), flags);
}
/**
* genl_set_err - report error to genetlink broadcast listeners
* @family: the generic netlink family
* @net: the network namespace to report the error to
* @portid: the PORTID of a process that we want to skip (if any)
* @group: the broadcast group that will notice the error
* (this is the offset of the multicast group in the groups array)
* @code: error code, must be negative (as usual in kernelspace)
*
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option.
*/
static inline int genl_set_err(struct genl_family *family, struct net *net,
u32 portid, u32 group, int code)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return netlink_set_err(net->genl_sock, portid, group, code);
}
static inline int genl_has_listeners(struct genl_family *family,
struct sock *sk, unsigned int group)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return netlink_has_listeners(sk, group);
}
#endif /* __NET_GENERIC_NETLINK_H */

97
include/net/geneve.h Normal file
View file

@ -0,0 +1,97 @@
#ifndef __NET_GENEVE_H
#define __NET_GENEVE_H 1
#ifdef CONFIG_INET
#include <net/udp_tunnel.h>
#endif
/* Geneve Header:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Virtual Network Identifier (VNI) | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Variable Length Options |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Option Header:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Option Class | Type |R|R|R| Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Variable Option Data |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct geneve_opt {
__be16 opt_class;
u8 type;
#ifdef __LITTLE_ENDIAN_BITFIELD
u8 length:5;
u8 r3:1;
u8 r2:1;
u8 r1:1;
#else
u8 r1:1;
u8 r2:1;
u8 r3:1;
u8 length:5;
#endif
u8 opt_data[];
};
#define GENEVE_CRIT_OPT_TYPE (1 << 7)
struct genevehdr {
#ifdef __LITTLE_ENDIAN_BITFIELD
u8 opt_len:6;
u8 ver:2;
u8 rsvd1:6;
u8 critical:1;
u8 oam:1;
#else
u8 ver:2;
u8 opt_len:6;
u8 oam:1;
u8 critical:1;
u8 rsvd1:6;
#endif
__be16 proto_type;
u8 vni[3];
u8 rsvd2;
struct geneve_opt options[];
};
#ifdef CONFIG_INET
struct geneve_sock;
typedef void (geneve_rcv_t)(struct geneve_sock *gs, struct sk_buff *skb);
struct geneve_sock {
struct hlist_node hlist;
geneve_rcv_t *rcv;
void *rcv_data;
struct work_struct del_work;
struct socket *sock;
struct rcu_head rcu;
atomic_t refcnt;
struct udp_offload udp_offloads;
};
#define GENEVE_VER 0
#define GENEVE_BASE_HLEN (sizeof(struct udphdr) + sizeof(struct genevehdr))
struct geneve_sock *geneve_sock_add(struct net *net, __be16 port,
geneve_rcv_t *rcv, void *data,
bool no_share, bool ipv6);
void geneve_sock_release(struct geneve_sock *vs);
int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
struct sk_buff *skb, __be32 src, __be32 dst, __u8 tos,
__u8 ttl, __be16 df, __be16 src_port, __be16 dst_port,
__be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
bool xnet);
#endif /*ifdef CONFIG_INET */
#endif /*ifdef__NET_GENEVE_H */

104
include/net/gre.h Normal file
View file

@ -0,0 +1,104 @@
#ifndef __LINUX_GRE_H
#define __LINUX_GRE_H
#include <linux/skbuff.h>
#include <net/ip_tunnels.h>
#define GREPROTO_CISCO 0
#define GREPROTO_PPTP 1
#define GREPROTO_MAX 2
#define GRE_IP_PROTO_MAX 2
struct gre_protocol {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
};
struct gre_base_hdr {
__be16 flags;
__be16 protocol;
};
#define GRE_HEADER_SECTION 4
int gre_add_protocol(const struct gre_protocol *proto, u8 version);
int gre_del_protocol(const struct gre_protocol *proto, u8 version);
struct gre_cisco_protocol {
int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi);
int (*err_handler)(struct sk_buff *skb, u32 info,
const struct tnl_ptk_info *tpi);
u8 priority;
};
int gre_cisco_register(struct gre_cisco_protocol *proto);
int gre_cisco_unregister(struct gre_cisco_protocol *proto);
void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
int hdr_len);
static inline struct sk_buff *gre_handle_offloads(struct sk_buff *skb,
bool csum)
{
return iptunnel_handle_offloads(skb, csum,
csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
}
static inline int ip_gre_calc_hlen(__be16 o_flags)
{
int addend = 4;
if (o_flags&TUNNEL_CSUM)
addend += 4;
if (o_flags&TUNNEL_KEY)
addend += 4;
if (o_flags&TUNNEL_SEQ)
addend += 4;
return addend;
}
static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
{
__be16 tflags = 0;
if (flags & GRE_CSUM)
tflags |= TUNNEL_CSUM;
if (flags & GRE_ROUTING)
tflags |= TUNNEL_ROUTING;
if (flags & GRE_KEY)
tflags |= TUNNEL_KEY;
if (flags & GRE_SEQ)
tflags |= TUNNEL_SEQ;
if (flags & GRE_STRICT)
tflags |= TUNNEL_STRICT;
if (flags & GRE_REC)
tflags |= TUNNEL_REC;
if (flags & GRE_VERSION)
tflags |= TUNNEL_VERSION;
return tflags;
}
static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
{
__be16 flags = 0;
if (tflags & TUNNEL_CSUM)
flags |= GRE_CSUM;
if (tflags & TUNNEL_ROUTING)
flags |= GRE_ROUTING;
if (tflags & TUNNEL_KEY)
flags |= GRE_KEY;
if (tflags & TUNNEL_SEQ)
flags |= GRE_SEQ;
if (tflags & TUNNEL_STRICT)
flags |= GRE_STRICT;
if (tflags & TUNNEL_REC)
flags |= GRE_REC;
if (tflags & TUNNEL_VERSION)
flags |= GRE_VERSION;
return flags;
}
#endif

107
include/net/gro_cells.h Normal file
View file

@ -0,0 +1,107 @@
#ifndef _NET_GRO_CELLS_H
#define _NET_GRO_CELLS_H
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
struct gro_cell {
struct sk_buff_head napi_skbs;
struct napi_struct napi;
} ____cacheline_aligned_in_smp;
struct gro_cells {
unsigned int gro_cells_mask;
struct gro_cell *cells;
};
static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
{
struct gro_cell *cell = gcells->cells;
struct net_device *dev = skb->dev;
if (!cell || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) {
netif_rx(skb);
return;
}
if (skb_rx_queue_recorded(skb))
cell += skb_get_rx_queue(skb) & gcells->gro_cells_mask;
if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) {
atomic_long_inc(&dev->rx_dropped);
kfree_skb(skb);
return;
}
/* We run in BH context */
spin_lock(&cell->napi_skbs.lock);
__skb_queue_tail(&cell->napi_skbs, skb);
if (skb_queue_len(&cell->napi_skbs) == 1)
napi_schedule(&cell->napi);
spin_unlock(&cell->napi_skbs.lock);
}
/* called unser BH context */
static inline int gro_cell_poll(struct napi_struct *napi, int budget)
{
struct gro_cell *cell = container_of(napi, struct gro_cell, napi);
struct sk_buff *skb;
int work_done = 0;
spin_lock(&cell->napi_skbs.lock);
while (work_done < budget) {
skb = __skb_dequeue(&cell->napi_skbs);
if (!skb)
break;
spin_unlock(&cell->napi_skbs.lock);
napi_gro_receive(napi, skb);
work_done++;
spin_lock(&cell->napi_skbs.lock);
}
if (work_done < budget)
napi_complete(napi);
spin_unlock(&cell->napi_skbs.lock);
return work_done;
}
static inline int gro_cells_init(struct gro_cells *gcells, struct net_device *dev)
{
int i;
gcells->gro_cells_mask = roundup_pow_of_two(netif_get_num_default_rss_queues()) - 1;
gcells->cells = kcalloc(gcells->gro_cells_mask + 1,
sizeof(struct gro_cell),
GFP_KERNEL);
if (!gcells->cells)
return -ENOMEM;
for (i = 0; i <= gcells->gro_cells_mask; i++) {
struct gro_cell *cell = gcells->cells + i;
skb_queue_head_init(&cell->napi_skbs);
netif_napi_add(dev, &cell->napi, gro_cell_poll, 64);
napi_enable(&cell->napi);
}
return 0;
}
static inline void gro_cells_destroy(struct gro_cells *gcells)
{
struct gro_cell *cell = gcells->cells;
int i;
if (!cell)
return;
for (i = 0; i <= gcells->gro_cells_mask; i++,cell++) {
netif_napi_del(&cell->napi);
skb_queue_purge(&cell->napi_skbs);
}
kfree(gcells->cells);
gcells->cells = NULL;
}
#endif

23
include/net/gue.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef __NET_GUE_H
#define __NET_GUE_H
struct guehdr {
union {
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 hlen:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
hlen:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 next_hdr;
__u16 flags;
};
__u32 word;
};
};
#endif

48
include/net/icmp.h Normal file
View file

@ -0,0 +1,48 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the ICMP module.
*
* Version: @(#)icmp.h 1.0.4 05/13/93
*
* Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* 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.
*/
#ifndef _ICMP_H
#define _ICMP_H
#include <linux/icmp.h>
#include <net/inet_sock.h>
#include <net/snmp.h>
struct icmp_err {
int errno;
unsigned int fatal:1;
};
extern const struct icmp_err icmp_err_convert[];
#define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field)
#define ICMP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field)
#define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256)
#define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field)
struct dst_entry;
struct net_proto_family;
struct sk_buff;
struct net;
void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
int icmp_rcv(struct sk_buff *skb);
void icmp_err(struct sk_buff *skb, u32 info);
int icmp_init(void);
void icmp_out_count(struct net *net, unsigned char type);
#endif /* _ICMP_H */

View file

@ -0,0 +1,333 @@
/*
* Copyright (c) 2003, 2004 David Young. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
* YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/*
* Modifications to fit into the linux IEEE 802.11 stack,
* Mike Kershaw (dragorn@kismetwireless.net)
*/
#ifndef IEEE80211RADIOTAP_H
#define IEEE80211RADIOTAP_H
#include <linux/if_ether.h>
#include <linux/kernel.h>
#include <asm/unaligned.h>
/* Base version of the radiotap packet header data */
#define PKTHDR_RADIOTAP_VERSION 0
/* A generic radio capture format is desirable. There is one for
* Linux, but it is neither rigidly defined (there were not even
* units given for some fields) nor easily extensible.
*
* I suggest the following extensible radio capture format. It is
* based on a bitmap indicating which fields are present.
*
* I am trying to describe precisely what the application programmer
* should expect in the following, and for that reason I tell the
* units and origin of each measurement (where it applies), or else I
* use sufficiently weaselly language ("is a monotonically nondecreasing
* function of...") that I cannot set false expectations for lawyerly
* readers.
*/
/*
* The radio capture header precedes the 802.11 header.
* All data in the header is little endian on all platforms.
*/
struct ieee80211_radiotap_header {
u8 it_version; /* Version 0. Only increases
* for drastic changes,
* introduction of compatible
* new fields does not count.
*/
u8 it_pad;
__le16 it_len; /* length of the whole
* header in bytes, including
* it_version, it_pad,
* it_len, and data fields.
*/
__le32 it_present; /* A bitmap telling which
* fields are present. Set bit 31
* (0x80000000) to extend the
* bitmap by another 32 bits.
* Additional extensions are made
* by setting bit 31.
*/
} __packed;
/* Name Data type Units
* ---- --------- -----
*
* IEEE80211_RADIOTAP_TSFT __le64 microseconds
*
* Value in microseconds of the MAC's 64-bit 802.11 Time
* Synchronization Function timer when the first bit of the
* MPDU arrived at the MAC. For received frames, only.
*
* IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
*
* Tx/Rx frequency in MHz, followed by flags (see below).
*
* IEEE80211_RADIOTAP_FHSS __le16 see below
*
* For frequency-hopping radios, the hop set (first byte)
* and pattern (second byte).
*
* IEEE80211_RADIOTAP_RATE u8 500kb/s
*
* Tx/Rx data rate
*
* IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
* one milliwatt (dBm)
*
* RF signal power at the antenna, decibel difference from
* one milliwatt.
*
* IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
* one milliwatt (dBm)
*
* RF noise power at the antenna, decibel difference from one
* milliwatt.
*
* IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB)
*
* RF signal power at the antenna, decibel difference from an
* arbitrary, fixed reference.
*
* IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB)
*
* RF noise power at the antenna, decibel difference from an
* arbitrary, fixed reference point.
*
* IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
*
* Quality of Barker code lock. Unitless. Monotonically
* nondecreasing with "better" lock strength. Called "Signal
* Quality" in datasheets. (Is there a standard way to measure
* this?)
*
* IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
*
* Transmit power expressed as unitless distance from max
* power set at factory calibration. 0 is max power.
* Monotonically nondecreasing with lower power levels.
*
* IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
*
* Transmit power expressed as decibel distance from max power
* set at factory calibration. 0 is max power. Monotonically
* nondecreasing with lower power levels.
*
* IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
* one milliwatt (dBm)
*
* Transmit power expressed as dBm (decibels from a 1 milliwatt
* reference). This is the absolute power level measured at
* the antenna port.
*
* IEEE80211_RADIOTAP_FLAGS u8 bitmap
*
* Properties of transmitted and received frames. See flags
* defined below.
*
* IEEE80211_RADIOTAP_ANTENNA u8 antenna index
*
* Unitless indication of the Rx/Tx antenna for this packet.
* The first antenna is antenna 0.
*
* IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
*
* Properties of received frames. See flags defined below.
*
* IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
*
* Properties of transmitted frames. See flags defined below.
*
* IEEE80211_RADIOTAP_RTS_RETRIES u8 data
*
* Number of rts retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_DATA_RETRIES u8 data
*
* Number of unicast retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless
*
* Contains a bitmap of known fields/flags, the flags, and
* the MCS index.
*
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
*
* Contains the AMPDU information for the subframe.
*
* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
*
* Contains VHT information about this frame.
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
IEEE80211_RADIOTAP_FLAGS = 1,
IEEE80211_RADIOTAP_RATE = 2,
IEEE80211_RADIOTAP_CHANNEL = 3,
IEEE80211_RADIOTAP_FHSS = 4,
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
IEEE80211_RADIOTAP_RX_FLAGS = 14,
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
IEEE80211_RADIOTAP_VHT = 21,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
/* Channel flags. */
#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
#define IEEE80211_CHAN_GSM 0x1000 /* GSM (900 MHz) */
#define IEEE80211_CHAN_STURBO 0x2000 /* Static Turbo */
#define IEEE80211_CHAN_HALF 0x4000 /* Half channel (10 MHz wide) */
#define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter channel (5 MHz wide) */
/* For IEEE80211_RADIOTAP_FLAGS */
#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
* during CFP
*/
#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
* with short
* preamble
*/
#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
* with WEP encryption
*/
#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
* with fragmentation
*/
#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
* 802.11 header and payload
* (to 32-bit boundary)
*/
#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */
/* For IEEE80211_RADIOTAP_RX_FLAGS */
#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* frame has bad PLCP */
/* For IEEE80211_RADIOTAP_TX_FLAGS */
#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
* retries */
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */
/* For IEEE80211_RADIOTAP_MCS */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BW_20 0
#define IEEE80211_RADIOTAP_MCS_BW_40 1
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
/* For IEEE80211_RADIOTAP_VHT */
#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01
#define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02
#define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04
#define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08
/* helpers */
static inline int ieee80211_get_radiotap_len(unsigned char *data)
{
struct ieee80211_radiotap_header *hdr =
(struct ieee80211_radiotap_header *)data;
return get_unaligned_le16(&hdr->it_len);
}
#endif /* IEEE80211_RADIOTAP_H */

195
include/net/ieee802154.h Normal file
View file

@ -0,0 +1,195 @@
/*
* IEEE802.15.4-2003 specification
*
* Copyright (C) 2007, 2008 Siemens AG
*
* 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.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
* Maxim Osipov <maxim.osipov@siemens.com>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
#ifndef NET_IEEE802154_H
#define NET_IEEE802154_H
#define IEEE802154_MTU 127
#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */
#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */
#define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */
#define IEEE802154_FC_TYPE_MAC_CMD 0x3 /* Frame is MAC command */
#define IEEE802154_FC_TYPE_SHIFT 0
#define IEEE802154_FC_TYPE_MASK ((1 << 3) - 1)
#define IEEE802154_FC_TYPE(x) ((x & IEEE802154_FC_TYPE_MASK) >> IEEE802154_FC_TYPE_SHIFT)
#define IEEE802154_FC_SET_TYPE(v, x) do { \
v = (((v) & ~IEEE802154_FC_TYPE_MASK) | \
(((x) << IEEE802154_FC_TYPE_SHIFT) & IEEE802154_FC_TYPE_MASK)); \
} while (0)
#define IEEE802154_FC_SECEN_SHIFT 3
#define IEEE802154_FC_SECEN (1 << IEEE802154_FC_SECEN_SHIFT)
#define IEEE802154_FC_FRPEND_SHIFT 4
#define IEEE802154_FC_FRPEND (1 << IEEE802154_FC_FRPEND_SHIFT)
#define IEEE802154_FC_ACK_REQ_SHIFT 5
#define IEEE802154_FC_ACK_REQ (1 << IEEE802154_FC_ACK_REQ_SHIFT)
#define IEEE802154_FC_INTRA_PAN_SHIFT 6
#define IEEE802154_FC_INTRA_PAN (1 << IEEE802154_FC_INTRA_PAN_SHIFT)
#define IEEE802154_FC_SAMODE_SHIFT 14
#define IEEE802154_FC_SAMODE_MASK (3 << IEEE802154_FC_SAMODE_SHIFT)
#define IEEE802154_FC_DAMODE_SHIFT 10
#define IEEE802154_FC_DAMODE_MASK (3 << IEEE802154_FC_DAMODE_SHIFT)
#define IEEE802154_FC_VERSION_SHIFT 12
#define IEEE802154_FC_VERSION_MASK (3 << IEEE802154_FC_VERSION_SHIFT)
#define IEEE802154_FC_VERSION(x) ((x & IEEE802154_FC_VERSION_MASK) >> IEEE802154_FC_VERSION_SHIFT)
#define IEEE802154_FC_SAMODE(x) \
(((x) & IEEE802154_FC_SAMODE_MASK) >> IEEE802154_FC_SAMODE_SHIFT)
#define IEEE802154_FC_DAMODE(x) \
(((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT)
#define IEEE802154_SCF_SECLEVEL_MASK 7
#define IEEE802154_SCF_SECLEVEL_SHIFT 0
#define IEEE802154_SCF_SECLEVEL(x) (x & IEEE802154_SCF_SECLEVEL_MASK)
#define IEEE802154_SCF_KEY_ID_MODE_SHIFT 3
#define IEEE802154_SCF_KEY_ID_MODE_MASK (3 << IEEE802154_SCF_KEY_ID_MODE_SHIFT)
#define IEEE802154_SCF_KEY_ID_MODE(x) \
((x & IEEE802154_SCF_KEY_ID_MODE_MASK) >> IEEE802154_SCF_KEY_ID_MODE_SHIFT)
#define IEEE802154_SCF_KEY_IMPLICIT 0
#define IEEE802154_SCF_KEY_INDEX 1
#define IEEE802154_SCF_KEY_SHORT_INDEX 2
#define IEEE802154_SCF_KEY_HW_INDEX 3
#define IEEE802154_SCF_SECLEVEL_NONE 0
#define IEEE802154_SCF_SECLEVEL_MIC32 1
#define IEEE802154_SCF_SECLEVEL_MIC64 2
#define IEEE802154_SCF_SECLEVEL_MIC128 3
#define IEEE802154_SCF_SECLEVEL_ENC 4
#define IEEE802154_SCF_SECLEVEL_ENC_MIC32 5
#define IEEE802154_SCF_SECLEVEL_ENC_MIC64 6
#define IEEE802154_SCF_SECLEVEL_ENC_MIC128 7
/* MAC footer size */
#define IEEE802154_MFR_SIZE 2 /* 2 octets */
/* MAC's Command Frames Identifiers */
#define IEEE802154_CMD_ASSOCIATION_REQ 0x01
#define IEEE802154_CMD_ASSOCIATION_RESP 0x02
#define IEEE802154_CMD_DISASSOCIATION_NOTIFY 0x03
#define IEEE802154_CMD_DATA_REQ 0x04
#define IEEE802154_CMD_PANID_CONFLICT_NOTIFY 0x05
#define IEEE802154_CMD_ORPHAN_NOTIFY 0x06
#define IEEE802154_CMD_BEACON_REQ 0x07
#define IEEE802154_CMD_COORD_REALIGN_NOTIFY 0x08
#define IEEE802154_CMD_GTS_REQ 0x09
/*
* The return values of MAC operations
*/
enum {
/*
* The requested operation was completed successfully.
* For a transmission request, this value indicates
* a successful transmission.
*/
IEEE802154_SUCCESS = 0x0,
/* The beacon was lost following a synchronization request. */
IEEE802154_BEACON_LOSS = 0xe0,
/*
* A transmission could not take place due to activity on the
* channel, i.e., the CSMA-CA mechanism has failed.
*/
IEEE802154_CHNL_ACCESS_FAIL = 0xe1,
/* The GTS request has been denied by the PAN coordinator. */
IEEE802154_DENINED = 0xe2,
/* The attempt to disable the transceiver has failed. */
IEEE802154_DISABLE_TRX_FAIL = 0xe3,
/*
* The received frame induces a failed security check according to
* the security suite.
*/
IEEE802154_FAILED_SECURITY_CHECK = 0xe4,
/*
* The frame resulting from secure processing has a length that is
* greater than aMACMaxFrameSize.
*/
IEEE802154_FRAME_TOO_LONG = 0xe5,
/*
* The requested GTS transmission failed because the specified GTS
* either did not have a transmit GTS direction or was not defined.
*/
IEEE802154_INVALID_GTS = 0xe6,
/*
* A request to purge an MSDU from the transaction queue was made using
* an MSDU handle that was not found in the transaction table.
*/
IEEE802154_INVALID_HANDLE = 0xe7,
/* A parameter in the primitive is out of the valid range.*/
IEEE802154_INVALID_PARAMETER = 0xe8,
/* No acknowledgment was received after aMaxFrameRetries. */
IEEE802154_NO_ACK = 0xe9,
/* A scan operation failed to find any network beacons.*/
IEEE802154_NO_BEACON = 0xea,
/* No response data were available following a request. */
IEEE802154_NO_DATA = 0xeb,
/* The operation failed because a short address was not allocated. */
IEEE802154_NO_SHORT_ADDRESS = 0xec,
/*
* A receiver enable request was unsuccessful because it could not be
* completed within the CAP.
*/
IEEE802154_OUT_OF_CAP = 0xed,
/*
* A PAN identifier conflict has been detected and communicated to the
* PAN coordinator.
*/
IEEE802154_PANID_CONFLICT = 0xee,
/* A coordinator realignment command has been received. */
IEEE802154_REALIGMENT = 0xef,
/* The transaction has expired and its information discarded. */
IEEE802154_TRANSACTION_EXPIRED = 0xf0,
/* There is no capacity to store the transaction. */
IEEE802154_TRANSACTION_OVERFLOW = 0xf1,
/*
* The transceiver was in the transmitter enabled state when the
* receiver was requested to be enabled.
*/
IEEE802154_TX_ACTIVE = 0xf2,
/* The appropriate key is not available in the ACL. */
IEEE802154_UNAVAILABLE_KEY = 0xf3,
/*
* A SET/GET request was issued with the identifier of a PIB attribute
* that is not supported.
*/
IEEE802154_UNSUPPORTED_ATTR = 0xf4,
/*
* A request to perform a scan operation failed because the MLME was
* in the process of performing a previously initiated scan operation.
*/
IEEE802154_SCAN_IN_PROGRESS = 0xfc,
};
#endif

View file

@ -0,0 +1,463 @@
/*
* An interface between IEEE802.15.4 device and rest of the kernel.
*
* Copyright (C) 2007-2012 Siemens AG
*
* 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.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
* Maxim Osipov <maxim.osipov@siemens.com>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
#ifndef IEEE802154_NETDEVICE_H
#define IEEE802154_NETDEVICE_H
#include <net/ieee802154.h>
#include <net/af_ieee802154.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
struct ieee802154_sechdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
u8 level:3,
key_id_mode:2,
reserved:3;
#elif defined(__BIG_ENDIAN_BITFIELD)
u8 reserved:3,
key_id_mode:2,
level:3;
#else
#error "Please fix <asm/byteorder.h>"
#endif
u8 key_id;
__le32 frame_counter;
union {
__le32 short_src;
__le64 extended_src;
};
};
struct ieee802154_addr {
u8 mode;
__le16 pan_id;
union {
__le16 short_addr;
__le64 extended_addr;
};
};
struct ieee802154_hdr_fc {
#if defined(__LITTLE_ENDIAN_BITFIELD)
u16 type:3,
security_enabled:1,
frame_pending:1,
ack_request:1,
intra_pan:1,
reserved:3,
dest_addr_mode:2,
version:2,
source_addr_mode:2;
#elif defined(__BIG_ENDIAN_BITFIELD)
u16 reserved:1,
intra_pan:1,
ack_request:1,
frame_pending:1,
security_enabled:1,
type:3,
source_addr_mode:2,
version:2,
dest_addr_mode:2,
reserved2:2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
};
struct ieee802154_hdr {
struct ieee802154_hdr_fc fc;
u8 seq;
struct ieee802154_addr source;
struct ieee802154_addr dest;
struct ieee802154_sechdr sec;
};
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
* the contents of hdr will be, and the actual value of those bits in
* hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
* version, if SECEN is set.
*/
int ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr);
/* pulls the entire 802.15.4 header off of the skb, including the security
* header, and performs pan id decompression
*/
int ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr);
/* parses the frame control, sequence number of address fields in a given skb
* and stores them into hdr, performing pan id decompression and length checks
* to be suitable for use in header_ops.parse
*/
int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
struct ieee802154_hdr *hdr);
/* parses the full 802.15.4 header a given skb and stores them into hdr,
* performing pan id decompression and length checks to be suitable for use in
* header_ops.parse
*/
int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
static inline int
ieee802154_sechdr_authtag_len(const struct ieee802154_sechdr *sec)
{
switch (sec->level) {
case IEEE802154_SCF_SECLEVEL_MIC32:
case IEEE802154_SCF_SECLEVEL_ENC_MIC32:
return 4;
case IEEE802154_SCF_SECLEVEL_MIC64:
case IEEE802154_SCF_SECLEVEL_ENC_MIC64:
return 8;
case IEEE802154_SCF_SECLEVEL_MIC128:
case IEEE802154_SCF_SECLEVEL_ENC_MIC128:
return 16;
case IEEE802154_SCF_SECLEVEL_NONE:
case IEEE802154_SCF_SECLEVEL_ENC:
default:
return 0;
}
}
static inline int ieee802154_hdr_length(struct sk_buff *skb)
{
struct ieee802154_hdr hdr;
int len = ieee802154_hdr_pull(skb, &hdr);
if (len > 0)
skb_push(skb, len);
return len;
}
static inline bool ieee802154_addr_equal(const struct ieee802154_addr *a1,
const struct ieee802154_addr *a2)
{
if (a1->pan_id != a2->pan_id || a1->mode != a2->mode)
return false;
if ((a1->mode == IEEE802154_ADDR_LONG &&
a1->extended_addr != a2->extended_addr) ||
(a1->mode == IEEE802154_ADDR_SHORT &&
a1->short_addr != a2->short_addr))
return false;
return true;
}
static inline __le64 ieee802154_devaddr_from_raw(const void *raw)
{
u64 temp;
memcpy(&temp, raw, IEEE802154_ADDR_LEN);
return (__force __le64)swab64(temp);
}
static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr)
{
u64 temp = swab64((__force u64)addr);
memcpy(raw, &temp, IEEE802154_ADDR_LEN);
}
static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a,
const struct ieee802154_addr_sa *sa)
{
a->mode = sa->addr_type;
a->pan_id = cpu_to_le16(sa->pan_id);
switch (a->mode) {
case IEEE802154_ADDR_SHORT:
a->short_addr = cpu_to_le16(sa->short_addr);
break;
case IEEE802154_ADDR_LONG:
a->extended_addr = ieee802154_devaddr_from_raw(sa->hwaddr);
break;
}
}
static inline void ieee802154_addr_to_sa(struct ieee802154_addr_sa *sa,
const struct ieee802154_addr *a)
{
sa->addr_type = a->mode;
sa->pan_id = le16_to_cpu(a->pan_id);
switch (a->mode) {
case IEEE802154_ADDR_SHORT:
sa->short_addr = le16_to_cpu(a->short_addr);
break;
case IEEE802154_ADDR_LONG:
ieee802154_devaddr_to_raw(sa->hwaddr, a->extended_addr);
break;
}
}
/*
* A control block of skb passed between the ARPHRD_IEEE802154 device
* and other stack parts.
*/
struct ieee802154_mac_cb {
u8 lqi;
u8 type;
bool ackreq;
bool secen;
bool secen_override;
u8 seclevel;
bool seclevel_override;
struct ieee802154_addr source;
struct ieee802154_addr dest;
};
static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
{
return (struct ieee802154_mac_cb *)skb->cb;
}
static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb));
memset(skb->cb, 0, sizeof(struct ieee802154_mac_cb));
return mac_cb(skb);
}
#define IEEE802154_LLSEC_KEY_SIZE 16
struct ieee802154_llsec_key_id {
u8 mode;
u8 id;
union {
struct ieee802154_addr device_addr;
__le32 short_source;
__le64 extended_source;
};
};
struct ieee802154_llsec_key {
u8 frame_types;
u32 cmd_frame_ids;
u8 key[IEEE802154_LLSEC_KEY_SIZE];
};
struct ieee802154_llsec_key_entry {
struct list_head list;
struct ieee802154_llsec_key_id id;
struct ieee802154_llsec_key *key;
};
struct ieee802154_llsec_device_key {
struct list_head list;
struct ieee802154_llsec_key_id key_id;
u32 frame_counter;
};
enum {
IEEE802154_LLSEC_DEVKEY_IGNORE,
IEEE802154_LLSEC_DEVKEY_RESTRICT,
IEEE802154_LLSEC_DEVKEY_RECORD,
__IEEE802154_LLSEC_DEVKEY_MAX,
};
struct ieee802154_llsec_device {
struct list_head list;
__le16 pan_id;
__le16 short_addr;
__le64 hwaddr;
u32 frame_counter;
bool seclevel_exempt;
u8 key_mode;
struct list_head keys;
};
struct ieee802154_llsec_seclevel {
struct list_head list;
u8 frame_type;
u8 cmd_frame_id;
bool device_override;
u32 sec_levels;
};
struct ieee802154_llsec_params {
bool enabled;
__be32 frame_counter;
u8 out_level;
struct ieee802154_llsec_key_id out_key;
__le64 default_key_source;
__le16 pan_id;
__le64 hwaddr;
__le64 coord_hwaddr;
__le16 coord_shortaddr;
};
struct ieee802154_llsec_table {
struct list_head keys;
struct list_head devices;
struct list_head security_levels;
};
#define IEEE802154_MAC_SCAN_ED 0
#define IEEE802154_MAC_SCAN_ACTIVE 1
#define IEEE802154_MAC_SCAN_PASSIVE 2
#define IEEE802154_MAC_SCAN_ORPHAN 3
struct ieee802154_mac_params {
s8 transmit_power;
u8 min_be;
u8 max_be;
u8 csma_retries;
s8 frame_retries;
bool lbt;
u8 cca_mode;
s32 cca_ed_level;
};
struct wpan_phy;
enum {
IEEE802154_LLSEC_PARAM_ENABLED = 1 << 0,
IEEE802154_LLSEC_PARAM_FRAME_COUNTER = 1 << 1,
IEEE802154_LLSEC_PARAM_OUT_LEVEL = 1 << 2,
IEEE802154_LLSEC_PARAM_OUT_KEY = 1 << 3,
IEEE802154_LLSEC_PARAM_KEY_SOURCE = 1 << 4,
IEEE802154_LLSEC_PARAM_PAN_ID = 1 << 5,
IEEE802154_LLSEC_PARAM_HWADDR = 1 << 6,
IEEE802154_LLSEC_PARAM_COORD_HWADDR = 1 << 7,
IEEE802154_LLSEC_PARAM_COORD_SHORTADDR = 1 << 8,
};
struct ieee802154_llsec_ops {
int (*get_params)(struct net_device *dev,
struct ieee802154_llsec_params *params);
int (*set_params)(struct net_device *dev,
const struct ieee802154_llsec_params *params,
int changed);
int (*add_key)(struct net_device *dev,
const struct ieee802154_llsec_key_id *id,
const struct ieee802154_llsec_key *key);
int (*del_key)(struct net_device *dev,
const struct ieee802154_llsec_key_id *id);
int (*add_dev)(struct net_device *dev,
const struct ieee802154_llsec_device *llsec_dev);
int (*del_dev)(struct net_device *dev, __le64 dev_addr);
int (*add_devkey)(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key);
int (*del_devkey)(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key);
int (*add_seclevel)(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl);
int (*del_seclevel)(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl);
void (*lock_table)(struct net_device *dev);
void (*get_table)(struct net_device *dev,
struct ieee802154_llsec_table **t);
void (*unlock_table)(struct net_device *dev);
};
/*
* This should be located at net_device->ml_priv
*
* get_phy should increment the reference counting on returned phy.
* Use wpan_wpy_put to put that reference.
*/
struct ieee802154_mlme_ops {
/* The following fields are optional (can be NULL). */
int (*assoc_req)(struct net_device *dev,
struct ieee802154_addr *addr,
u8 channel, u8 page, u8 cap);
int (*assoc_resp)(struct net_device *dev,
struct ieee802154_addr *addr,
__le16 short_addr, u8 status);
int (*disassoc_req)(struct net_device *dev,
struct ieee802154_addr *addr,
u8 reason);
int (*start_req)(struct net_device *dev,
struct ieee802154_addr *addr,
u8 channel, u8 page, u8 bcn_ord, u8 sf_ord,
u8 pan_coord, u8 blx, u8 coord_realign);
int (*scan_req)(struct net_device *dev,
u8 type, u32 channels, u8 page, u8 duration);
int (*set_mac_params)(struct net_device *dev,
const struct ieee802154_mac_params *params);
void (*get_mac_params)(struct net_device *dev,
struct ieee802154_mac_params *params);
struct ieee802154_llsec_ops *llsec;
/* The fields below are required. */
struct wpan_phy *(*get_phy)(const struct net_device *dev);
/*
* FIXME: these should become the part of PIB/MIB interface.
* However we still don't have IB interface of any kind
*/
__le16 (*get_pan_id)(const struct net_device *dev);
__le16 (*get_short_addr)(const struct net_device *dev);
u8 (*get_dsn)(const struct net_device *dev);
};
/* The IEEE 802.15.4 standard defines 2 type of the devices:
* - FFD - full functionality device
* - RFD - reduce functionality device
*
* So 2 sets of mlme operations are needed
*/
struct ieee802154_reduced_mlme_ops {
struct wpan_phy *(*get_phy)(const struct net_device *dev);
};
static inline struct ieee802154_mlme_ops *
ieee802154_mlme_ops(const struct net_device *dev)
{
return dev->ml_priv;
}
static inline struct ieee802154_reduced_mlme_ops *
ieee802154_reduced_mlme_ops(const struct net_device *dev)
{
return dev->ml_priv;
}
#endif

263
include/net/if_inet6.h Normal file
View file

@ -0,0 +1,263 @@
/*
* inet6 interface/address list definitions
* Linux INET6 implementation
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
*
* 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.
*/
#ifndef _NET_IF_INET6_H
#define _NET_IF_INET6_H
#include <net/snmp.h>
#include <linux/ipv6.h>
/* inet6_dev.if_flags */
#define IF_RA_OTHERCONF 0x80
#define IF_RA_MANAGED 0x40
#define IF_RA_RCVD 0x20
#define IF_RS_SENT 0x10
#define IF_READY 0x80000000
/* prefix flags */
#define IF_PREFIX_ONLINK 0x01
#define IF_PREFIX_AUTOCONF 0x02
enum {
INET6_IFADDR_STATE_PREDAD,
INET6_IFADDR_STATE_DAD,
INET6_IFADDR_STATE_POSTDAD,
INET6_IFADDR_STATE_ERRDAD,
INET6_IFADDR_STATE_DEAD,
};
struct inet6_ifaddr {
struct in6_addr addr;
__u32 prefix_len;
/* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
__u32 valid_lft;
__u32 prefered_lft;
atomic_t refcnt;
spinlock_t lock;
spinlock_t state_lock;
int state;
__u32 flags;
__u8 dad_probes;
__u16 scope;
unsigned long cstamp; /* created timestamp */
unsigned long tstamp; /* updated timestamp */
struct delayed_work dad_work;
struct inet6_dev *idev;
struct rt6_info *rt;
struct hlist_node addr_lst;
struct list_head if_list;
struct list_head tmp_list;
struct inet6_ifaddr *ifpub;
int regen_count;
bool tokenized;
struct rcu_head rcu;
struct in6_addr peer_addr;
};
struct ip6_sf_socklist {
unsigned int sl_max;
unsigned int sl_count;
struct in6_addr sl_addr[0];
};
#define IP6_SFLSIZE(count) (sizeof(struct ip6_sf_socklist) + \
(count) * sizeof(struct in6_addr))
#define IP6_SFBLOCK 10 /* allocate this many at once */
struct ipv6_mc_socklist {
struct in6_addr addr;
int ifindex;
struct ipv6_mc_socklist __rcu *next;
rwlock_t sflock;
unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */
struct ip6_sf_socklist *sflist;
struct rcu_head rcu;
};
struct ip6_sf_list {
struct ip6_sf_list *sf_next;
struct in6_addr sf_addr;
unsigned long sf_count[2]; /* include/exclude counts */
unsigned char sf_gsresp; /* include in g & s response? */
unsigned char sf_oldin; /* change state */
unsigned char sf_crcount; /* retrans. left to send */
};
#define MAF_TIMER_RUNNING 0x01
#define MAF_LAST_REPORTER 0x02
#define MAF_LOADED 0x04
#define MAF_NOREPORT 0x08
#define MAF_GSQUERY 0x10
struct ifmcaddr6 {
struct in6_addr mca_addr;
struct inet6_dev *idev;
struct ifmcaddr6 *next;
struct ip6_sf_list *mca_sources;
struct ip6_sf_list *mca_tomb;
unsigned int mca_sfmode;
unsigned char mca_crcount;
unsigned long mca_sfcount[2];
struct timer_list mca_timer;
unsigned int mca_flags;
int mca_users;
atomic_t mca_refcnt;
spinlock_t mca_lock;
unsigned long mca_cstamp;
unsigned long mca_tstamp;
};
/* Anycast stuff */
struct ipv6_ac_socklist {
struct in6_addr acl_addr;
int acl_ifindex;
struct ipv6_ac_socklist *acl_next;
};
struct ifacaddr6 {
struct in6_addr aca_addr;
struct inet6_dev *aca_idev;
struct rt6_info *aca_rt;
struct ifacaddr6 *aca_next;
int aca_users;
atomic_t aca_refcnt;
unsigned long aca_cstamp;
unsigned long aca_tstamp;
};
#define IFA_HOST IPV6_ADDR_LOOPBACK
#define IFA_LINK IPV6_ADDR_LINKLOCAL
#define IFA_SITE IPV6_ADDR_SITELOCAL
struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry;
DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev);
DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev);
};
struct inet6_dev {
struct net_device *dev;
struct list_head addr_list;
struct ifmcaddr6 *mc_list;
struct ifmcaddr6 *mc_tomb;
spinlock_t mc_lock;
unsigned char mc_qrv; /* Query Robustness Variable */
unsigned char mc_gq_running;
unsigned char mc_ifc_count;
unsigned char mc_dad_count;
unsigned long mc_v1_seen; /* Max time we stay in MLDv1 mode */
unsigned long mc_qi; /* Query Interval */
unsigned long mc_qri; /* Query Response Interval */
unsigned long mc_maxdelay;
struct timer_list mc_gq_timer; /* general query timer */
struct timer_list mc_ifc_timer; /* interface change timer */
struct timer_list mc_dad_timer; /* dad complete mc timer */
struct ifacaddr6 *ac_list;
rwlock_t lock;
atomic_t refcnt;
__u32 if_flags;
int dead;
u8 rndid[8];
struct timer_list regen_timer;
struct list_head tempaddr_list;
struct in6_addr token;
struct neigh_parms *nd_parms;
struct ipv6_devconf cnf;
struct ipv6_devstat stats;
struct timer_list rs_timer;
__u8 rs_probes;
__u8 addr_gen_mode;
unsigned long tstamp; /* ipv6InterfaceTable update timestamp */
struct rcu_head rcu;
};
static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf)
{
/*
* +-------+-------+-------+-------+-------+-------+
* | 33 | 33 | DST13 | DST14 | DST15 | DST16 |
* +-------+-------+-------+-------+-------+-------+
*/
buf[0]= 0x33;
buf[1]= 0x33;
memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
}
static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
{
buf[0] = 0x00;
}
static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
const unsigned char *broadcast, char *buf)
{
unsigned char scope = broadcast[5] & 0xF;
buf[0] = 0; /* Reserved */
buf[1] = 0xff; /* Multicast QPN */
buf[2] = 0xff;
buf[3] = 0xff;
buf[4] = 0xff;
buf[5] = 0x10 | scope; /* scope from broadcast address */
buf[6] = 0x60; /* IPv6 signature */
buf[7] = 0x1b;
buf[8] = broadcast[8]; /* P_Key */
buf[9] = broadcast[9];
memcpy(buf + 10, addr->s6_addr + 6, 10);
}
static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr,
const unsigned char *broadcast, char *buf)
{
if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) {
memcpy(buf, broadcast, 4);
} else {
/* v4mapped? */
if ((addr->s6_addr32[0] | addr->s6_addr32[1] |
(addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0)
return -EINVAL;
memcpy(buf, &addr->s6_addr32[3], 4);
}
return 0;
}
#endif

View file

@ -0,0 +1,46 @@
/*
* NET Generic infrastructure for INET6 connection oriented protocols.
*
* Authors: Many people, see the TCPv6 sources
*
* From code originally in TCPv6
*
* 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.
*/
#ifndef _INET6_CONNECTION_SOCK_H
#define _INET6_CONNECTION_SOCK_H
#include <linux/types.h>
struct in6_addr;
struct inet_bind_bucket;
struct request_sock;
struct sk_buff;
struct sock;
struct sockaddr;
int inet6_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb, bool relax);
struct dst_entry *inet6_csk_route_req(struct sock *sk, struct flowi6 *fl6,
const struct request_sock *req);
struct request_sock *inet6_csk_search_req(const struct sock *sk,
struct request_sock ***prevp,
const __be16 rport,
const struct in6_addr *raddr,
const struct in6_addr *laddr,
const int iif);
void inet6_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
const unsigned long timeout);
void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET6_CONNECTION_SOCK_H */

View file

@ -0,0 +1,102 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Authors: Lotsa people, from code originally in tcp
*
* 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.
*/
#ifndef _INET6_HASHTABLES_H
#define _INET6_HASHTABLES_H
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/in6.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <linux/jhash.h>
#include <net/inet_sock.h>
#include <net/ipv6.h>
#include <net/netns/hash.h>
struct inet_hashinfo;
static inline unsigned int __inet6_ehashfn(const u32 lhash,
const u16 lport,
const u32 fhash,
const __be16 fport,
const u32 initval)
{
const u32 ports = (((u32)lport) << 16) | (__force u32)fport;
return jhash_3words(lhash, fhash, ports, initval);
}
int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp);
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
* we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
*
* The sockhash lock must be held as a reader here.
*/
struct sock *__inet6_lookup_established(struct net *net,
struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum, const int dif);
struct sock *inet6_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const __be16 sport,
const struct in6_addr *daddr,
const unsigned short hnum, const int dif);
static inline struct sock *__inet6_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr,
const __be16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
{
struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
sport, daddr, hnum, dif);
if (sk)
return sk;
return inet6_lookup_listener(net, hashinfo, saddr, sport,
daddr, hnum, dif);
}
static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
struct sk_buff *skb,
const __be16 sport,
const __be16 dport,
int iif)
{
struct sock *sk = skb_steal_sock(skb);
if (sk)
return sk;
return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
&ipv6_hdr(skb)->saddr, sport,
&ipv6_hdr(skb)->daddr, ntohs(dport),
iif);
}
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr, const __be16 sport,
const struct in6_addr *daddr, const __be16 dport,
const int dif);
#endif /* IS_ENABLED(CONFIG_IPV6) */
#endif /* _INET6_HASHTABLES_H */

48
include/net/inet_common.h Normal file
View file

@ -0,0 +1,48 @@
#ifndef _INET_COMMON_H
#define _INET_COMMON_H
extern const struct proto_ops inet_stream_ops;
extern const struct proto_ops inet_dgram_ops;
/*
* INET4 prototypes used by INET6
*/
struct msghdr;
struct sock;
struct sockaddr;
struct socket;
int inet_release(struct socket *sock);
int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags);
int inet_accept(struct socket *sock, struct socket *newsock, int flags);
int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size);
ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags);
int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size, int flags);
int inet_shutdown(struct socket *sock, int how);
int inet_listen(struct socket *sock, int backlog);
void inet_sock_destruct(struct sock *sk);
int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
int inet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len,
int peer);
int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int inet_ctl_sock_create(struct sock **sk, unsigned short family,
unsigned short type, unsigned char protocol,
struct net *net);
int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
int *addr_len);
static inline void inet_ctl_sock_destroy(struct sock *sk)
{
sk_release_kernel(sk);
}
#endif

View file

@ -0,0 +1,353 @@
/*
* NET Generic infrastructure for INET connection oriented protocols.
*
* Definitions for inet_connection_sock
*
* Authors: Many people, see the TCP sources
*
* From code originally in TCP
*
* 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.
*/
#ifndef _INET_CONNECTION_SOCK_H
#define _INET_CONNECTION_SOCK_H
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/poll.h>
#include <net/inet_sock.h>
#include <net/request_sock.h>
#define INET_CSK_DEBUG 1
/* Cancel timers, when they are not required. */
#undef INET_CSK_CLEAR_TIMERS
struct inet_bind_bucket;
struct tcp_congestion_ops;
/*
* Pointers to address related TCP functions
* (i.e. things that depend on the address family)
*/
struct inet_connection_sock_af_ops {
int (*queue_xmit)(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
void (*send_check)(struct sock *sk, struct sk_buff *skb);
int (*rebuild_header)(struct sock *sk);
void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
int (*conn_request)(struct sock *sk, struct sk_buff *skb);
struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst);
u16 net_header_len;
u16 net_frag_header_len;
u16 sockaddr_len;
int (*setsockopt)(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
int (*getsockopt)(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
#ifdef CONFIG_COMPAT
int (*compat_setsockopt)(struct sock *sk,
int level, int optname,
char __user *optval, unsigned int optlen);
int (*compat_getsockopt)(struct sock *sk,
int level, int optname,
char __user *optval, int __user *optlen);
#endif
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
int (*bind_conflict)(const struct sock *sk,
const struct inet_bind_bucket *tb, bool relax);
void (*mtu_reduced)(struct sock *sk);
};
/** inet_connection_sock - INET connection oriented sock
*
* @icsk_accept_queue: FIFO of established children
* @icsk_bind_hash: Bind node
* @icsk_timeout: Timeout
* @icsk_retransmit_timer: Resend (no ack)
* @icsk_rto: Retransmit timeout
* @icsk_pmtu_cookie Last pmtu seen by socket
* @icsk_ca_ops Pluggable congestion control hook
* @icsk_af_ops Operations which are AF_INET{4,6} specific
* @icsk_ca_state: Congestion control state
* @icsk_retransmits: Number of unrecovered [RTO] timeouts
* @icsk_pending: Scheduled timer event
* @icsk_backoff: Backoff
* @icsk_syn_retries: Number of allowed SYN (or equivalent) retries
* @icsk_probes_out: unanswered 0 window probes
* @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options)
* @icsk_ack: Delayed ACK control data
* @icsk_mtup; MTU probing control data
*/
struct inet_connection_sock {
/* inet_sock has to be the first member! */
struct inet_sock icsk_inet;
struct request_sock_queue icsk_accept_queue;
struct inet_bind_bucket *icsk_bind_hash;
unsigned long icsk_timeout;
struct timer_list icsk_retransmit_timer;
struct timer_list icsk_delack_timer;
__u32 icsk_rto;
__u32 icsk_pmtu_cookie;
const struct tcp_congestion_ops *icsk_ca_ops;
const struct inet_connection_sock_af_ops *icsk_af_ops;
unsigned int (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
__u8 icsk_ca_state;
__u8 icsk_retransmits;
__u8 icsk_pending;
__u8 icsk_backoff;
__u8 icsk_syn_retries;
__u8 icsk_probes_out;
__u16 icsk_ext_hdr_len;
struct {
__u8 pending; /* ACK is pending */
__u8 quick; /* Scheduled number of quick acks */
__u8 pingpong; /* The session is interactive */
__u8 blocked; /* Delayed ACK was blocked by socket lock */
__u32 ato; /* Predicted tick of soft clock */
unsigned long timeout; /* Currently scheduled timeout */
__u32 lrcvtime; /* timestamp of last received data packet */
__u16 last_seg_size; /* Size of last incoming segment */
__u16 rcv_mss; /* MSS used for delayed ACK decisions */
} icsk_ack;
struct {
int enabled;
/* Range of MTUs to search */
int search_high;
int search_low;
/* Information on the current probe. */
int probe_size;
} icsk_mtup;
u32 icsk_ca_priv[16];
u32 icsk_user_timeout;
#define ICSK_CA_PRIV_SIZE (16 * sizeof(u32))
};
#define ICSK_TIME_RETRANS 1 /* Retransmit timer */
#define ICSK_TIME_DACK 2 /* Delayed ack timer */
#define ICSK_TIME_PROBE0 3 /* Zero window probe timer */
#define ICSK_TIME_EARLY_RETRANS 4 /* Early retransmit timer */
#define ICSK_TIME_LOSS_PROBE 5 /* Tail loss probe timer */
static inline struct inet_connection_sock *inet_csk(const struct sock *sk)
{
return (struct inet_connection_sock *)sk;
}
static inline void *inet_csk_ca(const struct sock *sk)
{
return (void *)inet_csk(sk)->icsk_ca_priv;
}
struct sock *inet_csk_clone_lock(const struct sock *sk,
const struct request_sock *req,
const gfp_t priority);
enum inet_csk_ack_state_t {
ICSK_ACK_SCHED = 1,
ICSK_ACK_TIMER = 2,
ICSK_ACK_PUSHED = 4,
ICSK_ACK_PUSHED2 = 8
};
void inet_csk_init_xmit_timers(struct sock *sk,
void (*retransmit_handler)(unsigned long),
void (*delack_handler)(unsigned long),
void (*keepalive_handler)(unsigned long));
void inet_csk_clear_xmit_timers(struct sock *sk);
static inline void inet_csk_schedule_ack(struct sock *sk)
{
inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_SCHED;
}
static inline int inet_csk_ack_scheduled(const struct sock *sk)
{
return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED;
}
static inline void inet_csk_delack_init(struct sock *sk)
{
memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
}
void inet_csk_delete_keepalive_timer(struct sock *sk);
void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
#ifdef INET_CSK_DEBUG
extern const char inet_csk_timer_bug_msg[];
#endif
static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what)
{
struct inet_connection_sock *icsk = inet_csk(sk);
if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) {
icsk->icsk_pending = 0;
#ifdef INET_CSK_CLEAR_TIMERS
sk_stop_timer(sk, &icsk->icsk_retransmit_timer);
#endif
} else if (what == ICSK_TIME_DACK) {
icsk->icsk_ack.blocked = icsk->icsk_ack.pending = 0;
#ifdef INET_CSK_CLEAR_TIMERS
sk_stop_timer(sk, &icsk->icsk_delack_timer);
#endif
}
#ifdef INET_CSK_DEBUG
else {
pr_debug("%s", inet_csk_timer_bug_msg);
}
#endif
}
/*
* Reset the retransmission timer
*/
static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
unsigned long when,
const unsigned long max_when)
{
struct inet_connection_sock *icsk = inet_csk(sk);
if (when > max_when) {
#ifdef INET_CSK_DEBUG
pr_debug("reset_xmit_timer: sk=%p %d when=0x%lx, caller=%p\n",
sk, what, when, current_text_addr());
#endif
when = max_when;
}
if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0 ||
what == ICSK_TIME_EARLY_RETRANS || what == ICSK_TIME_LOSS_PROBE) {
icsk->icsk_pending = what;
icsk->icsk_timeout = jiffies + when;
sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
} else if (what == ICSK_TIME_DACK) {
icsk->icsk_ack.pending |= ICSK_ACK_TIMER;
icsk->icsk_ack.timeout = jiffies + when;
sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout);
}
#ifdef INET_CSK_DEBUG
else {
pr_debug("%s", inet_csk_timer_bug_msg);
}
#endif
}
static inline unsigned long
inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
unsigned long max_when)
{
u64 when = (u64)icsk->icsk_rto << icsk->icsk_backoff;
return (unsigned long)min_t(u64, when, max_when);
}
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
struct request_sock *inet_csk_search_req(const struct sock *sk,
struct request_sock ***prevp,
const __be16 rport,
const __be32 raddr,
const __be32 laddr);
int inet_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb, bool relax);
int inet_csk_get_port(struct sock *sk, unsigned short snum);
struct dst_entry *inet_csk_route_req(struct sock *sk, struct flowi4 *fl4,
const struct request_sock *req);
struct dst_entry *inet_csk_route_child_sock(struct sock *sk, struct sock *newsk,
const struct request_sock *req);
static inline void inet_csk_reqsk_queue_add(struct sock *sk,
struct request_sock *req,
struct sock *child)
{
reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child);
}
void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
unsigned long timeout);
static inline void inet_csk_reqsk_queue_removed(struct sock *sk,
struct request_sock *req)
{
if (reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req) == 0)
inet_csk_delete_keepalive_timer(sk);
}
static inline void inet_csk_reqsk_queue_added(struct sock *sk,
const unsigned long timeout)
{
if (reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue) == 0)
inet_csk_reset_keepalive_timer(sk, timeout);
}
static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
{
return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
}
static inline int inet_csk_reqsk_queue_young(const struct sock *sk)
{
return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue);
}
static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue);
}
static inline void inet_csk_reqsk_queue_unlink(struct sock *sk,
struct request_sock *req,
struct request_sock **prev)
{
reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req, prev);
}
static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
struct request_sock *req,
struct request_sock **prev)
{
inet_csk_reqsk_queue_unlink(sk, req, prev);
inet_csk_reqsk_queue_removed(sk, req);
reqsk_free(req);
}
void inet_csk_reqsk_queue_prune(struct sock *parent,
const unsigned long interval,
const unsigned long timeout,
const unsigned long max_rto);
void inet_csk_destroy_sock(struct sock *sk);
void inet_csk_prepare_forced_close(struct sock *sk);
/*
* LISTEN is a special case for poll..
*/
static inline unsigned int inet_csk_listen_poll(const struct sock *sk)
{
return !reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) ?
(POLLIN | POLLRDNORM) : 0;
}
int inet_csk_listen_start(struct sock *sk, const int nr_table_entries);
void inet_csk_listen_stop(struct sock *sk);
void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET_CONNECTION_SOCK_H */

226
include/net/inet_ecn.h Normal file
View file

@ -0,0 +1,226 @@
#ifndef _INET_ECN_H_
#define _INET_ECN_H_
#include <linux/ip.h>
#include <linux/skbuff.h>
#include <net/inet_sock.h>
#include <net/dsfield.h>
enum {
INET_ECN_NOT_ECT = 0,
INET_ECN_ECT_1 = 1,
INET_ECN_ECT_0 = 2,
INET_ECN_CE = 3,
INET_ECN_MASK = 3,
};
extern int sysctl_tunnel_ecn_log;
static inline int INET_ECN_is_ce(__u8 dsfield)
{
return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
}
static inline int INET_ECN_is_not_ect(__u8 dsfield)
{
return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
}
static inline int INET_ECN_is_capable(__u8 dsfield)
{
return dsfield & INET_ECN_ECT_0;
}
/*
* RFC 3168 9.1.1
* The full-functionality option for ECN encapsulation is to copy the
* ECN codepoint of the inside header to the outside header on
* encapsulation if the inside header is not-ECT or ECT, and to set the
* ECN codepoint of the outside header to ECT(0) if the ECN codepoint of
* the inside header is CE.
*/
static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
{
outer &= ~INET_ECN_MASK;
outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
INET_ECN_ECT_0;
return outer;
}
static inline void INET_ECN_xmit(struct sock *sk)
{
inet_sk(sk)->tos |= INET_ECN_ECT_0;
if (inet6_sk(sk) != NULL)
inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
}
static inline void INET_ECN_dontxmit(struct sock *sk)
{
inet_sk(sk)->tos &= ~INET_ECN_MASK;
if (inet6_sk(sk) != NULL)
inet6_sk(sk)->tclass &= ~INET_ECN_MASK;
}
#define IP6_ECN_flow_init(label) do { \
(label) &= ~htonl(INET_ECN_MASK << 20); \
} while (0)
#define IP6_ECN_flow_xmit(sk, label) do { \
if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \
(label) |= htonl(INET_ECN_ECT_0 << 20); \
} while (0)
static inline int IP_ECN_set_ce(struct iphdr *iph)
{
u32 check = (__force u32)iph->check;
u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
/*
* After the last operation we have (in binary):
* INET_ECN_NOT_ECT => 01
* INET_ECN_ECT_1 => 10
* INET_ECN_ECT_0 => 11
* INET_ECN_CE => 00
*/
if (!(ecn & 2))
return !ecn;
/*
* The following gives us:
* INET_ECN_ECT_1 => check += htons(0xFFFD)
* INET_ECN_ECT_0 => check += htons(0xFFFE)
*/
check += (__force u16)htons(0xFFFB) + (__force u16)htons(ecn);
iph->check = (__force __sum16)(check + (check>=0xFFFF));
iph->tos |= INET_ECN_CE;
return 1;
}
static inline void IP_ECN_clear(struct iphdr *iph)
{
iph->tos &= ~INET_ECN_MASK;
}
static inline void ipv4_copy_dscp(unsigned int dscp, struct iphdr *inner)
{
dscp &= ~INET_ECN_MASK;
ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
}
struct ipv6hdr;
static inline int IP6_ECN_set_ce(struct ipv6hdr *iph)
{
if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
return 0;
*(__be32*)iph |= htonl(INET_ECN_CE << 20);
return 1;
}
static inline void IP6_ECN_clear(struct ipv6hdr *iph)
{
*(__be32*)iph &= ~htonl(INET_ECN_MASK << 20);
}
static inline void ipv6_copy_dscp(unsigned int dscp, struct ipv6hdr *inner)
{
dscp &= ~INET_ECN_MASK;
ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
}
static inline int INET_ECN_set_ce(struct sk_buff *skb)
{
switch (skb->protocol) {
case cpu_to_be16(ETH_P_IP):
if (skb_network_header(skb) + sizeof(struct iphdr) <=
skb_tail_pointer(skb))
return IP_ECN_set_ce(ip_hdr(skb));
break;
case cpu_to_be16(ETH_P_IPV6):
if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
skb_tail_pointer(skb))
return IP6_ECN_set_ce(ipv6_hdr(skb));
break;
}
return 0;
}
/*
* RFC 6040 4.2
* To decapsulate the inner header at the tunnel egress, a compliant
* tunnel egress MUST set the outgoing ECN field to the codepoint at the
* intersection of the appropriate arriving inner header (row) and outer
* header (column) in Figure 4
*
* +---------+------------------------------------------------+
* |Arriving | Arriving Outer Header |
* | Inner +---------+------------+------------+------------+
* | Header | Not-ECT | ECT(0) | ECT(1) | CE |
* +---------+---------+------------+------------+------------+
* | Not-ECT | Not-ECT |Not-ECT(!!!)|Not-ECT(!!!)| <drop>(!!!)|
* | ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE |
* | ECT(1) | ECT(1) | ECT(1) (!) | ECT(1) | CE |
* | CE | CE | CE | CE(!!!)| CE |
* +---------+---------+------------+------------+------------+
*
* Figure 4: New IP in IP Decapsulation Behaviour
*
* returns 0 on success
* 1 if something is broken and should be logged (!!! above)
* 2 if packet should be dropped
*/
static inline int INET_ECN_decapsulate(struct sk_buff *skb,
__u8 outer, __u8 inner)
{
if (INET_ECN_is_not_ect(inner)) {
switch (outer & INET_ECN_MASK) {
case INET_ECN_NOT_ECT:
return 0;
case INET_ECN_ECT_0:
case INET_ECN_ECT_1:
return 1;
case INET_ECN_CE:
return 2;
}
}
if (INET_ECN_is_ce(outer))
INET_ECN_set_ce(skb);
return 0;
}
static inline int IP_ECN_decapsulate(const struct iphdr *oiph,
struct sk_buff *skb)
{
__u8 inner;
if (skb->protocol == htons(ETH_P_IP))
inner = ip_hdr(skb)->tos;
else if (skb->protocol == htons(ETH_P_IPV6))
inner = ipv6_get_dsfield(ipv6_hdr(skb));
else
return 0;
return INET_ECN_decapsulate(skb, oiph->tos, inner);
}
static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h,
struct sk_buff *skb)
{
__u8 inner;
if (skb->protocol == htons(ETH_P_IP))
inner = ip_hdr(skb)->tos;
else if (skb->protocol == htons(ETH_P_IPV6))
inner = ipv6_get_dsfield(ipv6_hdr(skb));
else
return 0;
return INET_ECN_decapsulate(skb, ipv6_get_dsfield(oipv6h), inner);
}
#endif

179
include/net/inet_frag.h Normal file
View file

@ -0,0 +1,179 @@
#ifndef __NET_FRAG_H__
#define __NET_FRAG_H__
#include <linux/percpu_counter.h>
struct netns_frags {
/* The percpu_counter "mem" need to be cacheline aligned.
* mem.count must not share cacheline with other writers
*/
struct percpu_counter mem ____cacheline_aligned_in_smp;
/* sysctls */
int timeout;
int high_thresh;
int low_thresh;
};
/**
* fragment queue flags
*
* @INET_FRAG_FIRST_IN: first fragment has arrived
* @INET_FRAG_LAST_IN: final fragment has arrived
* @INET_FRAG_COMPLETE: frag queue has been processed and is due for destruction
* @INET_FRAG_EVICTED: frag queue is being evicted
*/
enum {
INET_FRAG_FIRST_IN = BIT(0),
INET_FRAG_LAST_IN = BIT(1),
INET_FRAG_COMPLETE = BIT(2),
INET_FRAG_EVICTED = BIT(3)
};
/**
* struct inet_frag_queue - fragment queue
*
* @lock: spinlock protecting the queue
* @timer: queue expiration timer
* @list: hash bucket list
* @refcnt: reference count of the queue
* @fragments: received fragments head
* @fragments_tail: received fragments tail
* @stamp: timestamp of the last received fragment
* @len: total length of the original datagram
* @meat: length of received fragments so far
* @flags: fragment queue flags
* @max_size: (ipv4 only) maximum received fragment size with IP_DF set
* @net: namespace that this frag belongs to
*/
struct inet_frag_queue {
spinlock_t lock;
struct timer_list timer;
struct hlist_node list;
atomic_t refcnt;
struct sk_buff *fragments;
struct sk_buff *fragments_tail;
ktime_t stamp;
int len;
int meat;
__u8 flags;
u16 max_size;
struct netns_frags *net;
};
#define INETFRAGS_HASHSZ 1024
/* averaged:
* max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
* rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
* struct frag_queue))
*/
#define INETFRAGS_MAXDEPTH 128
struct inet_frag_bucket {
struct hlist_head chain;
spinlock_t chain_lock;
};
struct inet_frags {
struct inet_frag_bucket hash[INETFRAGS_HASHSZ];
struct work_struct frags_work;
unsigned int next_bucket;
unsigned long last_rebuild_jiffies;
bool rebuild;
/* The first call to hashfn is responsible to initialize
* rnd. This is best done with net_get_random_once.
*
* rnd_seqlock is used to let hash insertion detect
* when it needs to re-lookup the hash chain to use.
*/
u32 rnd;
seqlock_t rnd_seqlock;
int qsize;
unsigned int (*hashfn)(const struct inet_frag_queue *);
bool (*match)(const struct inet_frag_queue *q,
const void *arg);
void (*constructor)(struct inet_frag_queue *q,
const void *arg);
void (*destructor)(struct inet_frag_queue *);
void (*skb_free)(struct sk_buff *);
void (*frag_expire)(unsigned long data);
struct kmem_cache *frags_cachep;
const char *frags_cache_name;
};
int inet_frags_init(struct inet_frags *);
void inet_frags_fini(struct inet_frags *);
void inet_frags_init_net(struct netns_frags *nf);
void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f);
struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
struct inet_frags *f, void *key, unsigned int hash);
void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
const char *prefix);
static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
{
if (atomic_dec_and_test(&q->refcnt))
inet_frag_destroy(q, f);
}
/* Memory Tracking Functions. */
/* The default percpu_counter batch size is not big enough to scale to
* fragmentation mem acct sizes.
* The mem size of a 64K fragment is approx:
* (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes
*/
static unsigned int frag_percpu_counter_batch = 130000;
static inline int frag_mem_limit(struct netns_frags *nf)
{
return percpu_counter_read(&nf->mem);
}
static inline void sub_frag_mem_limit(struct inet_frag_queue *q, int i)
{
__percpu_counter_add(&q->net->mem, -i, frag_percpu_counter_batch);
}
static inline void add_frag_mem_limit(struct inet_frag_queue *q, int i)
{
__percpu_counter_add(&q->net->mem, i, frag_percpu_counter_batch);
}
static inline void init_frag_mem_limit(struct netns_frags *nf)
{
percpu_counter_init(&nf->mem, 0, GFP_KERNEL);
}
static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf)
{
unsigned int res;
local_bh_disable();
res = percpu_counter_sum_positive(&nf->mem);
local_bh_enable();
return res;
}
/* RFC 3168 support :
* We want to check ECN values of all fragments, do detect invalid combinations.
* In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
*/
#define IPFRAG_ECN_NOT_ECT 0x01 /* one frag had ECN_NOT_ECT */
#define IPFRAG_ECN_ECT_1 0x02 /* one frag had ECN_ECT_1 */
#define IPFRAG_ECN_ECT_0 0x04 /* one frag had ECN_ECT_0 */
#define IPFRAG_ECN_CE 0x08 /* one frag had ECN_CE */
extern const u8 ip_frag_ecn_table[16];
#endif

View file

@ -0,0 +1,398 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Authors: Lotsa people, from code originally in tcp
*
* 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.
*/
#ifndef _INET_HASHTABLES_H
#define _INET_HASHTABLES_H
#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/vmalloc.h>
#include <net/inet_connection_sock.h>
#include <net/inet_sock.h>
#include <net/sock.h>
#include <net/route.h>
#include <net/tcp_states.h>
#include <net/netns/hash.h>
#include <linux/atomic.h>
#include <asm/byteorder.h>
/* This is for all connections with a full identity, no wildcards.
* The 'e' prefix stands for Establish, but we really put all sockets
* but LISTEN ones.
*/
struct inet_ehash_bucket {
struct hlist_nulls_head chain;
};
/* There are a few simple rules, which allow for local port reuse by
* an application. In essence:
*
* 1) Sockets bound to different interfaces may share a local port.
* Failing that, goto test 2.
* 2) If all sockets have sk->sk_reuse set, and none of them are in
* TCP_LISTEN state, the port may be shared.
* Failing that, goto test 3.
* 3) If all sockets are bound to a specific inet_sk(sk)->rcv_saddr local
* address, and none of them are the same, the port may be
* shared.
* Failing this, the port cannot be shared.
*
* The interesting point, is test #2. This is what an FTP server does
* all day. To optimize this case we use a specific flag bit defined
* below. As we add sockets to a bind bucket list, we perform a
* check of: (newsk->sk_reuse && (newsk->sk_state != TCP_LISTEN))
* As long as all sockets added to a bind bucket pass this test,
* the flag bit will be set.
* The resulting situation is that tcp_v[46]_verify_bind() can just check
* for this flag bit, if it is set and the socket trying to bind has
* sk->sk_reuse set, we don't even have to walk the owners list at all,
* we return that it is ok to bind this socket to the requested local port.
*
* Sounds like a lot of work, but it is worth it. In a more naive
* implementation (ie. current FreeBSD etc.) the entire list of ports
* must be walked for each data port opened by an ftp server. Needless
* to say, this does not scale at all. With a couple thousand FTP
* users logged onto your box, isn't it nice to know that new data
* ports are created in O(1) time? I thought so. ;-) -DaveM
*/
struct inet_bind_bucket {
#ifdef CONFIG_NET_NS
struct net *ib_net;
#endif
unsigned short port;
signed char fastreuse;
signed char fastreuseport;
kuid_t fastuid;
int num_owners;
struct hlist_node node;
struct hlist_head owners;
};
static inline struct net *ib_net(struct inet_bind_bucket *ib)
{
return read_pnet(&ib->ib_net);
}
#define inet_bind_bucket_for_each(tb, head) \
hlist_for_each_entry(tb, head, node)
struct inet_bind_hashbucket {
spinlock_t lock;
struct hlist_head chain;
};
/*
* Sockets can be hashed in established or listening table
* We must use different 'nulls' end-of-chain value for listening
* hash table, or we might find a socket that was closed and
* reallocated/inserted into established hash table
*/
#define LISTENING_NULLS_BASE (1U << 29)
struct inet_listen_hashbucket {
spinlock_t lock;
struct hlist_nulls_head head;
};
/* This is for listening sockets, thus all sockets which possess wildcards. */
#define INET_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */
struct inet_hashinfo {
/* This is for sockets with full identity only. Sockets here will
* always be without wildcards and will have the following invariant:
*
* TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
*
*/
struct inet_ehash_bucket *ehash;
spinlock_t *ehash_locks;
unsigned int ehash_mask;
unsigned int ehash_locks_mask;
/* Ok, let's try this, I give up, we do need a local binding
* TCP hash as well as the others for fast bind/connect.
*/
struct inet_bind_hashbucket *bhash;
unsigned int bhash_size;
/* 4 bytes hole on 64 bit */
struct kmem_cache *bind_bucket_cachep;
/* All the above members are written once at bootup and
* never written again _or_ are predominantly read-access.
*
* Now align to a new cache line as all the following members
* might be often dirty.
*/
/* All sockets in TCP_LISTEN state will be in here. This is the only
* table where wildcard'd TCP sockets can exist. Hash function here
* is just local port number.
*/
struct inet_listen_hashbucket listening_hash[INET_LHTABLE_SIZE]
____cacheline_aligned_in_smp;
atomic_t bsockets;
};
static inline struct inet_ehash_bucket *inet_ehash_bucket(
struct inet_hashinfo *hashinfo,
unsigned int hash)
{
return &hashinfo->ehash[hash & hashinfo->ehash_mask];
}
static inline spinlock_t *inet_ehash_lockp(
struct inet_hashinfo *hashinfo,
unsigned int hash)
{
return &hashinfo->ehash_locks[hash & hashinfo->ehash_locks_mask];
}
static inline int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
{
unsigned int i, size = 256;
#if defined(CONFIG_PROVE_LOCKING)
unsigned int nr_pcpus = 2;
#else
unsigned int nr_pcpus = num_possible_cpus();
#endif
if (nr_pcpus >= 4)
size = 512;
if (nr_pcpus >= 8)
size = 1024;
if (nr_pcpus >= 16)
size = 2048;
if (nr_pcpus >= 32)
size = 4096;
if (sizeof(spinlock_t) != 0) {
#ifdef CONFIG_NUMA
if (size * sizeof(spinlock_t) > PAGE_SIZE)
hashinfo->ehash_locks = vmalloc(size * sizeof(spinlock_t));
else
#endif
hashinfo->ehash_locks = kmalloc(size * sizeof(spinlock_t),
GFP_KERNEL);
if (!hashinfo->ehash_locks)
return ENOMEM;
for (i = 0; i < size; i++)
spin_lock_init(&hashinfo->ehash_locks[i]);
}
hashinfo->ehash_locks_mask = size - 1;
return 0;
}
static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
{
if (hashinfo->ehash_locks) {
#ifdef CONFIG_NUMA
unsigned int size = (hashinfo->ehash_locks_mask + 1) *
sizeof(spinlock_t);
if (size > PAGE_SIZE)
vfree(hashinfo->ehash_locks);
else
#endif
kfree(hashinfo->ehash_locks);
hashinfo->ehash_locks = NULL;
}
}
struct inet_bind_bucket *
inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
struct inet_bind_hashbucket *head,
const unsigned short snum);
void inet_bind_bucket_destroy(struct kmem_cache *cachep,
struct inet_bind_bucket *tb);
static inline int inet_bhashfn(struct net *net, const __u16 lport,
const int bhash_size)
{
return (lport + net_hash_mix(net)) & (bhash_size - 1);
}
void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
const unsigned short snum);
/* These can have wildcards, don't try too hard. */
static inline int inet_lhashfn(struct net *net, const unsigned short num)
{
return (num + net_hash_mix(net)) & (INET_LHTABLE_SIZE - 1);
}
static inline int inet_sk_listen_hashfn(const struct sock *sk)
{
return inet_lhashfn(sock_net(sk), inet_sk(sk)->inet_num);
}
/* Caller must disable local BH processing. */
int __inet_inherit_port(struct sock *sk, struct sock *child);
void inet_put_port(struct sock *sk);
void inet_hashinfo_init(struct inet_hashinfo *h);
int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw);
void inet_hash(struct sock *sk);
void inet_unhash(struct sock *sk);
struct sock *__inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
const __be32 saddr, const __be16 sport,
const __be32 daddr,
const unsigned short hnum,
const int dif);
static inline struct sock *inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
__be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif)
{
return __inet_lookup_listener(net, hashinfo, saddr, sport,
daddr, ntohs(dport), dif);
}
/* Socket demux engine toys. */
/* What happens here is ugly; there's a pair of adjacent fields in
struct inet_sock; __be16 dport followed by __u16 num. We want to
search by pair, so we combine the keys into a single 32bit value
and compare with 32bit value read from &...->dport. Let's at least
make sure that it's not mixed with anything else...
On 64bit targets we combine comparisons with pair of adjacent __be32
fields in the same way.
*/
#ifdef __BIG_ENDIAN
#define INET_COMBINED_PORTS(__sport, __dport) \
((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
#else /* __LITTLE_ENDIAN */
#define INET_COMBINED_PORTS(__sport, __dport) \
((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport)))
#endif
#if (BITS_PER_LONG == 64)
#ifdef __BIG_ENDIAN
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
const __addrpair __name = (__force __addrpair) ( \
(((__force __u64)(__be32)(__saddr)) << 32) | \
((__force __u64)(__be32)(__daddr)))
#else /* __LITTLE_ENDIAN */
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
const __addrpair __name = (__force __addrpair) ( \
(((__force __u64)(__be32)(__daddr)) << 32) | \
((__force __u64)(__be32)(__saddr)))
#endif /* __BIG_ENDIAN */
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_addrpair == (__cookie)) && \
(!(__sk)->sk_bound_dev_if || \
((__sk)->sk_bound_dev_if == (__dif))) && \
net_eq(sock_net(__sk), (__net)))
#else /* 32-bit arch */
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
const int __name __deprecated __attribute__((unused))
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_daddr == (__saddr)) && \
((__sk)->sk_rcv_saddr == (__daddr)) && \
(!(__sk)->sk_bound_dev_if || \
((__sk)->sk_bound_dev_if == (__dif))) && \
net_eq(sock_net(__sk), (__net)))
#endif /* 64-bit arch */
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need
* not check it for lookups anymore, thanks Alexey. -DaveM
*
* Local BH must be disabled here.
*/
struct sock *__inet_lookup_established(struct net *net,
struct inet_hashinfo *hashinfo,
const __be32 saddr, const __be16 sport,
const __be32 daddr, const u16 hnum,
const int dif);
static inline struct sock *
inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
const __be32 saddr, const __be16 sport,
const __be32 daddr, const __be16 dport,
const int dif)
{
return __inet_lookup_established(net, hashinfo, saddr, sport, daddr,
ntohs(dport), dif);
}
static inline struct sock *__inet_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
const __be32 saddr, const __be16 sport,
const __be32 daddr, const __be16 dport,
const int dif)
{
u16 hnum = ntohs(dport);
struct sock *sk = __inet_lookup_established(net, hashinfo,
saddr, sport, daddr, hnum, dif);
return sk ? : __inet_lookup_listener(net, hashinfo, saddr, sport,
daddr, hnum, dif);
}
static inline struct sock *inet_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
const __be32 saddr, const __be16 sport,
const __be32 daddr, const __be16 dport,
const int dif)
{
struct sock *sk;
local_bh_disable();
sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif);
local_bh_enable();
return sk;
}
static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
struct sk_buff *skb,
const __be16 sport,
const __be16 dport)
{
struct sock *sk = skb_steal_sock(skb);
const struct iphdr *iph = ip_hdr(skb);
if (sk)
return sk;
else
return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo,
iph->saddr, sport,
iph->daddr, dport, inet_iif(skb));
}
int __inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk, u32 port_offset,
int (*check_established)(struct inet_timewait_death_row *,
struct sock *, __u16,
struct inet_timewait_sock **),
int (*hash)(struct sock *sk,
struct inet_timewait_sock *twp));
int inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk);
#endif /* _INET_HASHTABLES_H */

253
include/net/inet_sock.h Normal file
View file

@ -0,0 +1,253 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for inet_sock
*
* Authors: Many, reorganised here by
* Arnaldo Carvalho de Melo <acme@mandriva.com>
*
* 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.
*/
#ifndef _INET_SOCK_H
#define _INET_SOCK_H
#include <linux/kmemcheck.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/jhash.h>
#include <linux/netdevice.h>
#include <net/flow.h>
#include <net/sock.h>
#include <net/request_sock.h>
#include <net/netns/hash.h>
/** struct ip_options - IP Options
*
* @faddr - Saved first hop address
* @nexthop - Saved nexthop address in LSRR and SSRR
* @is_strictroute - Strict source route
* @srr_is_hit - Packet destination addr was our one
* @is_changed - IP checksum more not valid
* @rr_needaddr - Need to record addr of outgoing dev
* @ts_needtime - Need to record timestamp
* @ts_needaddr - Need to record addr of outgoing dev
*/
struct ip_options {
__be32 faddr;
__be32 nexthop;
unsigned char optlen;
unsigned char srr;
unsigned char rr;
unsigned char ts;
unsigned char is_strictroute:1,
srr_is_hit:1,
is_changed:1,
rr_needaddr:1,
ts_needtime:1,
ts_needaddr:1;
unsigned char router_alert;
unsigned char cipso;
unsigned char __pad2;
unsigned char __data[0];
};
struct ip_options_rcu {
struct rcu_head rcu;
struct ip_options opt;
};
struct ip_options_data {
struct ip_options_rcu opt;
char data[40];
};
struct inet_request_sock {
struct request_sock req;
#define ir_loc_addr req.__req_common.skc_rcv_saddr
#define ir_rmt_addr req.__req_common.skc_daddr
#define ir_num req.__req_common.skc_num
#define ir_rmt_port req.__req_common.skc_dport
#define ir_v6_rmt_addr req.__req_common.skc_v6_daddr
#define ir_v6_loc_addr req.__req_common.skc_v6_rcv_saddr
#define ir_iif req.__req_common.skc_bound_dev_if
kmemcheck_bitfield_begin(flags);
u16 snd_wscale : 4,
rcv_wscale : 4,
tstamp_ok : 1,
sack_ok : 1,
wscale_ok : 1,
ecn_ok : 1,
acked : 1,
no_srccheck: 1;
kmemcheck_bitfield_end(flags);
union {
struct ip_options_rcu *opt;
struct sk_buff *pktopts;
};
u32 ir_mark;
};
static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
{
return (struct inet_request_sock *)sk;
}
static inline u32 inet_request_mark(struct sock *sk, struct sk_buff *skb)
{
if (!sk->sk_mark && sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept) {
return skb->mark;
} else {
return sk->sk_mark;
}
}
struct inet_cork {
unsigned int flags;
__be32 addr;
struct ip_options *opt;
unsigned int fragsize;
int length; /* Total length of all frames */
struct dst_entry *dst;
u8 tx_flags;
__u8 ttl;
__s16 tos;
char priority;
};
struct inet_cork_full {
struct inet_cork base;
struct flowi fl;
};
struct ip_mc_socklist;
struct ipv6_pinfo;
struct rtable;
/** struct inet_sock - representation of INET sockets
*
* @sk - ancestor class
* @pinet6 - pointer to IPv6 control block
* @inet_daddr - Foreign IPv4 addr
* @inet_rcv_saddr - Bound local IPv4 addr
* @inet_dport - Destination port
* @inet_num - Local port
* @inet_saddr - Sending source
* @uc_ttl - Unicast TTL
* @inet_sport - Source port
* @inet_id - ID counter for DF pkts
* @tos - TOS
* @mc_ttl - Multicasting TTL
* @is_icsk - is this an inet_connection_sock?
* @uc_index - Unicast outgoing device index
* @mc_index - Multicast device index
* @mc_list - Group array
* @cork - info to build ip hdr on each ip frag while socket is corked
*/
struct inet_sock {
/* sk and pinet6 has to be the first two members of inet_sock */
struct sock sk;
#if IS_ENABLED(CONFIG_IPV6)
struct ipv6_pinfo *pinet6;
#endif
/* Socket demultiplex comparisons on incoming packets. */
#define inet_daddr sk.__sk_common.skc_daddr
#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
#define inet_dport sk.__sk_common.skc_dport
#define inet_num sk.__sk_common.skc_num
__be32 inet_saddr;
__s16 uc_ttl;
__u16 cmsg_flags;
__be16 inet_sport;
__u16 inet_id;
struct ip_options_rcu __rcu *inet_opt;
int rx_dst_ifindex;
__u8 tos;
__u8 min_ttl;
__u8 mc_ttl;
__u8 pmtudisc;
__u8 recverr:1,
is_icsk:1,
freebind:1,
hdrincl:1,
mc_loop:1,
transparent:1,
mc_all:1,
nodefrag:1;
__u8 rcv_tos;
int uc_index;
int mc_index;
__be32 mc_addr;
struct ip_mc_socklist __rcu *mc_list;
struct inet_cork_full cork;
};
#define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */
#define IPCORK_ALLFRAG 2 /* always fragment (for ipv6 for now) */
static inline struct inet_sock *inet_sk(const struct sock *sk)
{
return (struct inet_sock *)sk;
}
static inline void __inet_sk_copy_descendant(struct sock *sk_to,
const struct sock *sk_from,
const int ancestor_size)
{
memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1,
sk_from->sk_prot->obj_size - ancestor_size);
}
#if !(IS_ENABLED(CONFIG_IPV6))
static inline void inet_sk_copy_descendant(struct sock *sk_to,
const struct sock *sk_from)
{
__inet_sk_copy_descendant(sk_to, sk_from, sizeof(struct inet_sock));
}
#endif
int inet_sk_rebuild_header(struct sock *sk);
static inline unsigned int __inet_ehashfn(const __be32 laddr,
const __u16 lport,
const __be32 faddr,
const __be16 fport,
u32 initval)
{
return jhash_3words((__force __u32) laddr,
(__force __u32) faddr,
((__u32) lport) << 16 | (__force __u32)fport,
initval);
}
static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops)
{
struct request_sock *req = reqsk_alloc(ops);
struct inet_request_sock *ireq = inet_rsk(req);
if (req != NULL) {
kmemcheck_annotate_bitfield(ireq, flags);
ireq->opt = NULL;
}
return req;
}
static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
{
__u8 flags = 0;
if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl)
flags |= FLOWI_FLAG_ANYSRC;
return flags;
}
#endif /* _INET_SOCK_H */

View file

@ -0,0 +1,220 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for a generic INET TIMEWAIT sock
*
* From code originally in net/tcp.h
*
* 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.
*/
#ifndef _INET_TIMEWAIT_SOCK_
#define _INET_TIMEWAIT_SOCK_
#include <linux/kmemcheck.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <net/inet_sock.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/timewait_sock.h>
#include <linux/atomic.h>
struct inet_hashinfo;
#define INET_TWDR_RECYCLE_SLOTS_LOG 5
#define INET_TWDR_RECYCLE_SLOTS (1 << INET_TWDR_RECYCLE_SLOTS_LOG)
/*
* If time > 4sec, it is "slow" path, no recycling is required,
* so that we select tick to get range about 4 seconds.
*/
#if HZ <= 16 || HZ > 4096
# error Unsupported: HZ <= 16 or HZ > 4096
#elif HZ <= 32
# define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 64
# define INET_TWDR_RECYCLE_TICK (6 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 128
# define INET_TWDR_RECYCLE_TICK (7 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 256
# define INET_TWDR_RECYCLE_TICK (8 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 512
# define INET_TWDR_RECYCLE_TICK (9 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 1024
# define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#elif HZ <= 2048
# define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#else
# define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
#endif
static inline u32 inet_tw_time_stamp(void)
{
return jiffies;
}
/* TIME_WAIT reaping mechanism. */
#define INET_TWDR_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
#define INET_TWDR_TWKILL_QUOTA 100
struct inet_timewait_death_row {
/* Short-time timewait calendar */
int twcal_hand;
unsigned long twcal_jiffie;
struct timer_list twcal_timer;
struct hlist_head twcal_row[INET_TWDR_RECYCLE_SLOTS];
spinlock_t death_lock;
int tw_count;
int period;
u32 thread_slots;
struct work_struct twkill_work;
struct timer_list tw_timer;
int slot;
struct hlist_head cells[INET_TWDR_TWKILL_SLOTS];
struct inet_hashinfo *hashinfo;
int sysctl_tw_recycle;
int sysctl_max_tw_buckets;
};
void inet_twdr_hangman(unsigned long data);
void inet_twdr_twkill_work(struct work_struct *work);
void inet_twdr_twcal_tick(unsigned long data);
struct inet_bind_bucket;
/*
* This is a TIME_WAIT sock. It works around the memory consumption
* problems of sockets in such a state on heavily loaded servers, but
* without violating the protocol specification.
*/
struct inet_timewait_sock {
/*
* Now struct sock also uses sock_common, so please just
* don't add nothing before this first member (__tw_common) --acme
*/
struct sock_common __tw_common;
#define tw_family __tw_common.skc_family
#define tw_state __tw_common.skc_state
#define tw_reuse __tw_common.skc_reuse
#define tw_ipv6only __tw_common.skc_ipv6only
#define tw_bound_dev_if __tw_common.skc_bound_dev_if
#define tw_node __tw_common.skc_nulls_node
#define tw_bind_node __tw_common.skc_bind_node
#define tw_refcnt __tw_common.skc_refcnt
#define tw_hash __tw_common.skc_hash
#define tw_prot __tw_common.skc_prot
#define tw_net __tw_common.skc_net
#define tw_daddr __tw_common.skc_daddr
#define tw_v6_daddr __tw_common.skc_v6_daddr
#define tw_rcv_saddr __tw_common.skc_rcv_saddr
#define tw_v6_rcv_saddr __tw_common.skc_v6_rcv_saddr
#define tw_dport __tw_common.skc_dport
#define tw_num __tw_common.skc_num
int tw_timeout;
volatile unsigned char tw_substate;
unsigned char tw_rcv_wscale;
/* Socket demultiplex comparisons on incoming packets. */
/* these three are in inet_sock */
__be16 tw_sport;
kmemcheck_bitfield_begin(flags);
/* And these are ours. */
unsigned int tw_pad0 : 1, /* 1 bit hole */
tw_transparent : 1,
tw_flowlabel : 20,
tw_pad : 2, /* 2 bits hole */
tw_tos : 8;
kmemcheck_bitfield_end(flags);
u32 tw_ttd;
struct inet_bind_bucket *tw_tb;
struct hlist_node tw_death_node;
};
#define tw_tclass tw_tos
static inline int inet_twsk_dead_hashed(const struct inet_timewait_sock *tw)
{
return !hlist_unhashed(&tw->tw_death_node);
}
static inline void inet_twsk_dead_node_init(struct inet_timewait_sock *tw)
{
tw->tw_death_node.pprev = NULL;
}
static inline void __inet_twsk_del_dead_node(struct inet_timewait_sock *tw)
{
__hlist_del(&tw->tw_death_node);
inet_twsk_dead_node_init(tw);
}
static inline int inet_twsk_del_dead_node(struct inet_timewait_sock *tw)
{
if (inet_twsk_dead_hashed(tw)) {
__inet_twsk_del_dead_node(tw);
return 1;
}
return 0;
}
#define inet_twsk_for_each(tw, node, head) \
hlist_nulls_for_each_entry(tw, node, head, tw_node)
#define inet_twsk_for_each_inmate(tw, jail) \
hlist_for_each_entry(tw, jail, tw_death_node)
#define inet_twsk_for_each_inmate_safe(tw, safe, jail) \
hlist_for_each_entry_safe(tw, safe, jail, tw_death_node)
static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk)
{
return (struct inet_timewait_sock *)sk;
}
void inet_twsk_free(struct inet_timewait_sock *tw);
void inet_twsk_put(struct inet_timewait_sock *tw);
int inet_twsk_unhash(struct inet_timewait_sock *tw);
int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
struct inet_hashinfo *hashinfo);
struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
const int state);
void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
struct inet_hashinfo *hashinfo);
void inet_twsk_schedule(struct inet_timewait_sock *tw,
struct inet_timewait_death_row *twdr,
const int timeo, const int timewait_len);
void inet_twsk_deschedule(struct inet_timewait_sock *tw,
struct inet_timewait_death_row *twdr);
void inet_twsk_purge(struct inet_hashinfo *hashinfo,
struct inet_timewait_death_row *twdr, int family);
static inline
struct net *twsk_net(const struct inet_timewait_sock *twsk)
{
return read_pnet(&twsk->tw_net);
}
static inline
void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net)
{
write_pnet(&twsk->tw_net, net);
}
#endif /* _INET_TIMEWAIT_SOCK_ */

173
include/net/inetpeer.h Normal file
View file

@ -0,0 +1,173 @@
/*
* INETPEER - A storage for permanent information about peers
*
* Authors: Andrey V. Savochkin <saw@msu.ru>
*/
#ifndef _NET_INETPEER_H
#define _NET_INETPEER_H
#include <linux/types.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/spinlock.h>
#include <linux/rtnetlink.h>
#include <net/ipv6.h>
#include <linux/atomic.h>
struct inetpeer_addr_base {
union {
__be32 a4;
__be32 a6[4];
};
};
struct inetpeer_addr {
struct inetpeer_addr_base addr;
__u16 family;
};
struct inet_peer {
/* group together avl_left,avl_right,v4daddr to speedup lookups */
struct inet_peer __rcu *avl_left, *avl_right;
struct inetpeer_addr daddr;
__u32 avl_height;
u32 metrics[RTAX_MAX];
u32 rate_tokens; /* rate limiting for ICMP */
unsigned long rate_last;
union {
struct list_head gc_list;
struct rcu_head gc_rcu;
};
/*
* Once inet_peer is queued for deletion (refcnt == -1), following field
* is not available: rid
* We can share memory with rcu_head to help keep inet_peer small.
*/
union {
struct {
atomic_t rid; /* Frag reception counter */
};
struct rcu_head rcu;
struct inet_peer *gc_next;
};
/* following fields might be frequently dirtied */
__u32 dtime; /* the time of last use of not referenced entries */
atomic_t refcnt;
};
struct inet_peer_base {
struct inet_peer __rcu *root;
seqlock_t lock;
int total;
};
#define INETPEER_BASE_BIT 0x1UL
static inline struct inet_peer *inetpeer_ptr(unsigned long val)
{
BUG_ON(val & INETPEER_BASE_BIT);
return (struct inet_peer *) val;
}
static inline struct inet_peer_base *inetpeer_base_ptr(unsigned long val)
{
if (!(val & INETPEER_BASE_BIT))
return NULL;
val &= ~INETPEER_BASE_BIT;
return (struct inet_peer_base *) val;
}
static inline bool inetpeer_ptr_is_peer(unsigned long val)
{
return !(val & INETPEER_BASE_BIT);
}
static inline void __inetpeer_ptr_set_peer(unsigned long *val, struct inet_peer *peer)
{
/* This implicitly clears INETPEER_BASE_BIT */
*val = (unsigned long) peer;
}
static inline bool inetpeer_ptr_set_peer(unsigned long *ptr, struct inet_peer *peer)
{
unsigned long val = (unsigned long) peer;
unsigned long orig = *ptr;
if (!(orig & INETPEER_BASE_BIT) ||
cmpxchg(ptr, orig, val) != orig)
return false;
return true;
}
static inline void inetpeer_init_ptr(unsigned long *ptr, struct inet_peer_base *base)
{
*ptr = (unsigned long) base | INETPEER_BASE_BIT;
}
static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from)
{
unsigned long val = *from;
*to = val;
if (inetpeer_ptr_is_peer(val)) {
struct inet_peer *peer = inetpeer_ptr(val);
atomic_inc(&peer->refcnt);
}
}
void inet_peer_base_init(struct inet_peer_base *);
void inet_initpeers(void) __init;
#define INETPEER_METRICS_NEW (~(u32) 0)
static inline bool inet_metrics_new(const struct inet_peer *p)
{
return p->metrics[RTAX_LOCK-1] == INETPEER_METRICS_NEW;
}
/* can be called with or without local BH being disabled */
struct inet_peer *inet_getpeer(struct inet_peer_base *base,
const struct inetpeer_addr *daddr,
int create);
static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
__be32 v4daddr,
int create)
{
struct inetpeer_addr daddr;
daddr.addr.a4 = v4daddr;
daddr.family = AF_INET;
return inet_getpeer(base, &daddr, create);
}
static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
const struct in6_addr *v6daddr,
int create)
{
struct inetpeer_addr daddr;
*(struct in6_addr *)daddr.addr.a6 = *v6daddr;
daddr.family = AF_INET6;
return inet_getpeer(base, &daddr, create);
}
/* can be called from BH context or outside */
void inet_putpeer(struct inet_peer *p);
bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
void inetpeer_invalidate_tree(struct inet_peer_base *);
/*
* temporary check to make sure we dont access rid, tcp_ts,
* tcp_ts_stamp if no refcount is taken on inet_peer
*/
static inline void inet_peer_refcheck(const struct inet_peer *p)
{
WARN_ON_ONCE(atomic_read(&p->refcnt) <= 0);
}
#endif /* _NET_INETPEER_H */

554
include/net/ip.h Normal file
View file

@ -0,0 +1,554 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the IP module.
*
* Version: @(#)ip.h 1.0.2 05/07/93
*
* Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Alan Cox, <gw4pts@gw4pts.ampr.org>
*
* Changes:
* Mike McLagan : Routing by source
*
* 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.
*/
#ifndef _IP_H
#define _IP_H
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <net/inet_sock.h>
#include <net/route.h>
#include <net/snmp.h>
#include <net/flow.h>
#include <net/flow_keys.h>
struct sock;
struct inet_skb_parm {
struct ip_options opt; /* Compiled IP options */
unsigned char flags;
#define IPSKB_FORWARDED BIT(0)
#define IPSKB_XFRM_TUNNEL_SIZE BIT(1)
#define IPSKB_XFRM_TRANSFORMED BIT(2)
#define IPSKB_FRAG_COMPLETE BIT(3)
#define IPSKB_REROUTED BIT(4)
#define IPSKB_DOREDIRECT BIT(5)
u16 frag_max_size;
};
static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
{
return ip_hdr(skb)->ihl * 4;
}
struct ipcm_cookie {
__be32 addr;
int oif;
struct ip_options_rcu *opt;
__u8 tx_flags;
__u8 ttl;
__s16 tos;
char priority;
};
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
struct ip_ra_chain {
struct ip_ra_chain __rcu *next;
struct sock *sk;
union {
void (*destructor)(struct sock *);
struct sock *saved_sk;
};
struct rcu_head rcu;
};
extern struct ip_ra_chain __rcu *ip_ra_chain;
/* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */
#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
#define IP_MF 0x2000 /* Flag: "More Fragments" */
#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
struct msghdr;
struct net_device;
struct packet_type;
struct rtable;
struct sockaddr;
int igmp_mc_init(void);
/*
* Functions provided by ip.c
*/
int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
__be32 saddr, __be32 daddr,
struct ip_options_rcu *opt);
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct net_device *orig_dev);
int ip_local_deliver(struct sk_buff *skb);
int ip_mr_input(struct sk_buff *skb);
int ip_output(struct sock *sk, struct sk_buff *skb);
int ip_mc_output(struct sock *sk, struct sk_buff *skb);
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
int ip_do_nat(struct sk_buff *skb);
void ip_send_check(struct iphdr *ip);
int __ip_local_out(struct sk_buff *skb);
int ip_local_out_sk(struct sock *sk, struct sk_buff *skb);
static inline int ip_local_out(struct sk_buff *skb)
{
return ip_local_out_sk(skb->sk, skb);
}
int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
void ip_init(void);
int ip_append_data(struct sock *sk, struct flowi4 *fl4,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
void *from, int len, int protolen,
struct ipcm_cookie *ipc,
struct rtable **rt,
unsigned int flags);
int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd,
struct sk_buff *skb);
ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
int offset, size_t size, int flags);
struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4,
struct sk_buff_head *queue,
struct inet_cork *cork);
int ip_send_skb(struct net *net, struct sk_buff *skb);
int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
void ip_flush_pending_frames(struct sock *sk);
struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
int getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
struct ipcm_cookie *ipc, struct rtable **rtp,
unsigned int flags);
static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
{
return __ip_make_skb(sk, fl4, &sk->sk_write_queue, &inet_sk(sk)->cork.base);
}
static inline __u8 get_rttos(struct ipcm_cookie* ipc, struct inet_sock *inet)
{
return (ipc->tos != -1) ? RT_TOS(ipc->tos) : RT_TOS(inet->tos);
}
static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk)
{
return (ipc->tos != -1) ? RT_CONN_FLAGS_TOS(sk, ipc->tos) : RT_CONN_FLAGS(sk);
}
/* datagram.c */
int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
void ip4_datagram_release_cb(struct sock *sk);
struct ip_reply_arg {
struct kvec iov[1];
int flags;
__wsum csum;
int csumoffset; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */
int bound_dev_if;
u8 tos;
kuid_t uid;
};
#define IP_REPLY_ARG_NOSRCCHECK 1
static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
{
return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
}
void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
const struct ip_options *sopt,
__be32 daddr, __be32 saddr,
const struct ip_reply_arg *arg,
unsigned int len);
#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
#define IP_INC_STATS_BH(net, field) SNMP_INC_STATS64_BH((net)->mib.ip_statistics, field)
#define IP_ADD_STATS(net, field, val) SNMP_ADD_STATS64((net)->mib.ip_statistics, field, val)
#define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS64_BH((net)->mib.ip_statistics, field, val)
#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS64((net)->mib.ip_statistics, field, val)
#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS64_BH((net)->mib.ip_statistics, field, val)
#define NET_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.net_statistics, field)
#define NET_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
#define NET_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
#define NET_ADD_STATS(net, field, adnd) SNMP_ADD_STATS((net)->mib.net_statistics, field, adnd)
#define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd)
#define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd)
unsigned long snmp_fold_field(void __percpu *mib, int offt);
#if BITS_PER_LONG==32
u64 snmp_fold_field64(void __percpu *mib, int offt, size_t sync_off);
#else
static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_off)
{
return snmp_fold_field(mib, offt);
}
#endif
void inet_get_local_port_range(struct net *net, int *low, int *high);
#ifdef CONFIG_SYSCTL
static inline int inet_is_local_reserved_port(struct net *net, int port)
{
if (!net->ipv4.sysctl_local_reserved_ports)
return 0;
return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
}
static inline bool sysctl_dev_name_is_allowed(const char *name)
{
return strcmp(name, "default") != 0 && strcmp(name, "all") != 0;
}
#else
static inline int inet_is_local_reserved_port(struct net *net, int port)
{
return 0;
}
#endif
/* From inetpeer.c */
extern int inet_peer_threshold;
extern int inet_peer_minttl;
extern int inet_peer_maxttl;
/* From ip_input.c */
extern int sysctl_ip_early_demux;
/* From ip_output.c */
extern int sysctl_ip_dynaddr;
void ipfrag_init(void);
void ip_static_sysctl_init(void);
#define IP4_REPLY_MARK(net, mark) \
((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0)
static inline bool ip_is_fragment(const struct iphdr *iph)
{
return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
}
#ifdef CONFIG_INET
#include <net/dst.h>
/* The function in 2.2 was invalid, producing wrong result for
* check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
static inline
int ip_decrease_ttl(struct iphdr *iph)
{
u32 check = (__force u32)iph->check;
check += (__force u32)htons(0x0100);
iph->check = (__force __sum16)(check + (check>=0xFFFF));
return --iph->ttl;
}
static inline
int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
{
return inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
(inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&
!(dst_metric_locked(dst, RTAX_MTU)));
}
static inline bool ip_sk_accept_pmtu(const struct sock *sk)
{
return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE &&
inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT;
}
static inline bool ip_sk_use_pmtu(const struct sock *sk)
{
return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
}
static inline bool ip_sk_ignore_df(const struct sock *sk)
{
return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO ||
inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT;
}
static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
bool forwarding)
{
struct net *net = dev_net(dst->dev);
if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
dst_metric_locked(dst, RTAX_MTU) ||
!forwarding)
return dst_mtu(dst);
return min(dst->dev->mtu, IP_MAX_MTU);
}
static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb)
{
if (!skb->sk || ip_sk_use_pmtu(skb->sk)) {
bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
} else {
return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU);
}
}
u32 ip_idents_reserve(u32 hash, int segs);
void __ip_select_ident(struct iphdr *iph, int segs);
static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs)
{
struct iphdr *iph = ip_hdr(skb);
if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
/* This is only to work around buggy Windows95/2000
* VJ compression implementations. If the ID field
* does not change, they drop every other packet in
* a TCP stream using header compression.
*/
if (sk && inet_sk(sk)->inet_daddr) {
iph->id = htons(inet_sk(sk)->inet_id);
inet_sk(sk)->inet_id += segs;
} else {
iph->id = 0;
}
} else {
__ip_select_ident(iph, segs);
}
}
static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk)
{
ip_select_ident_segs(skb, sk, 1);
}
static inline __wsum inet_compute_pseudo(struct sk_buff *skb, int proto)
{
return csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
skb->len, proto, 0);
}
static inline void inet_set_txhash(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
struct flow_keys keys;
keys.src = inet->inet_saddr;
keys.dst = inet->inet_daddr;
keys.port16[0] = inet->inet_sport;
keys.port16[1] = inet->inet_dport;
sk->sk_txhash = flow_hash_from_keys(&keys);
}
static inline __wsum inet_gro_compute_pseudo(struct sk_buff *skb, int proto)
{
const struct iphdr *iph = skb_gro_network_header(skb);
return csum_tcpudp_nofold(iph->saddr, iph->daddr,
skb_gro_len(skb), proto, 0);
}
/*
* Map a multicast IP onto multicast MAC for type ethernet.
*/
static inline void ip_eth_mc_map(__be32 naddr, char *buf)
{
__u32 addr=ntohl(naddr);
buf[0]=0x01;
buf[1]=0x00;
buf[2]=0x5e;
buf[5]=addr&0xFF;
addr>>=8;
buf[4]=addr&0xFF;
addr>>=8;
buf[3]=addr&0x7F;
}
/*
* Map a multicast IP onto multicast MAC for type IP-over-InfiniBand.
* Leave P_Key as 0 to be filled in by driver.
*/
static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
{
__u32 addr;
unsigned char scope = broadcast[5] & 0xF;
buf[0] = 0; /* Reserved */
buf[1] = 0xff; /* Multicast QPN */
buf[2] = 0xff;
buf[3] = 0xff;
addr = ntohl(naddr);
buf[4] = 0xff;
buf[5] = 0x10 | scope; /* scope from broadcast address */
buf[6] = 0x40; /* IPv4 signature */
buf[7] = 0x1b;
buf[8] = broadcast[8]; /* P_Key */
buf[9] = broadcast[9];
buf[10] = 0;
buf[11] = 0;
buf[12] = 0;
buf[13] = 0;
buf[14] = 0;
buf[15] = 0;
buf[19] = addr & 0xff;
addr >>= 8;
buf[18] = addr & 0xff;
addr >>= 8;
buf[17] = addr & 0xff;
addr >>= 8;
buf[16] = addr & 0x0f;
}
static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf)
{
if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0)
memcpy(buf, broadcast, 4);
else
memcpy(buf, &naddr, sizeof(naddr));
}
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
static __inline__ void inet_reset_saddr(struct sock *sk)
{
inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
#if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
memset(&np->saddr, 0, sizeof(np->saddr));
memset(&sk->sk_v6_rcv_saddr, 0, sizeof(sk->sk_v6_rcv_saddr));
}
#endif
}
#endif
bool ip_call_ra_chain(struct sk_buff *skb);
/*
* Functions provided by ip_fragment.c
*/
enum ip_defrag_users {
IP_DEFRAG_LOCAL_DELIVER,
IP_DEFRAG_CALL_RA_CHAIN,
IP_DEFRAG_CONNTRACK_IN,
__IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHRT_MAX,
IP_DEFRAG_CONNTRACK_OUT,
__IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
IP_DEFRAG_CONNTRACK_BRIDGE_IN,
__IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
IP_DEFRAG_VS_IN,
IP_DEFRAG_VS_OUT,
IP_DEFRAG_VS_FWD,
IP_DEFRAG_AF_PACKET,
IP_DEFRAG_MACVLAN,
};
int ip_defrag(struct sk_buff *skb, u32 user);
#ifdef CONFIG_INET
struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user);
#else
static inline struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
{
return skb;
}
#endif
int ip_frag_mem(struct net *net);
/*
* Functions provided by ip_forward.c
*/
int ip_forward(struct sk_buff *skb);
/*
* Functions provided by ip_options.c
*/
void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
__be32 daddr, struct rtable *rt, int is_frag);
int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
const struct ip_options *sopt);
static inline int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
{
return __ip_options_echo(dopt, skb, &IPCB(skb)->opt);
}
void ip_options_fragment(struct sk_buff *skb);
int ip_options_compile(struct net *net, struct ip_options *opt,
struct sk_buff *skb);
int ip_options_get(struct net *net, struct ip_options_rcu **optp,
unsigned char *data, int optlen);
int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp,
unsigned char __user *data, int optlen);
void ip_options_undo(struct ip_options *opt);
void ip_forward_options(struct sk_buff *skb);
int ip_options_rcv_srr(struct sk_buff *skb);
/*
* Functions provided by ip_sockglue.c
*/
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
int ip_cmsg_send(struct net *net, struct msghdr *msg,
struct ipcm_cookie *ipc, bool allow_ipv6);
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
unsigned int optlen);
int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
int __user *optlen);
int compat_ip_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
int compat_ip_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
int ip_ra_control(struct sock *sk, unsigned char on,
void (*destructor)(struct sock *));
int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
u32 info, u8 *payload);
void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
u32 info);
bool icmp_global_allow(void);
extern int sysctl_icmp_msgs_per_sec;
extern int sysctl_icmp_msgs_burst;
#ifdef CONFIG_PROC_FS
int ip_misc_proc_init(void);
#endif
#endif /* _IP_H */

106
include/net/ip6_checksum.h Normal file
View file

@ -0,0 +1,106 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Checksumming functions for IPv6
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Borrows very liberally from tcp.c and ip.c, see those
* files for more names.
*
* 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.
*/
/*
* Fixes:
*
* Ralf Baechle : generic ipv6 checksum
* <ralf@waldorf-gmbh.de>
*/
#ifndef _CHECKSUM_IPV6_H
#define _CHECKSUM_IPV6_H
#include <asm/types.h>
#include <asm/byteorder.h>
#include <net/ip.h>
#include <asm/checksum.h>
#include <linux/in6.h>
#include <linux/tcp.h>
#include <linux/ipv6.h>
#ifndef _HAVE_ARCH_IPV6_CSUM
__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__u32 len, unsigned short proto,
__wsum csum);
#endif
static inline __wsum ip6_compute_pseudo(struct sk_buff *skb, int proto)
{
return ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
skb->len, proto, 0));
}
static inline __wsum ip6_gro_compute_pseudo(struct sk_buff *skb, int proto)
{
const struct ipv6hdr *iph = skb_gro_network_header(skb);
return ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
skb_gro_len(skb), proto, 0));
}
static __inline__ __sum16 tcp_v6_check(int len,
const struct in6_addr *saddr,
const struct in6_addr *daddr,
__wsum base)
{
return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
}
static inline void __tcp_v6_send_check(struct sk_buff *skb,
const struct in6_addr *saddr,
const struct in6_addr *daddr)
{
struct tcphdr *th = tcp_hdr(skb);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
skb->csum_start = skb_transport_header(skb) - skb->head;
skb->csum_offset = offsetof(struct tcphdr, check);
} else {
th->check = tcp_v6_check(skb->len, saddr, daddr,
csum_partial(th, th->doff << 2,
skb->csum));
}
}
#if IS_ENABLED(CONFIG_IPV6)
static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
{
struct ipv6_pinfo *np = inet6_sk(sk);
__tcp_v6_send_check(skb, &np->saddr, &sk->sk_v6_daddr);
}
#endif
static inline __sum16 udp_v6_check(int len,
const struct in6_addr *saddr,
const struct in6_addr *daddr,
__wsum base)
{
return csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, base);
}
void udp6_set_csum(bool nocheck, struct sk_buff *skb,
const struct in6_addr *saddr,
const struct in6_addr *daddr, int len);
int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto);
#endif

322
include/net/ip6_fib.h Normal file
View file

@ -0,0 +1,322 @@
/*
* Linux INET6 implementation
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
* 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.
*/
#ifndef _IP6_FIB_H
#define _IP6_FIB_H
#include <linux/ipv6_route.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include <net/dst.h>
#include <net/flow.h>
#include <net/netlink.h>
#include <net/inetpeer.h>
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
#define FIB6_TABLE_HASHSZ 256
#else
#define FIB6_TABLE_HASHSZ 1
#endif
struct rt6_info;
struct fib6_config {
u32 fc_table;
u32 fc_metric;
int fc_dst_len;
int fc_src_len;
int fc_ifindex;
u32 fc_flags;
u32 fc_protocol;
u32 fc_type; /* only 8 bits are used */
struct in6_addr fc_dst;
struct in6_addr fc_src;
struct in6_addr fc_prefsrc;
struct in6_addr fc_gateway;
unsigned long fc_expires;
struct nlattr *fc_mx;
int fc_mx_len;
int fc_mp_len;
struct nlattr *fc_mp;
struct nl_info fc_nlinfo;
};
struct fib6_node {
struct fib6_node *parent;
struct fib6_node *left;
struct fib6_node *right;
#ifdef CONFIG_IPV6_SUBTREES
struct fib6_node *subtree;
#endif
struct rt6_info *leaf;
__u16 fn_bit; /* bit key */
__u16 fn_flags;
int fn_sernum;
struct rt6_info *rr_ptr;
};
#ifndef CONFIG_IPV6_SUBTREES
#define FIB6_SUBTREE(fn) NULL
#else
#define FIB6_SUBTREE(fn) ((fn)->subtree)
#endif
/*
* routing information
*
*/
struct rt6key {
struct in6_addr addr;
int plen;
};
struct fib6_table;
struct rt6_info {
struct dst_entry dst;
/*
* Tail elements of dst_entry (__refcnt etc.)
* and these elements (rarely used in hot path) are in
* the same cache line.
*/
struct fib6_table *rt6i_table;
struct fib6_node *rt6i_node;
struct in6_addr rt6i_gateway;
/* Multipath routes:
* siblings is a list of rt6_info that have the the same metric/weight,
* destination, but not the same gateway. nsiblings is just a cache
* to speed up lookup.
*/
struct list_head rt6i_siblings;
unsigned int rt6i_nsiblings;
atomic_t rt6i_ref;
/* These are in a separate cache line. */
struct rt6key rt6i_dst ____cacheline_aligned_in_smp;
u32 rt6i_flags;
struct rt6key rt6i_src;
struct rt6key rt6i_prefsrc;
struct inet6_dev *rt6i_idev;
unsigned long _rt6i_peer;
u32 rt6i_metric;
/* more non-fragment space at head required */
unsigned short rt6i_nfheader_len;
u8 rt6i_protocol;
};
static inline struct inet_peer *rt6_peer_ptr(struct rt6_info *rt)
{
return inetpeer_ptr(rt->_rt6i_peer);
}
static inline bool rt6_has_peer(struct rt6_info *rt)
{
return inetpeer_ptr_is_peer(rt->_rt6i_peer);
}
static inline void __rt6_set_peer(struct rt6_info *rt, struct inet_peer *peer)
{
__inetpeer_ptr_set_peer(&rt->_rt6i_peer, peer);
}
static inline bool rt6_set_peer(struct rt6_info *rt, struct inet_peer *peer)
{
return inetpeer_ptr_set_peer(&rt->_rt6i_peer, peer);
}
static inline void rt6_init_peer(struct rt6_info *rt, struct inet_peer_base *base)
{
inetpeer_init_ptr(&rt->_rt6i_peer, base);
}
static inline void rt6_transfer_peer(struct rt6_info *rt, struct rt6_info *ort)
{
inetpeer_transfer_peer(&rt->_rt6i_peer, &ort->_rt6i_peer);
}
static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
{
return ((struct rt6_info *)dst)->rt6i_idev;
}
static inline void rt6_clean_expires(struct rt6_info *rt)
{
rt->rt6i_flags &= ~RTF_EXPIRES;
rt->dst.expires = 0;
}
static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
{
rt->dst.expires = expires;
rt->rt6i_flags |= RTF_EXPIRES;
}
static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
{
struct rt6_info *rt;
for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
rt = (struct rt6_info *)rt->dst.from);
if (rt && rt != rt0)
rt0->dst.expires = rt->dst.expires;
dst_set_expires(&rt0->dst, timeout);
rt0->rt6i_flags |= RTF_EXPIRES;
}
static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
{
struct dst_entry *new = (struct dst_entry *) from;
rt->rt6i_flags &= ~RTF_EXPIRES;
dst_hold(new);
rt->dst.from = new;
}
static inline void ip6_rt_put(struct rt6_info *rt)
{
/* dst_release() accepts a NULL parameter.
* We rely on dst being first structure in struct rt6_info
*/
BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
dst_release(&rt->dst);
}
enum fib6_walk_state {
#ifdef CONFIG_IPV6_SUBTREES
FWS_S,
#endif
FWS_L,
FWS_R,
FWS_C,
FWS_U
};
struct fib6_walker {
struct list_head lh;
struct fib6_node *root, *node;
struct rt6_info *leaf;
enum fib6_walk_state state;
bool prune;
unsigned int skip;
unsigned int count;
int (*func)(struct fib6_walker *);
void *args;
};
struct rt6_statistics {
__u32 fib_nodes;
__u32 fib_route_nodes;
__u32 fib_rt_alloc; /* permanent routes */
__u32 fib_rt_entries; /* rt entries in table */
__u32 fib_rt_cache; /* cache routes */
__u32 fib_discarded_routes;
};
#define RTN_TL_ROOT 0x0001
#define RTN_ROOT 0x0002 /* tree root node */
#define RTN_RTINFO 0x0004 /* node with valid routing info */
/*
* priority levels (or metrics)
*
*/
struct fib6_table {
struct hlist_node tb6_hlist;
u32 tb6_id;
rwlock_t tb6_lock;
struct fib6_node tb6_root;
struct inet_peer_base tb6_peers;
};
#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
#define RT6_TABLE_MAIN RT_TABLE_MAIN
#define RT6_TABLE_DFLT RT6_TABLE_MAIN
#define RT6_TABLE_INFO RT6_TABLE_MAIN
#define RT6_TABLE_PREFIX RT6_TABLE_MAIN
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
#define FIB6_TABLE_MIN 1
#define FIB6_TABLE_MAX RT_TABLE_MAX
#define RT6_TABLE_LOCAL RT_TABLE_LOCAL
#else
#define FIB6_TABLE_MIN RT_TABLE_MAIN
#define FIB6_TABLE_MAX FIB6_TABLE_MIN
#define RT6_TABLE_LOCAL RT6_TABLE_MAIN
#endif
typedef struct rt6_info *(*pol_lookup_t)(struct net *,
struct fib6_table *,
struct flowi6 *, int);
/*
* exported functions
*/
struct fib6_table *fib6_get_table(struct net *net, u32 id);
struct fib6_table *fib6_new_table(struct net *net, u32 id);
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup);
struct fib6_node *fib6_lookup(struct fib6_node *root,
const struct in6_addr *daddr,
const struct in6_addr *saddr);
struct fib6_node *fib6_locate(struct fib6_node *root,
const struct in6_addr *daddr, int dst_len,
const struct in6_addr *saddr, int src_len);
void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
void *arg);
int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info,
struct nlattr *mx, int mx_len);
int fib6_del(struct rt6_info *rt, struct nl_info *info);
void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info);
void fib6_run_gc(unsigned long expires, struct net *net, bool force);
void fib6_gc_cleanup(void);
int fib6_init(void);
int ipv6_route_open(struct inode *inode, struct file *file);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
int fib6_rules_init(void);
void fib6_rules_cleanup(void);
#else
static inline int fib6_rules_init(void)
{
return 0;
}
static inline void fib6_rules_cleanup(void)
{
return ;
}
#endif
#endif

201
include/net/ip6_route.h Normal file
View file

@ -0,0 +1,201 @@
#ifndef _NET_IP6_ROUTE_H
#define _NET_IP6_ROUTE_H
struct route_info {
__u8 type;
__u8 length;
__u8 prefix_len;
#if defined(__BIG_ENDIAN_BITFIELD)
__u8 reserved_h:3,
route_pref:2,
reserved_l:3;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 reserved_l:3,
route_pref:2,
reserved_h:3;
#endif
__be32 lifetime;
__u8 prefix[0]; /* 0,8 or 16 */
};
#include <net/flow.h>
#include <net/ip6_fib.h>
#include <net/sock.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/route.h>
#define RT6_LOOKUP_F_IFACE 0x00000001
#define RT6_LOOKUP_F_REACHABLE 0x00000002
#define RT6_LOOKUP_F_HAS_SADDR 0x00000004
#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008
#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
/* We do not (yet ?) support IPv6 jumbograms (RFC 2675)
* Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
*/
#define IP6_MAX_MTU (0xFFFF + sizeof(struct ipv6hdr))
/*
* rt6_srcprefs2flags() and rt6_flags2srcprefs() translate
* between IPV6_ADDR_PREFERENCES socket option values
* IPV6_PREFER_SRC_TMP = 0x1
* IPV6_PREFER_SRC_PUBLIC = 0x2
* IPV6_PREFER_SRC_COA = 0x4
* and above RT6_LOOKUP_F_SRCPREF_xxx flags.
*/
static inline int rt6_srcprefs2flags(unsigned int srcprefs)
{
/* No need to bitmask because srcprefs have only 3 bits. */
return srcprefs << 3;
}
static inline unsigned int rt6_flags2srcprefs(int flags)
{
return (flags >> 3) & 7;
}
static inline bool rt6_need_strict(const struct in6_addr *daddr)
{
return ipv6_addr_type(daddr) &
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
}
void ip6_route_input(struct sk_buff *skb);
struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
struct flowi6 *fl6);
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
int flags);
int ip6_route_init(void);
void ip6_route_cleanup(void);
int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg);
int ip6_route_add(struct fib6_config *cfg);
int ip6_ins_rt(struct rt6_info *);
int ip6_del_rt(struct rt6_info *);
int ip6_route_get_saddr(struct net *net, struct rt6_info *rt,
const struct in6_addr *daddr, unsigned int prefs,
struct in6_addr *saddr);
struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
const struct in6_addr *saddr, int oif, int flags);
struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct flowi6 *fl6);
int icmp6_dst_gc(void);
void fib6_force_start_gc(struct net *net);
struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
const struct in6_addr *addr, bool anycast);
/*
* support functions for ND
*
*/
struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr,
struct net_device *dev);
struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
struct net_device *dev, unsigned int pref);
void rt6_purge_dflt_routers(struct net *net);
int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
const struct in6_addr *gwaddr);
void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
u32 mark, kuid_t uid);
void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
u32 mark);
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
struct netlink_callback;
struct rt6_rtnl_dump_arg {
struct sk_buff *skb;
struct netlink_callback *cb;
struct net *net;
};
int rt6_dump_route(struct rt6_info *rt, void *p_arg);
void rt6_ifdown(struct net *net, struct net_device *dev);
void rt6_mtu_change(struct net_device *dev, unsigned int mtu);
void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway);
/*
* Store a destination cache entry in a socket
*/
static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct rt6_info *rt = (struct rt6_info *) dst;
sk_setup_caps(sk, dst);
np->daddr_cache = daddr;
#ifdef CONFIG_IPV6_SUBTREES
np->saddr_cache = saddr;
#endif
np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
}
static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
struct in6_addr *daddr, struct in6_addr *saddr)
{
spin_lock(&sk->sk_dst_lock);
__ip6_dst_store(sk, dst, daddr, saddr);
spin_unlock(&sk->sk_dst_lock);
}
static inline bool ipv6_unicast_destination(const struct sk_buff *skb)
{
struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
return rt->rt6i_flags & RTF_LOCAL;
}
static inline bool ipv6_anycast_destination(const struct sk_buff *skb)
{
struct rt6_info *rt = (struct rt6_info *) skb_dst(skb);
return rt->rt6i_flags & RTF_ANYCAST;
}
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
{
struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
inet6_sk(skb->sk) : NULL;
return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ?
skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
}
static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
{
return inet6_sk(sk)->pmtudisc != IPV6_PMTUDISC_INTERFACE &&
inet6_sk(sk)->pmtudisc != IPV6_PMTUDISC_OMIT;
}
static inline bool ip6_sk_ignore_df(const struct sock *sk)
{
return inet6_sk(sk)->pmtudisc < IPV6_PMTUDISC_DO ||
inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT;
}
static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
{
return &rt->rt6i_gateway;
}
#endif

92
include/net/ip6_tunnel.h Normal file
View file

@ -0,0 +1,92 @@
#ifndef _NET_IP6_TUNNEL_H
#define _NET_IP6_TUNNEL_H
#include <linux/ipv6.h>
#include <linux/netdevice.h>
#include <linux/if_tunnel.h>
#include <linux/ip6_tunnel.h>
#define IP6TUNNEL_ERR_TIMEO (30*HZ)
/* capable of sending packets */
#define IP6_TNL_F_CAP_XMIT 0x10000
/* capable of receiving packets */
#define IP6_TNL_F_CAP_RCV 0x20000
/* determine capability on a per-packet basis */
#define IP6_TNL_F_CAP_PER_PACKET 0x40000
struct __ip6_tnl_parm {
char name[IFNAMSIZ]; /* name of tunnel device */
int link; /* ifindex of underlying L2 interface */
__u8 proto; /* tunnel protocol */
__u8 encap_limit; /* encapsulation limit for tunnel */
__u8 hop_limit; /* hop limit for tunnel */
__be32 flowinfo; /* traffic class and flowlabel for tunnel */
__u32 flags; /* tunnel flags */
struct in6_addr laddr; /* local tunnel end-point address */
struct in6_addr raddr; /* remote tunnel end-point address */
__be16 i_flags;
__be16 o_flags;
__be32 i_key;
__be32 o_key;
};
/* IPv6 tunnel */
struct ip6_tnl {
struct ip6_tnl __rcu *next; /* next tunnel in list */
struct net_device *dev; /* virtual device associated with tunnel */
struct net *net; /* netns for packet i/o */
struct __ip6_tnl_parm parms; /* tunnel configuration parameters */
struct flowi fl; /* flowi template for xmit */
struct dst_entry *dst_cache; /* cached dst */
u32 dst_cookie;
int err_count;
unsigned long err_time;
/* These fields used only by GRE */
__u32 i_seqno; /* The last seen seqno */
__u32 o_seqno; /* The last output seqno */
int hlen; /* Precalculated GRE header length */
int mlink;
};
/* Tunnel encapsulation limit destination sub-option */
struct ipv6_tlv_tnl_enc_lim {
__u8 type; /* type-code for option */
__u8 length; /* option length */
__u8 encap_limit; /* tunnel encapsulation limit */
} __packed;
struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t);
void ip6_tnl_dst_reset(struct ip6_tnl *t);
void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst);
int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
int ip6_tnl_xmit_ctl(struct ip6_tnl *t);
__u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
__u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *stats = &dev->stats;
int pkt_len, err;
pkt_len = skb->len;
err = ip6_local_out(skb);
if (net_xmit_eval(err) == 0) {
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
u64_stats_update_begin(&tstats->syncp);
tstats->tx_bytes += pkt_len;
tstats->tx_packets++;
u64_stats_update_end(&tstats->syncp);
} else {
stats->tx_errors++;
stats->tx_aborted_errors++;
}
}
#endif

338
include/net/ip_fib.h Normal file
View file

@ -0,0 +1,338 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the Forwarding Information Base.
*
* Authors: A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
* 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.
*/
#ifndef _NET_IP_FIB_H
#define _NET_IP_FIB_H
#include <net/flow.h>
#include <linux/seq_file.h>
#include <linux/rcupdate.h>
#include <net/fib_rules.h>
#include <net/inetpeer.h>
#include <linux/percpu.h>
struct fib_config {
u8 fc_dst_len;
u8 fc_tos;
u8 fc_protocol;
u8 fc_scope;
u8 fc_type;
/* 3 bytes unused */
u32 fc_table;
__be32 fc_dst;
__be32 fc_gw;
int fc_oif;
u32 fc_flags;
u32 fc_priority;
__be32 fc_prefsrc;
struct nlattr *fc_mx;
struct rtnexthop *fc_mp;
int fc_mx_len;
int fc_mp_len;
u32 fc_flow;
u32 fc_nlflags;
struct nl_info fc_nlinfo;
};
struct fib_info;
struct rtable;
struct fib_nh_exception {
struct fib_nh_exception __rcu *fnhe_next;
int fnhe_genid;
__be32 fnhe_daddr;
u32 fnhe_pmtu;
__be32 fnhe_gw;
unsigned long fnhe_expires;
struct rtable __rcu *fnhe_rth_input;
struct rtable __rcu *fnhe_rth_output;
unsigned long fnhe_stamp;
};
struct fnhe_hash_bucket {
struct fib_nh_exception __rcu *chain;
};
#define FNHE_HASH_SHIFT 11
#define FNHE_HASH_SIZE (1 << FNHE_HASH_SHIFT)
#define FNHE_RECLAIM_DEPTH 5
struct fib_nh {
struct net_device *nh_dev;
struct hlist_node nh_hash;
struct fib_info *nh_parent;
unsigned int nh_flags;
unsigned char nh_scope;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
int nh_weight;
int nh_power;
#endif
#ifdef CONFIG_IP_ROUTE_CLASSID
__u32 nh_tclassid;
#endif
int nh_oif;
__be32 nh_gw;
__be32 nh_saddr;
int nh_saddr_genid;
struct rtable __rcu * __percpu *nh_pcpu_rth_output;
struct rtable __rcu *nh_rth_input;
struct fnhe_hash_bucket __rcu *nh_exceptions;
};
/*
* This structure contains data shared by many of routes.
*/
struct fib_info {
struct hlist_node fib_hash;
struct hlist_node fib_lhash;
struct net *fib_net;
int fib_treeref;
atomic_t fib_clntref;
unsigned int fib_flags;
unsigned char fib_dead;
unsigned char fib_protocol;
unsigned char fib_scope;
unsigned char fib_type;
__be32 fib_prefsrc;
u32 fib_priority;
u32 *fib_metrics;
#define fib_mtu fib_metrics[RTAX_MTU-1]
#define fib_window fib_metrics[RTAX_WINDOW-1]
#define fib_rtt fib_metrics[RTAX_RTT-1]
#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
int fib_nhs;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
int fib_power;
#endif
struct rcu_head rcu;
struct fib_nh fib_nh[0];
#define fib_dev fib_nh[0].nh_dev
};
#ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_rule;
#endif
struct fib_table;
struct fib_result {
unsigned char prefixlen;
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
u32 tclassid;
struct fib_info *fi;
struct fib_table *table;
struct list_head *fa_head;
};
struct fib_result_nl {
__be32 fl_addr; /* To be looked up*/
u32 fl_mark;
unsigned char fl_tos;
unsigned char fl_scope;
unsigned char tb_id_in;
unsigned char tb_id; /* Results */
unsigned char prefixlen;
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
int err;
};
#ifdef CONFIG_IP_ROUTE_MULTIPATH
#define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
#else /* CONFIG_IP_ROUTE_MULTIPATH */
#define FIB_RES_NH(res) ((res).fi->fib_nh[0])
#endif /* CONFIG_IP_ROUTE_MULTIPATH */
#ifdef CONFIG_IP_MULTIPLE_TABLES
#define FIB_TABLE_HASHSZ 256
#else
#define FIB_TABLE_HASHSZ 2
#endif
__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
#define FIB_RES_SADDR(net, res) \
((FIB_RES_NH(res).nh_saddr_genid == \
atomic_read(&(net)->ipv4.dev_addr_genid)) ? \
FIB_RES_NH(res).nh_saddr : \
fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
#define FIB_RES_PREFSRC(net, res) ((res).fi->fib_prefsrc ? : \
FIB_RES_SADDR(net, res))
struct fib_table {
struct hlist_node tb_hlist;
u32 tb_id;
int tb_default;
int tb_num_default;
unsigned long tb_data[0];
};
int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
struct fib_result *res, int fib_flags);
int fib_table_insert(struct fib_table *, struct fib_config *);
int fib_table_delete(struct fib_table *, struct fib_config *);
int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
struct netlink_callback *cb);
int fib_table_flush(struct fib_table *table);
void fib_free_table(struct fib_table *tb);
#ifndef CONFIG_IP_MULTIPLE_TABLES
#define TABLE_LOCAL_INDEX 0
#define TABLE_MAIN_INDEX 1
static inline struct fib_table *fib_get_table(struct net *net, u32 id)
{
struct hlist_head *ptr;
ptr = id == RT_TABLE_LOCAL ?
&net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
&net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
return hlist_entry(ptr->first, struct fib_table, tb_hlist);
}
static inline struct fib_table *fib_new_table(struct net *net, u32 id)
{
return fib_get_table(net, id);
}
static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
struct fib_result *res)
{
struct fib_table *table;
table = fib_get_table(net, RT_TABLE_LOCAL);
if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
return 0;
table = fib_get_table(net, RT_TABLE_MAIN);
if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
return 0;
return -ENETUNREACH;
}
#else /* CONFIG_IP_MULTIPLE_TABLES */
int __net_init fib4_rules_init(struct net *net);
void __net_exit fib4_rules_exit(struct net *net);
struct fib_table *fib_new_table(struct net *net, u32 id);
struct fib_table *fib_get_table(struct net *net, u32 id);
int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res);
static inline int fib_lookup(struct net *net, struct flowi4 *flp,
struct fib_result *res)
{
if (!net->ipv4.fib_has_custom_rules) {
res->tclassid = 0;
if (net->ipv4.fib_local &&
!fib_table_lookup(net->ipv4.fib_local, flp, res,
FIB_LOOKUP_NOREF))
return 0;
if (net->ipv4.fib_main &&
!fib_table_lookup(net->ipv4.fib_main, flp, res,
FIB_LOOKUP_NOREF))
return 0;
if (net->ipv4.fib_default &&
!fib_table_lookup(net->ipv4.fib_default, flp, res,
FIB_LOOKUP_NOREF))
return 0;
return -ENETUNREACH;
}
return __fib_lookup(net, flp, res);
}
#endif /* CONFIG_IP_MULTIPLE_TABLES */
/* Exported by fib_frontend.c */
extern const struct nla_policy rtm_ipv4_policy[];
void ip_fib_init(void);
__be32 fib_compute_spec_dst(struct sk_buff *skb);
int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
u8 tos, int oif, struct net_device *dev,
struct in_device *idev, u32 *itag);
void fib_select_default(struct fib_result *res);
#ifdef CONFIG_IP_ROUTE_CLASSID
static inline int fib_num_tclassid_users(struct net *net)
{
return net->ipv4.fib_num_tclassid_users;
}
#else
static inline int fib_num_tclassid_users(struct net *net)
{
return 0;
}
#endif
/* Exported by fib_semantics.c */
int ip_fib_check_default(__be32 gw, struct net_device *dev);
int fib_sync_down_dev(struct net_device *dev, int force);
int fib_sync_down_addr(struct net *net, __be32 local);
int fib_sync_up(struct net_device *dev);
void fib_select_multipath(struct fib_result *res);
/* Exported by fib_trie.c */
void fib_trie_init(void);
struct fib_table *fib_trie_table(u32 id);
static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
{
#ifdef CONFIG_IP_ROUTE_CLASSID
#ifdef CONFIG_IP_MULTIPLE_TABLES
u32 rtag;
#endif
*itag = FIB_RES_NH(*res).nh_tclassid<<16;
#ifdef CONFIG_IP_MULTIPLE_TABLES
rtag = res->tclassid;
if (*itag == 0)
*itag = (rtag<<16);
*itag |= (rtag>>16);
#endif
#endif
}
void free_fib_info(struct fib_info *fi);
static inline void fib_info_put(struct fib_info *fi)
{
if (atomic_dec_and_test(&fi->fib_clntref))
free_fib_info(fi);
}
#ifdef CONFIG_PROC_FS
int __net_init fib_proc_init(struct net *net);
void __net_exit fib_proc_exit(struct net *net);
#else
static inline int fib_proc_init(struct net *net)
{
return 0;
}
static inline void fib_proc_exit(struct net *net)
{
}
#endif
#endif /* _NET_FIB_H */

205
include/net/ip_tunnels.h Normal file
View file

@ -0,0 +1,205 @@
#ifndef __NET_IP_TUNNELS_H
#define __NET_IP_TUNNELS_H 1
#include <linux/if_tunnel.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/u64_stats_sync.h>
#include <net/dsfield.h>
#include <net/gro_cells.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#endif
/* Keep error state on tunnel for 30 sec */
#define IPTUNNEL_ERR_TIMEO (30*HZ)
/* 6rd prefix/relay information */
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd_parm {
struct in6_addr prefix;
__be32 relay_prefix;
u16 prefixlen;
u16 relay_prefixlen;
};
#endif
struct ip_tunnel_encap {
__u16 type;
__u16 flags;
__be16 sport;
__be16 dport;
};
struct ip_tunnel_prl_entry {
struct ip_tunnel_prl_entry __rcu *next;
__be32 addr;
u16 flags;
struct rcu_head rcu_head;
};
struct ip_tunnel_dst {
struct dst_entry __rcu *dst;
__be32 saddr;
};
struct ip_tunnel {
struct ip_tunnel __rcu *next;
struct hlist_node hash_node;
struct net_device *dev;
struct net *net; /* netns for packet i/o */
int err_count; /* Number of arrived ICMP errors */
unsigned long err_time; /* Time when the last ICMP error
* arrived */
/* These four fields used only by GRE */
__u32 i_seqno; /* The last seen seqno */
__u32 o_seqno; /* The last output seqno */
int tun_hlen; /* Precalculated header length */
int mlink;
struct ip_tunnel_dst __percpu *dst_cache;
struct ip_tunnel_parm parms;
int encap_hlen; /* Encap header length (FOU,GUE) */
struct ip_tunnel_encap encap;
int hlen; /* tun_hlen + encap_hlen */
/* for SIT */
#ifdef CONFIG_IPV6_SIT_6RD
struct ip_tunnel_6rd_parm ip6rd;
#endif
struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
unsigned int prl_count; /* # of entries in PRL */
int ip_tnl_net_id;
struct gro_cells gro_cells;
};
#define TUNNEL_CSUM __cpu_to_be16(0x01)
#define TUNNEL_ROUTING __cpu_to_be16(0x02)
#define TUNNEL_KEY __cpu_to_be16(0x04)
#define TUNNEL_SEQ __cpu_to_be16(0x08)
#define TUNNEL_STRICT __cpu_to_be16(0x10)
#define TUNNEL_REC __cpu_to_be16(0x20)
#define TUNNEL_VERSION __cpu_to_be16(0x40)
#define TUNNEL_NO_KEY __cpu_to_be16(0x80)
#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100)
#define TUNNEL_OAM __cpu_to_be16(0x0200)
#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400)
#define TUNNEL_OPTIONS_PRESENT __cpu_to_be16(0x0800)
struct tnl_ptk_info {
__be16 flags;
__be16 proto;
__be32 key;
__be32 seq;
};
#define PACKET_RCVD 0
#define PACKET_REJECT 1
#define IP_TNL_HASH_BITS 7
#define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS)
struct ip_tunnel_net {
struct net_device *fb_tunnel_dev;
struct hlist_head tunnels[IP_TNL_HASH_SIZE];
};
#ifdef CONFIG_INET
int ip_tunnel_init(struct net_device *dev);
void ip_tunnel_uninit(struct net_device *dev);
void ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname);
void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops);
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
const struct iphdr *tnl_params, const u8 protocol);
int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
u8 *protocol, struct flowi4 *fl4);
int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *tot);
struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
int link, __be16 flags,
__be32 remote, __be32 local,
__be32 key);
int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
const struct tnl_ptk_info *tpi, bool log_ecn_error);
int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm *p);
int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm *p);
void ip_tunnel_setup(struct net_device *dev, int net_id);
void ip_tunnel_dst_reset_all(struct ip_tunnel *t);
int ip_tunnel_encap_setup(struct ip_tunnel *t,
struct ip_tunnel_encap *ipencap);
/* Extract dsfield from inner protocol */
static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
const struct sk_buff *skb)
{
if (skb->protocol == htons(ETH_P_IP))
return iph->tos;
else if (skb->protocol == htons(ETH_P_IPV6))
return ipv6_get_dsfield((const struct ipv6hdr *)iph);
else
return 0;
}
/* Propogate ECN bits out */
static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
const struct sk_buff *skb)
{
u8 inner = ip_tunnel_get_dsfield(iph, skb);
return INET_ECN_encapsulate(tos, inner);
}
int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto,
__u8 tos, __u8 ttl, __be16 df, bool xnet);
struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
int gso_type_mask);
static inline void iptunnel_xmit_stats(int err,
struct net_device_stats *err_stats,
struct pcpu_sw_netstats __percpu *stats)
{
if (err > 0) {
struct pcpu_sw_netstats *tstats = this_cpu_ptr(stats);
u64_stats_update_begin(&tstats->syncp);
tstats->tx_bytes += err;
tstats->tx_packets++;
u64_stats_update_end(&tstats->syncp);
} else if (err < 0) {
err_stats->tx_errors++;
err_stats->tx_aborted_errors++;
} else {
err_stats->tx_dropped++;
}
}
#endif /* CONFIG_INET */
#endif /* __NET_IP_TUNNELS_H */

1573
include/net/ip_vs.h Normal file

File diff suppressed because it is too large Load diff

29
include/net/ipcomp.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef _NET_IPCOMP_H
#define _NET_IPCOMP_H
#include <linux/types.h>
#define IPCOMP_SCRATCH_SIZE 65400
struct crypto_comp;
struct ipcomp_data {
u16 threshold;
struct crypto_comp * __percpu *tfms;
};
struct ip_comp_hdr;
struct sk_buff;
struct xfrm_state;
int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
void ipcomp_destroy(struct xfrm_state *x);
int ipcomp_init_state(struct xfrm_state *x);
static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
{
return (struct ip_comp_hdr *)skb_transport_header(skb);
}
#endif

25
include/net/ipconfig.h Normal file
View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 1997 Martin Mares
*
* Automatic IP Layer Configuration
*/
/* The following are initdata: */
extern int ic_proto_enabled; /* Protocols enabled (see IC_xxx) */
extern int ic_set_manually; /* IPconfig parameters set manually */
extern __be32 ic_myaddr; /* My IP address */
extern __be32 ic_gateway; /* Gateway IP address */
extern __be32 ic_servaddr; /* Boot server IP address */
extern __be32 root_server_addr; /* Address of NFS server */
extern u8 root_server_path[]; /* Path to mount as root */
/* bits in ic_proto_{enabled,used} */
#define IC_PROTO 0xFF /* Protocols mask: */
#define IC_BOOTP 0x01 /* BOOTP (or DHCP, see below) */
#define IC_RARP 0x02 /* RARP */
#define IC_USE_DHCP 0x100 /* If on, use DHCP instead of BOOTP */

923
include/net/ipv6.h Normal file
View file

@ -0,0 +1,923 @@
/*
* Linux INET6 implementation
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
* 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.
*/
#ifndef _NET_IPV6_H
#define _NET_IPV6_H
#include <linux/ipv6.h>
#include <linux/hardirq.h>
#include <linux/jhash.h>
#include <net/if_inet6.h>
#include <net/ndisc.h>
#include <net/flow.h>
#include <net/flow_keys.h>
#include <net/snmp.h>
#define SIN6_LEN_RFC2133 24
#define IPV6_MAXPLEN 65535
/*
* NextHeader field of IPv6 header
*/
#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */
#define NEXTHDR_TCP 6 /* TCP segment. */
#define NEXTHDR_UDP 17 /* UDP message. */
#define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */
#define NEXTHDR_ROUTING 43 /* Routing header. */
#define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */
#define NEXTHDR_GRE 47 /* GRE header. */
#define NEXTHDR_ESP 50 /* Encapsulating security payload. */
#define NEXTHDR_AUTH 51 /* Authentication header. */
#define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
#define NEXTHDR_NONE 59 /* No next header */
#define NEXTHDR_DEST 60 /* Destination options header. */
#define NEXTHDR_SCTP 132 /* SCTP message. */
#define NEXTHDR_MOBILITY 135 /* Mobility header. */
#define NEXTHDR_MAX 255
#define IPV6_DEFAULT_HOPLIMIT 64
#define IPV6_DEFAULT_MCASTHOPS 1
/*
* Addr type
*
* type - unicast | multicast
* scope - local | site | global
* v4 - compat
* v4mapped
* any
* loopback
*/
#define IPV6_ADDR_ANY 0x0000U
#define IPV6_ADDR_UNICAST 0x0001U
#define IPV6_ADDR_MULTICAST 0x0002U
#define IPV6_ADDR_LOOPBACK 0x0010U
#define IPV6_ADDR_LINKLOCAL 0x0020U
#define IPV6_ADDR_SITELOCAL 0x0040U
#define IPV6_ADDR_COMPATv4 0x0080U
#define IPV6_ADDR_SCOPE_MASK 0x00f0U
#define IPV6_ADDR_MAPPED 0x1000U
/*
* Addr scopes
*/
#define IPV6_ADDR_MC_SCOPE(a) \
((a)->s6_addr[1] & 0x0f) /* nonstandard */
#define __IPV6_ADDR_SCOPE_INVALID -1
#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08
#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
/*
* Addr flags
*/
#define IPV6_ADDR_MC_FLAG_TRANSIENT(a) \
((a)->s6_addr[1] & 0x10)
#define IPV6_ADDR_MC_FLAG_PREFIX(a) \
((a)->s6_addr[1] & 0x20)
#define IPV6_ADDR_MC_FLAG_RENDEZVOUS(a) \
((a)->s6_addr[1] & 0x40)
/*
* fragmentation header
*/
struct frag_hdr {
__u8 nexthdr;
__u8 reserved;
__be16 frag_off;
__be32 identification;
};
#define IP6_MF 0x0001
#define IP6_OFFSET 0xFFF8
#define IP6_REPLY_MARK(net, mark) \
((net)->ipv6.sysctl.fwmark_reflect ? (mark) : 0)
#include <net/sock.h>
/* sysctls */
extern int sysctl_mld_max_msf;
extern int sysctl_mld_qrv;
#define _DEVINC(net, statname, modifier, idev, field) \
({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
})
/* per device counters are atomic_long_t */
#define _DEVINCATOMIC(net, statname, modifier, idev, field) \
({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
})
/* per device and per net counters are atomic_long_t */
#define _DEVINC_ATOMIC_ATOMIC(net, statname, idev, field) \
({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field));\
})
#define _DEVADD(net, statname, modifier, idev, field, val) \
({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
})
#define _DEVUPD(net, statname, modifier, idev, field, val) \
({ \
struct inet6_dev *_idev = (idev); \
if (likely(_idev != NULL)) \
SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
})
/* MIBs */
#define IP6_INC_STATS(net, idev,field) \
_DEVINC(net, ipv6, 64, idev, field)
#define IP6_INC_STATS_BH(net, idev,field) \
_DEVINC(net, ipv6, 64_BH, idev, field)
#define IP6_ADD_STATS(net, idev,field,val) \
_DEVADD(net, ipv6, 64, idev, field, val)
#define IP6_ADD_STATS_BH(net, idev,field,val) \
_DEVADD(net, ipv6, 64_BH, idev, field, val)
#define IP6_UPD_PO_STATS(net, idev,field,val) \
_DEVUPD(net, ipv6, 64, idev, field, val)
#define IP6_UPD_PO_STATS_BH(net, idev,field,val) \
_DEVUPD(net, ipv6, 64_BH, idev, field, val)
#define ICMP6_INC_STATS(net, idev, field) \
_DEVINCATOMIC(net, icmpv6, , idev, field)
#define ICMP6_INC_STATS_BH(net, idev, field) \
_DEVINCATOMIC(net, icmpv6, _BH, idev, field)
#define ICMP6MSGOUT_INC_STATS(net, idev, field) \
_DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \
_DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
#define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \
_DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field)
struct ip6_ra_chain {
struct ip6_ra_chain *next;
struct sock *sk;
int sel;
void (*destructor)(struct sock *);
};
extern struct ip6_ra_chain *ip6_ra_chain;
extern rwlock_t ip6_ra_lock;
/*
This structure is prepared by protocol, when parsing
ancillary data and passed to IPv6.
*/
struct ipv6_txoptions {
/* Length of this structure */
int tot_len;
/* length of extension headers */
__u16 opt_flen; /* after fragment hdr */
__u16 opt_nflen; /* before fragment hdr */
struct ipv6_opt_hdr *hopopt;
struct ipv6_opt_hdr *dst0opt;
struct ipv6_rt_hdr *srcrt; /* Routing Header */
struct ipv6_opt_hdr *dst1opt;
/* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
};
struct ip6_flowlabel {
struct ip6_flowlabel __rcu *next;
__be32 label;
atomic_t users;
struct in6_addr dst;
struct ipv6_txoptions *opt;
unsigned long linger;
struct rcu_head rcu;
u8 share;
union {
struct pid *pid;
kuid_t uid;
} owner;
unsigned long lastuse;
unsigned long expires;
struct net *fl_net;
};
#define IPV6_FLOWINFO_MASK cpu_to_be32(0x0FFFFFFF)
#define IPV6_FLOWLABEL_MASK cpu_to_be32(0x000FFFFF)
#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
#define IPV6_TCLASS_SHIFT 20
struct ipv6_fl_socklist {
struct ipv6_fl_socklist __rcu *next;
struct ip6_flowlabel *fl;
struct rcu_head rcu;
};
struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
struct ip6_flowlabel *fl,
struct ipv6_txoptions *fopt);
void fl6_free_socklist(struct sock *sk);
int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq,
int flags);
int ip6_flowlabel_init(void);
void ip6_flowlabel_cleanup(void);
static inline void fl6_sock_release(struct ip6_flowlabel *fl)
{
if (fl)
atomic_dec(&fl->users);
}
void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
struct icmp6hdr *thdr, int len);
int ip6_ra_control(struct sock *sk, int sel);
int ipv6_parse_hopopts(struct sk_buff *skb);
struct ipv6_txoptions *ipv6_dup_options(struct sock *sk,
struct ipv6_txoptions *opt);
struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
struct ipv6_txoptions *opt,
int newtype,
struct ipv6_opt_hdr __user *newopt,
int newoptlen);
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *opt);
bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,
const struct inet6_skb_parm *opt);
static inline bool ipv6_accept_ra(struct inet6_dev *idev)
{
/* If forwarding is enabled, RA are not accepted unless the special
* hybrid mode (accept_ra=2) is enabled.
*/
return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 :
idev->cnf.accept_ra;
}
#if IS_ENABLED(CONFIG_IPV6)
static inline int ip6_frag_mem(struct net *net)
{
return sum_frag_mem_limit(&net->ipv6.frags);
}
#endif
#define IPV6_FRAG_HIGH_THRESH (4 * 1024*1024) /* 4194304 */
#define IPV6_FRAG_LOW_THRESH (3 * 1024*1024) /* 3145728 */
#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */
int __ipv6_addr_type(const struct in6_addr *addr);
static inline int ipv6_addr_type(const struct in6_addr *addr)
{
return __ipv6_addr_type(addr) & 0xffff;
}
static inline int ipv6_addr_scope(const struct in6_addr *addr)
{
return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
}
static inline int __ipv6_addr_src_scope(int type)
{
return (type == IPV6_ADDR_ANY) ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16);
}
static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
{
return __ipv6_addr_src_scope(__ipv6_addr_type(addr));
}
static inline bool __ipv6_addr_needs_scope_id(int type)
{
return type & IPV6_ADDR_LINKLOCAL ||
(type & IPV6_ADDR_MULTICAST &&
(type & (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)));
}
static inline __u32 ipv6_iface_scope_id(const struct in6_addr *addr, int iface)
{
return __ipv6_addr_needs_scope_id(__ipv6_addr_type(addr)) ? iface : 0;
}
static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
{
return memcmp(a1, a2, sizeof(struct in6_addr));
}
static inline bool
ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
const struct in6_addr *a2)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
const unsigned long *ul1 = (const unsigned long *)a1;
const unsigned long *ulm = (const unsigned long *)m;
const unsigned long *ul2 = (const unsigned long *)a2;
return !!(((ul1[0] ^ ul2[0]) & ulm[0]) |
((ul1[1] ^ ul2[1]) & ulm[1]));
#else
return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]));
#endif
}
static inline void ipv6_addr_prefix(struct in6_addr *pfx,
const struct in6_addr *addr,
int plen)
{
/* caller must guarantee 0 <= plen <= 128 */
int o = plen >> 3,
b = plen & 0x7;
memset(pfx->s6_addr, 0, sizeof(pfx->s6_addr));
memcpy(pfx->s6_addr, addr, o);
if (b != 0)
pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
}
static inline void __ipv6_addr_set_half(__be32 *addr,
__be32 wh, __be32 wl)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
#if defined(__BIG_ENDIAN)
if (__builtin_constant_p(wh) && __builtin_constant_p(wl)) {
*(__force u64 *)addr = ((__force u64)(wh) << 32 | (__force u64)(wl));
return;
}
#elif defined(__LITTLE_ENDIAN)
if (__builtin_constant_p(wl) && __builtin_constant_p(wh)) {
*(__force u64 *)addr = ((__force u64)(wl) << 32 | (__force u64)(wh));
return;
}
#endif
#endif
addr[0] = wh;
addr[1] = wl;
}
static inline void ipv6_addr_set(struct in6_addr *addr,
__be32 w1, __be32 w2,
__be32 w3, __be32 w4)
{
__ipv6_addr_set_half(&addr->s6_addr32[0], w1, w2);
__ipv6_addr_set_half(&addr->s6_addr32[2], w3, w4);
}
static inline bool ipv6_addr_equal(const struct in6_addr *a1,
const struct in6_addr *a2)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
const unsigned long *ul1 = (const unsigned long *)a1;
const unsigned long *ul2 = (const unsigned long *)a2;
return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL;
#else
return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
(a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
(a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
(a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0;
#endif
}
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
static inline bool __ipv6_prefix_equal64_half(const __be64 *a1,
const __be64 *a2,
unsigned int len)
{
if (len && ((*a1 ^ *a2) & cpu_to_be64((~0UL) << (64 - len))))
return false;
return true;
}
static inline bool ipv6_prefix_equal(const struct in6_addr *addr1,
const struct in6_addr *addr2,
unsigned int prefixlen)
{
const __be64 *a1 = (const __be64 *)addr1;
const __be64 *a2 = (const __be64 *)addr2;
if (prefixlen >= 64) {
if (a1[0] ^ a2[0])
return false;
return __ipv6_prefix_equal64_half(a1 + 1, a2 + 1, prefixlen - 64);
}
return __ipv6_prefix_equal64_half(a1, a2, prefixlen);
}
#else
static inline bool ipv6_prefix_equal(const struct in6_addr *addr1,
const struct in6_addr *addr2,
unsigned int prefixlen)
{
const __be32 *a1 = addr1->s6_addr32;
const __be32 *a2 = addr2->s6_addr32;
unsigned int pdw, pbi;
/* check complete u32 in prefix */
pdw = prefixlen >> 5;
if (pdw && memcmp(a1, a2, pdw << 2))
return false;
/* check incomplete u32 in prefix */
pbi = prefixlen & 0x1f;
if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
return false;
return true;
}
#endif
struct inet_frag_queue;
enum ip6_defrag_users {
IP6_DEFRAG_LOCAL_DELIVER,
IP6_DEFRAG_CONNTRACK_IN,
__IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHRT_MAX,
IP6_DEFRAG_CONNTRACK_OUT,
__IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
__IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
};
struct ip6_create_arg {
__be32 id;
u32 user;
const struct in6_addr *src;
const struct in6_addr *dst;
u8 ecn;
};
void ip6_frag_init(struct inet_frag_queue *q, const void *a);
bool ip6_frag_match(const struct inet_frag_queue *q, const void *a);
/*
* Equivalent of ipv4 struct ip
*/
struct frag_queue {
struct inet_frag_queue q;
__be32 id; /* fragment id */
u32 user;
struct in6_addr saddr;
struct in6_addr daddr;
int iif;
unsigned int csum;
__u16 nhoffset;
u8 ecn;
};
void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
struct inet_frags *frags);
static inline bool ipv6_addr_any(const struct in6_addr *a)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
const unsigned long *ul = (const unsigned long *)a;
return (ul[0] | ul[1]) == 0UL;
#else
return (a->s6_addr32[0] | a->s6_addr32[1] |
a->s6_addr32[2] | a->s6_addr32[3]) == 0;
#endif
}
static inline u32 ipv6_addr_hash(const struct in6_addr *a)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
const unsigned long *ul = (const unsigned long *)a;
unsigned long x = ul[0] ^ ul[1];
return (u32)(x ^ (x >> 32));
#else
return (__force u32)(a->s6_addr32[0] ^ a->s6_addr32[1] ^
a->s6_addr32[2] ^ a->s6_addr32[3]);
#endif
}
/* more secured version of ipv6_addr_hash() */
static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 initval)
{
u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1];
return jhash_3words(v,
(__force u32)a->s6_addr32[2],
(__force u32)a->s6_addr32[3],
initval);
}
static inline bool ipv6_addr_loopback(const struct in6_addr *a)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
const __be64 *be = (const __be64 *)a;
return (be[0] | (be[1] ^ cpu_to_be64(1))) == 0UL;
#else
return (a->s6_addr32[0] | a->s6_addr32[1] |
a->s6_addr32[2] | (a->s6_addr32[3] ^ cpu_to_be32(1))) == 0;
#endif
}
/*
* Note that we must __force cast these to unsigned long to make sparse happy,
* since all of the endian-annotated types are fixed size regardless of arch.
*/
static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
{
return (
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
*(unsigned long *)a |
#else
(__force unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
#endif
(__force unsigned long)(a->s6_addr32[2] ^
cpu_to_be32(0x0000ffff))) == 0UL;
}
/*
* Check for a RFC 4843 ORCHID address
* (Overlay Routable Cryptographic Hash Identifiers)
*/
static inline bool ipv6_addr_orchid(const struct in6_addr *a)
{
return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010);
}
static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr)
{
return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000);
}
static inline void ipv6_addr_set_v4mapped(const __be32 addr,
struct in6_addr *v4mapped)
{
ipv6_addr_set(v4mapped,
0, 0,
htonl(0x0000FFFF),
addr);
}
/*
* find the first different bit between two addresses
* length of address must be a multiple of 32bits
*/
static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen)
{
const __be32 *a1 = token1, *a2 = token2;
int i;
addrlen >>= 2;
for (i = 0; i < addrlen; i++) {
__be32 xb = a1[i] ^ a2[i];
if (xb)
return i * 32 + 31 - __fls(ntohl(xb));
}
/*
* we should *never* get to this point since that
* would mean the addrs are equal
*
* However, we do get to it 8) And exacly, when
* addresses are equal 8)
*
* ip route add 1111::/128 via ...
* ip route add 1111::/64 via ...
* and we are here.
*
* Ideally, this function should stop comparison
* at prefix length. It does not, but it is still OK,
* if returned value is greater than prefix length.
* --ANK (980803)
*/
return addrlen << 5;
}
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
static inline int __ipv6_addr_diff64(const void *token1, const void *token2, int addrlen)
{
const __be64 *a1 = token1, *a2 = token2;
int i;
addrlen >>= 3;
for (i = 0; i < addrlen; i++) {
__be64 xb = a1[i] ^ a2[i];
if (xb)
return i * 64 + 63 - __fls(be64_to_cpu(xb));
}
return addrlen << 6;
}
#endif
static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
if (__builtin_constant_p(addrlen) && !(addrlen & 7))
return __ipv6_addr_diff64(token1, token2, addrlen);
#endif
return __ipv6_addr_diff32(token1, token2, addrlen);
}
static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2)
{
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
}
void ipv6_proxy_select_ident(struct sk_buff *skb);
int ip6_dst_hoplimit(struct dst_entry *dst);
static inline int ip6_sk_dst_hoplimit(struct ipv6_pinfo *np, struct flowi6 *fl6,
struct dst_entry *dst)
{
int hlimit;
if (ipv6_addr_is_multicast(&fl6->daddr))
hlimit = np->mcast_hops;
else
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
return hlimit;
}
#if IS_ENABLED(CONFIG_IPV6)
static inline void ip6_set_txhash(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct flow_keys keys;
keys.src = (__force __be32)ipv6_addr_hash(&np->saddr);
keys.dst = (__force __be32)ipv6_addr_hash(&sk->sk_v6_daddr);
keys.port16[0] = inet->inet_sport;
keys.port16[1] = inet->inet_dport;
sk->sk_txhash = flow_hash_from_keys(&keys);
}
static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
__be32 flowlabel, bool autolabel)
{
if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) {
__be32 hash;
hash = skb_get_hash(skb);
/* Since this is being sent on the wire obfuscate hash a bit
* to minimize possbility that any useful information to an
* attacker is leaked. Only lower 20 bits are relevant.
*/
hash ^= hash >> 12;
flowlabel = hash & IPV6_FLOWLABEL_MASK;
}
return flowlabel;
}
#else
static inline void ip6_set_txhash(struct sock *sk) { }
static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
__be32 flowlabel, bool autolabel)
{
return flowlabel;
}
#endif
/*
* Header manipulation
*/
static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass,
__be32 flowlabel)
{
*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel;
}
static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr)
{
return *(__be32 *)hdr & IPV6_FLOWINFO_MASK;
}
static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
{
return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
}
static inline u8 ip6_tclass(__be32 flowinfo)
{
return ntohl(flowinfo & IPV6_TCLASS_MASK) >> IPV6_TCLASS_SHIFT;
}
/*
* Prototypes exported by ipv6
*/
/*
* rcv function (called from netdevice level)
*/
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);
int ip6_rcv_finish(struct sk_buff *skb);
/*
* upper-layer output functions
*/
int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
struct ipv6_txoptions *opt, int tclass);
int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
int ip6_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen, int hlimit,
int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags, int dontfrag);
int ip6_push_pending_frames(struct sock *sk);
void ip6_flush_pending_frames(struct sock *sk);
int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6);
struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
const struct in6_addr *final_dst);
struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
const struct in6_addr *final_dst);
struct dst_entry *ip6_blackhole_route(struct net *net,
struct dst_entry *orig_dst);
/*
* skb processing functions
*/
int ip6_output(struct sock *sk, struct sk_buff *skb);
int ip6_forward(struct sk_buff *skb);
int ip6_input(struct sk_buff *skb);
int ip6_mc_input(struct sk_buff *skb);
int __ip6_local_out(struct sk_buff *skb);
int ip6_local_out(struct sk_buff *skb);
/*
* Extension header (options) processing
*/
void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto, struct in6_addr **daddr_p);
void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto);
int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp,
__be16 *frag_offp);
bool ipv6_ext_hdr(u8 nexthdr);
enum {
IP6_FH_F_FRAG = (1 << 0),
IP6_FH_F_AUTH = (1 << 1),
IP6_FH_F_SKIP_RH = (1 << 2),
};
/* find specified header and get offset to it */
int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,
unsigned short *fragoff, int *fragflg);
int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
const struct ipv6_txoptions *opt,
struct in6_addr *orig);
/*
* socket options (ipv6_sockglue.c)
*/
int ipv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
int ipv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *addr,
int addr_len);
int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
int *addr_len);
int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
int *addr_len);
void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
u32 info, u8 *payload);
void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu);
int inet6_release(struct socket *sock);
int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
int inet6_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len,
int peer);
int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int inet6_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk);
/*
* reassembly.c
*/
extern const struct proto_ops inet6_stream_ops;
extern const struct proto_ops inet6_dgram_ops;
struct group_source_req;
struct group_filter;
int ip6_mc_source(int add, int omode, struct sock *sk,
struct group_source_req *pgsr);
int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
struct group_filter __user *optval, int __user *optlen);
#ifdef CONFIG_PROC_FS
int ac6_proc_init(struct net *net);
void ac6_proc_exit(struct net *net);
int raw6_proc_init(void);
void raw6_proc_exit(void);
int tcp6_proc_init(struct net *net);
void tcp6_proc_exit(struct net *net);
int udp6_proc_init(struct net *net);
void udp6_proc_exit(struct net *net);
int udplite6_proc_init(void);
void udplite6_proc_exit(void);
int ipv6_misc_proc_init(void);
void ipv6_misc_proc_exit(void);
int snmp6_register_dev(struct inet6_dev *idev);
int snmp6_unregister_dev(struct inet6_dev *idev);
#else
static inline int ac6_proc_init(struct net *net) { return 0; }
static inline void ac6_proc_exit(struct net *net) { }
static inline int snmp6_register_dev(struct inet6_dev *idev) { return 0; }
static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
#endif
#ifdef CONFIG_SYSCTL
extern struct ctl_table ipv6_route_table_template[];
struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
struct ctl_table *ipv6_route_sysctl_init(struct net *net);
int ipv6_sysctl_register(void);
void ipv6_sysctl_unregister(void);
#endif
#endif /* _NET_IPV6_H */

171
include/net/ipx.h Normal file
View file

@ -0,0 +1,171 @@
#ifndef _NET_INET_IPX_H_
#define _NET_INET_IPX_H_
/*
* The following information is in its entirety obtained from:
*
* Novell 'IPX Router Specification' Version 1.10
* Part No. 107-000029-001
*
* Which is available from ftp.novell.com
*/
#include <linux/netdevice.h>
#include <net/datalink.h>
#include <linux/ipx.h>
#include <linux/list.h>
#include <linux/slab.h>
struct ipx_address {
__be32 net;
__u8 node[IPX_NODE_LEN];
__be16 sock;
};
#define ipx_broadcast_node "\377\377\377\377\377\377"
#define ipx_this_node "\0\0\0\0\0\0"
#define IPX_MAX_PPROP_HOPS 8
struct ipxhdr {
__be16 ipx_checksum __packed;
#define IPX_NO_CHECKSUM cpu_to_be16(0xFFFF)
__be16 ipx_pktsize __packed;
__u8 ipx_tctrl;
__u8 ipx_type;
#define IPX_TYPE_UNKNOWN 0x00
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
#define IPX_TYPE_SPX 0x05 /* SPX protocol */
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast */
struct ipx_address ipx_dest __packed;
struct ipx_address ipx_source __packed;
};
static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb)
{
return (struct ipxhdr *)skb_transport_header(skb);
}
struct ipx_interface {
/* IPX address */
__be32 if_netnum;
unsigned char if_node[IPX_NODE_LEN];
atomic_t refcnt;
/* physical device info */
struct net_device *if_dev;
struct datalink_proto *if_dlink;
__be16 if_dlink_type;
/* socket support */
unsigned short if_sknum;
struct hlist_head if_sklist;
spinlock_t if_sklist_lock;
/* administrative overhead */
int if_ipx_offset;
unsigned char if_internal;
unsigned char if_primary;
struct list_head node; /* node in ipx_interfaces list */
};
struct ipx_route {
__be32 ir_net;
struct ipx_interface *ir_intrfc;
unsigned char ir_routed;
unsigned char ir_router_node[IPX_NODE_LEN];
struct list_head node; /* node in ipx_routes list */
atomic_t refcnt;
};
struct ipx_cb {
u8 ipx_tctrl;
__be32 ipx_dest_net;
__be32 ipx_source_net;
struct {
__be32 netnum;
int index;
} last_hop;
};
#include <net/sock.h>
struct ipx_sock {
/* struct sock has to be the first member of ipx_sock */
struct sock sk;
struct ipx_address dest_addr;
struct ipx_interface *intrfc;
__be16 port;
#ifdef CONFIG_IPX_INTERN
unsigned char node[IPX_NODE_LEN];
#endif
unsigned short type;
/*
* To handle special ncp connection-handling sockets for mars_nwe,
* the connection number must be stored in the socket.
*/
unsigned short ipx_ncp_conn;
};
static inline struct ipx_sock *ipx_sk(struct sock *sk)
{
return (struct ipx_sock *)sk;
}
#define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0]))
#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
extern struct list_head ipx_routes;
extern rwlock_t ipx_routes_lock;
extern struct list_head ipx_interfaces;
struct ipx_interface *ipx_interfaces_head(void);
extern spinlock_t ipx_interfaces_lock;
extern struct ipx_interface *ipx_primary_net;
int ipx_proc_init(void);
void ipx_proc_exit(void);
const char *ipx_frame_name(__be16);
const char *ipx_device_name(struct ipx_interface *intrfc);
static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
{
atomic_inc(&intrfc->refcnt);
}
void ipxitf_down(struct ipx_interface *intrfc);
struct ipx_interface *ipxitf_find_using_net(__be32 net);
int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node);
__be16 ipx_cksum(struct ipxhdr *packet, int length);
int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
unsigned char *node);
void ipxrtr_del_routes(struct ipx_interface *intrfc);
int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
struct iovec *iov, size_t len, int noblock);
int ipxrtr_route_skb(struct sk_buff *skb);
struct ipx_route *ipxrtr_lookup(__be32 net);
int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
{
if (atomic_dec_and_test(&intrfc->refcnt))
ipxitf_down(intrfc);
}
static __inline__ void ipxrtr_hold(struct ipx_route *rt)
{
atomic_inc(&rt->refcnt);
}
static __inline__ void ipxrtr_put(struct ipx_route *rt)
{
if (atomic_dec_and_test(&rt->refcnt))
kfree(rt);
}
#endif /* _NET_INET_IPX_H_ */

Some files were not shown because too many files have changed in this diff Show more