Commit da29f6a8 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents f5076217 e1ec2e00
#ifndef __LINUX_BRIDGE_EBT_ARP_H
#define __LINUX_BRIDGE_EBT_ARP_H
#define EBT_ARP_OPCODE 0x01
#define EBT_ARP_HTYPE 0x02
#define EBT_ARP_PTYPE 0x04
#define EBT_ARP_SRC_IP 0x08
#define EBT_ARP_DST_IP 0x10
#define EBT_ARP_MASK (EBT_ARP_OPCODE | EBT_ARP_HTYPE | EBT_ARP_PTYPE | \
EBT_ARP_SRC_IP | EBT_ARP_DST_IP)
#define EBT_ARP_MATCH "arp"
struct ebt_arp_info
{
uint16_t htype;
uint16_t ptype;
uint16_t opcode;
uint32_t saddr;
uint32_t smsk;
uint32_t daddr;
uint32_t dmsk;
uint8_t bitmask;
uint8_t invflags;
};
#endif
#ifndef __LINUX_BRIDGE_EBT_IP_H
#define __LINUX_BRIDGE_EBT_IP_H
#define EBT_IP_SOURCE 0x01
#define EBT_IP_DEST 0x02
#define EBT_IP_TOS 0x04
#define EBT_IP_PROTO 0x08
#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO)
#define EBT_IP_MATCH "ip"
// the same values are used for the invflags
struct ebt_ip_info
{
uint32_t saddr;
uint32_t daddr;
uint32_t smsk;
uint32_t dmsk;
uint8_t tos;
uint8_t protocol;
uint8_t bitmask;
uint8_t invflags;
};
#endif
#ifndef __LINUX_BRIDGE_EBT_LOG_H
#define __LINUX_BRIDGE_EBT_LOG_H
#define EBT_LOG_IP 0x01 // if the frame is made by ip, log the ip information
#define EBT_LOG_ARP 0x02
#define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP)
#define EBT_LOG_PREFIX_SIZE 30
#define EBT_LOG_WATCHER "log"
struct ebt_log_info
{
uint8_t loglevel;
uint8_t prefix[EBT_LOG_PREFIX_SIZE];
uint32_t bitmask;
};
#endif
#ifndef __LINUX_BRIDGE_EBT_MARK_M_H
#define __LINUX_BRIDGE_EBT_MARK_M_H
#define EBT_MARK_AND 0x01
#define EBT_MARK_OR 0x02
#define EBT_MARK_MASK (EBT_MARK_AND | EBT_MARK_OR)
struct ebt_mark_m_info
{
unsigned long mark, mask;
uint8_t invert;
uint8_t bitmask;
};
#define EBT_MARK_MATCH "mark_m"
#endif
#ifndef __LINUX_BRIDGE_EBT_MARK_T_H
#define __LINUX_BRIDGE_EBT_MARK_T_H
struct ebt_mark_t_info
{
unsigned long mark;
// EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
int target;
};
#define EBT_MARK_TARGET "mark"
#endif
#ifndef __LINUX_BRIDGE_EBT_NAT_H
#define __LINUX_BRIDGE_EBT_NAT_H
struct ebt_nat_info
{
unsigned char mac[ETH_ALEN];
// EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN
int target;
};
#define EBT_SNAT_TARGET "snat"
#define EBT_DNAT_TARGET "dnat"
#endif
#ifndef __LINUX_BRIDGE_EBT_REDIRECT_H
#define __LINUX_BRIDGE_EBT_REDIRECT_H
struct ebt_redirect_info
{
// EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
int target;
};
#define EBT_REDIRECT_TARGET "redirect"
#endif
#ifndef __LINUX_BRIDGE_EBT_VLAN_H
#define __LINUX_BRIDGE_EBT_VLAN_H
#define EBT_VLAN_ID 0x01
#define EBT_VLAN_PRIO 0x02
#define EBT_VLAN_ENCAP 0x04
#define EBT_VLAN_MASK (EBT_VLAN_ID | EBT_VLAN_PRIO | EBT_VLAN_ENCAP)
#define EBT_VLAN_MATCH "vlan"
struct ebt_vlan_info {
uint16_t id; /* VLAN ID {1-4095} */
uint8_t prio; /* VLAN User Priority {0-7} */
uint16_t encap; /* VLAN Encapsulated frame code {0-65535} */
uint8_t bitmask; /* Args bitmask bit 1=1 - ID arg,
bit 2=1 User-Priority arg, bit 3=1 encap*/
uint8_t invflags; /* Inverse bitmask bit 1=1 - inversed ID arg,
bit 2=1 - inversed Pirority arg */
};
#endif
/*
* ebtables
*
* Authors:
* Bart De Schuymer <bart.de.schuymer@pandora.be>
*
* ebtables.c,v 2.0, April, 2002
*
* This code is stongly inspired on the iptables code which is
* Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
*/
#ifndef __LINUX_BRIDGE_EFF_H
#define __LINUX_BRIDGE_EFF_H
#include <linux/if.h>
#include <linux/netfilter_bridge.h>
#include <linux/if_ether.h>
#define EBT_TABLE_MAXNAMELEN 32
#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
#define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
// [gs]etsockopt numbers
#define EBT_BASE_CTL 128
#define EBT_SO_SET_ENTRIES (EBT_BASE_CTL)
#define EBT_SO_SET_COUNTERS (EBT_SO_SET_ENTRIES+1)
#define EBT_SO_SET_MAX (EBT_SO_SET_COUNTERS+1)
#define EBT_SO_GET_INFO (EBT_BASE_CTL)
#define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO+1)
#define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES+1)
#define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO+1)
#define EBT_SO_GET_MAX (EBT_SO_GET_INIT_ENTRIES+1)
// verdicts >0 are "branches"
#define EBT_ACCEPT -1
#define EBT_DROP -2
#define EBT_CONTINUE -3
#define EBT_RETURN -4
#define NUM_STANDARD_TARGETS 4
// return values for match() functions
#define EBT_MATCH 0
#define EBT_NOMATCH 1
struct ebt_counter
{
uint64_t pcnt;
};
struct ebt_entries {
// this field is always set to zero
// See EBT_ENTRY_OR_ENTRIES.
// Must be same size as ebt_entry.bitmask
unsigned int distinguisher;
// the chain name
char name[EBT_CHAIN_MAXNAMELEN];
// counter offset for this chain
unsigned int counter_offset;
// one standard (accept, drop, return) per hook
int policy;
// nr. of entries
unsigned int nentries;
// entry list
char data[0];
};
// used for the bitmask of struct ebt_entry
// This is a hack to make a difference between an ebt_entry struct and an
// ebt_entries struct when traversing the entries from start to end.
// Using this simplifies the code alot, while still being able to use
// ebt_entries.
// Contrary, iptables doesn't use something like ebt_entries and therefore uses
// different techniques for naming the policy and such. So, iptables doesn't
// need a hack like this.
#define EBT_ENTRY_OR_ENTRIES 0x01
// these are the normal masks
#define EBT_NOPROTO 0x02
#define EBT_802_3 0x04
#define EBT_SOURCEMAC 0x08
#define EBT_DESTMAC 0x10
#define EBT_F_MASK (EBT_NOPROTO | EBT_802_3 | EBT_SOURCEMAC | EBT_DESTMAC \
| EBT_ENTRY_OR_ENTRIES)
#define EBT_IPROTO 0x01
#define EBT_IIN 0x02
#define EBT_IOUT 0x04
#define EBT_ISOURCE 0x8
#define EBT_IDEST 0x10
#define EBT_ILOGICALIN 0x20
#define EBT_ILOGICALOUT 0x40
#define EBT_INV_MASK (EBT_IPROTO | EBT_IIN | EBT_IOUT | EBT_ILOGICALIN \
| EBT_ILOGICALOUT | EBT_ISOURCE | EBT_IDEST)
struct ebt_entry_match
{
union {
char name[EBT_FUNCTION_MAXNAMELEN];
struct ebt_match *match;
} u;
// size of data
unsigned int match_size;
unsigned char data[0];
};
struct ebt_entry_watcher
{
union {
char name[EBT_FUNCTION_MAXNAMELEN];
struct ebt_watcher *watcher;
} u;
// size of data
unsigned int watcher_size;
unsigned char data[0];
};
struct ebt_entry_target
{
union {
char name[EBT_FUNCTION_MAXNAMELEN];
struct ebt_target *target;
} u;
// size of data
unsigned int target_size;
unsigned char data[0];
};
#define EBT_STANDARD_TARGET "standard"
struct ebt_standard_target
{
struct ebt_entry_target target;
int verdict;
};
// one entry
struct ebt_entry {
// this needs to be the first field
unsigned int bitmask;
unsigned int invflags;
uint16_t ethproto;
// the physical in-dev
char in[IFNAMSIZ];
// the logical in-dev
char logical_in[IFNAMSIZ];
// the physical out-dev
char out[IFNAMSIZ];
// the logical out-dev
char logical_out[IFNAMSIZ];
unsigned char sourcemac[ETH_ALEN];
unsigned char sourcemsk[ETH_ALEN];
unsigned char destmac[ETH_ALEN];
unsigned char destmsk[ETH_ALEN];
// sizeof ebt_entry + matches
unsigned int watchers_offset;
// sizeof ebt_entry + matches + watchers
unsigned int target_offset;
// sizeof ebt_entry + matches + watchers + target
unsigned int next_offset;
unsigned char elems[0];
};
struct ebt_replace
{
char name[EBT_TABLE_MAXNAMELEN];
unsigned int valid_hooks;
// nr of rules in the table
unsigned int nentries;
// total size of the entries
unsigned int entries_size;
// start of the chains
struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
// nr of counters userspace expects back
unsigned int num_counters;
// where the kernel will put the old counters
struct ebt_counter *counters;
char *entries;
};
#ifdef __KERNEL__
struct ebt_match
{
struct list_head list;
const char name[EBT_FUNCTION_MAXNAMELEN];
// 0 == it matches
int (*match)(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const void *matchdata,
unsigned int datalen);
// 0 == let it in
int (*check)(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *matchdata, unsigned int datalen);
void (*destroy)(void *matchdata, unsigned int datalen);
struct module *me;
};
struct ebt_watcher
{
struct list_head list;
const char name[EBT_FUNCTION_MAXNAMELEN];
void (*watcher)(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const void *watcherdata,
unsigned int datalen);
// 0 == let it in
int (*check)(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *watcherdata, unsigned int datalen);
void (*destroy)(void *watcherdata, unsigned int datalen);
struct module *me;
};
struct ebt_target
{
struct list_head list;
const char name[EBT_FUNCTION_MAXNAMELEN];
// returns one of the standard verdicts
int (*target)(struct sk_buff **pskb, unsigned int hooknr,
const struct net_device *in, const struct net_device *out,
const void *targetdata, unsigned int datalen);
// 0 == let it in
int (*check)(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *targetdata, unsigned int datalen);
void (*destroy)(void *targetdata, unsigned int datalen);
struct module *me;
};
// used for jumping from and into user defined chains (udc)
struct ebt_chainstack
{
struct ebt_entries *chaininfo; // pointer to chain data
struct ebt_entry *e; // pointer to entry data
unsigned int n; // n'th entry
};
struct ebt_table_info
{
// total size of the entries
unsigned int entries_size;
unsigned int nentries;
// pointers to the start of the chains
struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
// room to maintain the stack used for jumping from and into udc
struct ebt_chainstack **chainstack;
char *entries;
struct ebt_counter counters[0] ____cacheline_aligned;
};
struct ebt_table
{
struct list_head list;
char name[EBT_TABLE_MAXNAMELEN];
struct ebt_replace *table;
unsigned int valid_hooks;
rwlock_t lock;
// e.g. could be the table explicitly only allows certain
// matches, targets, ... 0 == let it in
int (*check)(const struct ebt_table_info *info,
unsigned int valid_hooks);
// the data used by the kernel
struct ebt_table_info *private;
};
extern int ebt_register_table(struct ebt_table *table);
extern void ebt_unregister_table(struct ebt_table *table);
extern int ebt_register_match(struct ebt_match *match);
extern void ebt_unregister_match(struct ebt_match *match);
extern int ebt_register_watcher(struct ebt_watcher *watcher);
extern void ebt_unregister_watcher(struct ebt_watcher *watcher);
extern int ebt_register_target(struct ebt_target *target);
extern void ebt_unregister_target(struct ebt_target *target);
extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out,
struct ebt_table *table);
// Used in the kernel match() functions
#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
// True if the hook mask denotes that the rule is in a base chain,
// used in the check() functions
#define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS))
// Clear the bit in the hook mask that tells if the rule is on a base chain
#define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS))
// True if the target is not a standard target
#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
#endif /* __KERNEL__ */
// blatently stolen from ip_tables.h
// fn returns 0 to continue iteration
#define EBT_MATCH_ITERATE(e, fn, args...) \
({ \
unsigned int __i; \
int __ret = 0; \
struct ebt_entry_match *__match; \
\
for (__i = sizeof(struct ebt_entry); \
__i < (e)->watchers_offset; \
__i += __match->match_size + \
sizeof(struct ebt_entry_match)) { \
__match = (void *)(e) + __i; \
\
__ret = fn(__match , ## args); \
if (__ret != 0) \
break; \
} \
if (__ret == 0) { \
if (__i != (e)->watchers_offset) \
__ret = -EINVAL; \
} \
__ret; \
})
#define EBT_WATCHER_ITERATE(e, fn, args...) \
({ \
unsigned int __i; \
int __ret = 0; \
struct ebt_entry_watcher *__watcher; \
\
for (__i = e->watchers_offset; \
__i < (e)->target_offset; \
__i += __watcher->watcher_size + \
sizeof(struct ebt_entry_watcher)) { \
__watcher = (void *)(e) + __i; \
\
__ret = fn(__watcher , ## args); \
if (__ret != 0) \
break; \
} \
if (__ret == 0) { \
if (__i != (e)->target_offset) \
__ret = -EINVAL; \
} \
__ret; \
})
#define EBT_ENTRY_ITERATE(entries, size, fn, args...) \
({ \
unsigned int __i; \
int __ret = 0; \
struct ebt_entry *__entry; \
\
for (__i = 0; __i < (size);) { \
__entry = (void *)(entries) + __i; \
__ret = fn(__entry , ## args); \
if (__ret != 0) \
break; \
if (__entry->bitmask != 0) \
__i += __entry->next_offset; \
else \
__i += sizeof(struct ebt_entries); \
} \
if (__ret == 0) { \
if (__i != (size)) \
__ret = -EINVAL; \
} \
__ret; \
})
#endif
...@@ -216,4 +216,6 @@ extern void llc_conn_busy_tmr_cb(unsigned long timeout_data); ...@@ -216,4 +216,6 @@ extern void llc_conn_busy_tmr_cb(unsigned long timeout_data);
extern void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data); extern void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
extern void llc_conn_ack_tmr_cb(unsigned long timeout_data); extern void llc_conn_ack_tmr_cb(unsigned long timeout_data);
extern void llc_conn_rej_tmr_cb(unsigned long timeout_data); extern void llc_conn_rej_tmr_cb(unsigned long timeout_data);
extern void llc_conn_set_p_flag(struct sock *sk, u8 value);
#endif /* LLC_C_AC_H */ #endif /* LLC_C_AC_H */
...@@ -126,7 +126,6 @@ struct llc_conn_ev_prim_if { ...@@ -126,7 +126,6 @@ struct llc_conn_ev_prim_if {
/* Event LLC_CONN_EV_TYPE_PDU interface */ /* Event LLC_CONN_EV_TYPE_PDU interface */
struct llc_conn_ev_pdu_if { struct llc_conn_ev_pdu_if {
u8 ev; u8 ev;
u8 reason;
}; };
union llc_conn_ev_if { union llc_conn_ev_if {
...@@ -137,6 +136,7 @@ union llc_conn_ev_if { ...@@ -137,6 +136,7 @@ union llc_conn_ev_if {
struct llc_conn_state_ev { struct llc_conn_state_ev {
u8 type; u8 type;
u8 reason;
u8 status; u8 status;
u8 flag; u8 flag;
struct llc_prim_if_block *ind_prim; struct llc_prim_if_block *ind_prim;
......
...@@ -41,18 +41,14 @@ struct llc_stat_ev_prim_if { ...@@ -41,18 +41,14 @@ struct llc_stat_ev_prim_if {
u8 type; /* request, indicate, response, confirm */ u8 type; /* request, indicate, response, confirm */
}; };
struct llc_stat_ev_pdu_if {
u8 reason;
};
union llc_stat_ev_if { union llc_stat_ev_if {
struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */ struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_stat_ev_prim_if prim; struct llc_stat_ev_prim_if prim;
struct llc_stat_ev_pdu_if pdu;
}; };
struct llc_station_state_ev { struct llc_station_state_ev {
u8 type; u8 type;
u8 reason;
union llc_stat_ev_if data; union llc_stat_ev_if data;
struct list_head node; /* node in station->ev_q.list */ struct list_head node; /* node in station->ev_q.list */
}; };
......
...@@ -70,7 +70,6 @@ struct llc_addr { ...@@ -70,7 +70,6 @@ struct llc_addr {
struct llc_prim_reset { struct llc_prim_reset {
struct sock *sk; struct sock *sk;
u16 link; u16 link;
u8 reason; /* used only by indicate */
}; };
/* Sending data in conection-less mode */ /* Sending data in conection-less mode */
......
...@@ -49,7 +49,6 @@ struct llc_sap_ev_prim_if { ...@@ -49,7 +49,6 @@ struct llc_sap_ev_prim_if {
struct llc_sap_ev_pdu_if { struct llc_sap_ev_pdu_if {
u8 ev; u8 ev;
u8 reason;
}; };
union llc_sap_ev_if { union llc_sap_ev_if {
...@@ -62,6 +61,7 @@ struct llc_prim_if_block; ...@@ -62,6 +61,7 @@ struct llc_prim_if_block;
struct llc_sap_state_ev { struct llc_sap_state_ev {
u8 type; u8 type;
u8 reason;
u8 ind_cfm_flag; u8 ind_cfm_flag;
struct llc_prim_if_block *prim; struct llc_prim_if_block *prim;
union llc_sap_ev_if data; union llc_sap_ev_if data;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/string.h>
#include <net/tcp.h> #include <net/tcp.h>
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
#include <linux/netfilter_ipv4/ipt_ULOG.h> #include <linux/netfilter_ipv4/ipt_ULOG.h>
#include <linux/netfilter_ipv4/lockhelp.h> #include <linux/netfilter_ipv4/lockhelp.h>
#include <net/sock.h> #include <net/sock.h>
#include <asm/bitops.h> #include <linux/bitops.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
......
...@@ -211,7 +211,7 @@ check_udp(const struct iphdr *iph, ...@@ -211,7 +211,7 @@ check_udp(const struct iphdr *iph,
/* Bad checksum? Don't print, just say it's unclean. */ /* Bad checksum? Don't print, just say it's unclean. */
/* FIXME: SRC ROUTE packets won't match checksum --RR */ /* FIXME: SRC ROUTE packets won't match checksum --RR */
if (!more_frags && !embedded if (!more_frags && !embedded && udph->check
&& csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
csum_partial((char *)udph, datalen, 0)) != 0) csum_partial((char *)udph, datalen, 0)) != 0)
return 0; return 0;
......
...@@ -1493,6 +1493,9 @@ int ip6t_register_table(struct ip6t_table *table) ...@@ -1493,6 +1493,9 @@ int ip6t_register_table(struct ip6t_table *table)
duprintf("table->private->number = %u\n", duprintf("table->private->number = %u\n",
table->private->number); table->private->number);
/* save number of initial entries */
table->private->initial_entries = table->private->number;
table->lock = RW_LOCK_UNLOCKED; table->lock = RW_LOCK_UNLOCKED;
list_prepend(&ip6t_tables, table); list_prepend(&ip6t_tables, table);
......
...@@ -50,6 +50,18 @@ ...@@ -50,6 +50,18 @@
struct udp_mib udp_stats_in6[NR_CPUS*2]; struct udp_mib udp_stats_in6[NR_CPUS*2];
static __inline__ int udv6_rcv_saddr_equal(struct sock *sk, struct sock *sk2)
{
struct ipv6_pinfo *np = inet6_sk(sk);
int addr_type = ipv6_addr_type(&np->rcv_saddr);
return !inet_sk(sk2)->rcv_saddr || addr_type == IPV6_ADDR_ANY ||
(sk2->family == AF_INET6 &&
!ipv6_addr_cmp(&np->rcv_saddr, &inet6_sk(sk2)->rcv_saddr)) ||
(addr_type == IPV6_ADDR_MAPPED && sk2->family == AF_INET &&
inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr);
}
/* Grrr, addr_type already calculated by caller, but I don't want /* Grrr, addr_type already calculated by caller, but I don't want
* to add some silly "cookie" argument to this method just for that. * to add some silly "cookie" argument to this method just for that.
*/ */
...@@ -98,25 +110,15 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -98,25 +110,15 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum)
udp_port_rover = snum = result; udp_port_rover = snum = result;
} else { } else {
struct sock *sk2; struct sock *sk2;
struct ipv6_pinfo *np = inet6_sk(sk);
int addr_type = ipv6_addr_type(&np->rcv_saddr);
for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
sk2 != NULL; sk2 != NULL;
sk2 = sk2->next) { sk2 = sk2->next) {
struct inet_opt *inet2 = inet_sk(sk2); if (inet_sk(sk2)->num == snum &&
struct ipv6_pinfo *np2 = inet6_sk(sk2);
if (inet2->num == snum &&
sk2 != sk && sk2 != sk &&
sk2->bound_dev_if == sk->bound_dev_if && sk2->bound_dev_if == sk->bound_dev_if &&
(!inet2->rcv_saddr || (!sk2->reuse || !sk->reuse) &&
addr_type == IPV6_ADDR_ANY || udv6_rcv_saddr_equal(sk, sk2))
!ipv6_addr_cmp(&np->rcv_saddr, &np2->rcv_saddr) ||
(addr_type == IPV6_ADDR_MAPPED &&
sk2->family == AF_INET &&
inet_sk(sk)->rcv_saddr == inet2->rcv_saddr)) &&
(!sk2->reuse || !sk->reuse))
goto fail; goto fail;
} }
} }
......
...@@ -129,13 +129,7 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) ...@@ -129,13 +129,7 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
rc = 1; rc = 1;
} }
if (!rc) { if (!rc) {
/* ev->reason = reason;
* FIXME: ev needs reason field,
* perhaps the ev->status is enough,
* have to check,
* better way to signal its a disc
*/
/* prim_data->disc.reason = reason; */
ev->flag = LLC_DISC_PRIM + 1; ev->flag = LLC_DISC_PRIM + 1;
ev->ind_prim = (void *)1; ev->ind_prim = (void *)1;
} }
...@@ -146,8 +140,7 @@ int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb) ...@@ -146,8 +140,7 @@ int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
/* here we use the ev->status, humm */ ev->reason = ev->status;
/* prim_data->disc.reason = ev->status; */
ev->flag = LLC_DISC_PRIM + 1; ev->flag = LLC_DISC_PRIM + 1;
ev->cfm_prim = (void *)1; ev->cfm_prim = (void *)1;
return 0; return 0;
...@@ -196,11 +189,11 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) ...@@ -196,11 +189,11 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
union llc_u_prim_data *prim_data = prim->data; union llc_u_prim_data *prim_data = prim->data;
prim_data->res.sk = sk; prim_data->res.sk = sk;
prim_data->res.reason = reason;
prim_data->res.link = llc->link; prim_data->res.link = llc->link;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_RESET_PRIM; prim->prim = LLC_RESET_PRIM;
prim->sap = sap; prim->sap = sap;
ev->reason = reason;
ev->flag = 1; ev->flag = 1;
ev->ind_prim = prim; ev->ind_prim = prim;
} }
...@@ -813,6 +806,16 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -813,6 +806,16 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
return rc; return rc;
} }
void llc_conn_set_p_flag(struct sock *sk, u8 value)
{
int state_changed = llc_sk(sk)->p_flag && !value;
llc_sk(sk)->p_flag = value;
if (state_changed)
sk->state_change(sk);
}
int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
{ {
int rc = 1; int rc = 1;
...@@ -834,7 +837,8 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -834,7 +837,8 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
rc = 0; rc = 0;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
llc->p_flag = p_bit; llc_conn_set_p_flag(sk, p_bit);
return rc; return rc;
} }
...@@ -897,7 +901,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb) ...@@ -897,7 +901,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
llc->p_flag = 1; llc_conn_set_p_flag(sk, 1);
mod_timer(&llc->pf_cycle_timer.timer, mod_timer(&llc->pf_cycle_timer.timer,
jiffies + llc->pf_cycle_timer.expire * HZ); jiffies + llc->pf_cycle_timer.expire * HZ);
return 0; return 0;
...@@ -1205,7 +1209,7 @@ int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb) ...@@ -1205,7 +1209,7 @@ int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb)
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
del_timer(&llc->pf_cycle_timer.timer); del_timer(&llc->pf_cycle_timer.timer);
llc->p_flag = 0; llc_conn_set_p_flag(sk, 0);
return 0; return 0;
} }
...@@ -1259,7 +1263,7 @@ int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb) ...@@ -1259,7 +1263,7 @@ int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb)
llc_pdu_decode_pf_bit(skb, &f_bit); llc_pdu_decode_pf_bit(skb, &f_bit);
if (f_bit) { if (f_bit) {
llc_sk(sk)->p_flag = 0; llc_conn_set_p_flag(sk, 0);
llc_conn_ac_stop_p_timer(sk, skb); llc_conn_ac_stop_p_timer(sk, skb);
} }
} }
...@@ -1294,13 +1298,13 @@ int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk, ...@@ -1294,13 +1298,13 @@ int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk,
int llc_conn_ac_set_p_flag_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_set_p_flag_0(struct sock *sk, struct sk_buff *skb)
{ {
llc_sk(sk)->p_flag = 0; llc_conn_set_p_flag(sk, 0);
return 0; return 0;
} }
int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb)
{ {
llc_sk(sk)->p_flag = 1; llc_conn_set_p_flag(sk, 1);
return 0; return 0;
} }
......
...@@ -39,22 +39,20 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, ...@@ -39,22 +39,20 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
/* Offset table on connection states transition diagram */ /* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
static void llc_save_primitive(struct sock *sk, struct sk_buff* skb, void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
u8 ua, u8 test, u8 xid)
{ {
struct llc_opt *llc = llc_sk(sk);
struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
/* save primitive for use by the user. */ /* save primitive for use by the user. */
addr->sllc_family = sk->family; addr->sllc_family = sk->family;
addr->sllc_arphrd = skb->dev->type; addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = test; addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = xid; addr->sllc_xid = prim == LLC_XID_PRIM;
addr->sllc_ua = ua; addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
addr->sllc_dsap = llc->sap->laddr.lsap; llc_pdu_decode_sa(skb, addr->sllc_smac);
memcpy(addr->sllc_dmac, llc->laddr.mac, IFHWADDRLEN); llc_pdu_decode_da(skb, addr->sllc_dmac);
addr->sllc_ssap = llc->daddr.lsap; llc_pdu_decode_dsap(skb, &addr->sllc_dsap);
memcpy(addr->sllc_smac, llc->daddr.mac, IFHWADDRLEN); llc_pdu_decode_ssap(skb, &addr->sllc_ssap);
} }
/** /**
...@@ -96,7 +94,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -96,7 +94,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
*/ */
switch (flag) { switch (flag) {
case LLC_DATA_PRIM + 1: case LLC_DATA_PRIM + 1:
llc_save_primitive(sk, skb, 0, 0, 0); llc_save_primitive(sk, skb, LLC_DATA_PRIM);
if (sock_queue_rcv_skb(sk, skb)) { if (sock_queue_rcv_skb(sk, skb)) {
/* /*
* FIXME: have to sync the LLC state * FIXME: have to sync the LLC state
...@@ -378,16 +376,20 @@ void llc_conn_free_ev(struct sk_buff *skb) ...@@ -378,16 +376,20 @@ void llc_conn_free_ev(struct sk_buff *skb)
static int llc_conn_service(struct sock *sk, struct sk_buff *skb) static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
{ {
int rc = 1; int rc = 1;
struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state_trans *trans; struct llc_conn_state_trans *trans;
if (llc_sk(sk)->state > NBR_CONN_STATES) if (llc->state > NBR_CONN_STATES)
goto out; goto out;
rc = 0; rc = 0;
trans = llc_qualify_conn_ev(sk, skb); trans = llc_qualify_conn_ev(sk, skb);
if (trans) { if (trans) {
rc = llc_exec_conn_trans_actions(sk, trans, skb); rc = llc_exec_conn_trans_actions(sk, trans, skb);
if (!rc && trans->next_state != NO_STATE_CHANGE) if (!rc && trans->next_state != NO_STATE_CHANGE) {
llc_sk(sk)->state = trans->next_state; llc->state = trans->next_state;
if (!llc_data_accept_state(llc->state))
sk->state_change(sk);
}
} }
out: out:
return rc; return rc;
......
...@@ -216,8 +216,8 @@ static void llc_station_rcv(struct sk_buff *skb) ...@@ -216,8 +216,8 @@ static void llc_station_rcv(struct sk_buff *skb)
struct llc_station *station = llc_station_get(); struct llc_station *station = llc_station_get();
struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_PDU; ev->type = LLC_STATION_EV_TYPE_PDU;
ev->data.pdu.reason = 0; ev->reason = 0;
llc_station_state_process(station, skb); llc_station_state_process(station, skb);
} }
...@@ -236,8 +236,8 @@ int llc_conn_rcv(struct sock* sk, struct sk_buff *skb) ...@@ -236,8 +236,8 @@ int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
if (!llc->dev) if (!llc->dev)
llc->dev = skb->dev; llc->dev = skb->dev;
ev->type = LLC_CONN_EV_TYPE_PDU; ev->type = LLC_CONN_EV_TYPE_PDU;
ev->data.pdu.reason = 0; ev->reason = 0;
return llc_conn_state_process(sk, skb); return llc_conn_state_process(sk, skb);
} }
...@@ -252,8 +252,8 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb) ...@@ -252,8 +252,8 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->type = LLC_SAP_EV_TYPE_PDU; ev->type = LLC_SAP_EV_TYPE_PDU;
ev->data.pdu.reason = 0; ev->reason = 0;
llc_sap_state_process(sap, skb); llc_sap_state_process(sap, skb);
} }
......
...@@ -304,7 +304,7 @@ void llc_sk_reset(struct sock *sk) ...@@ -304,7 +304,7 @@ void llc_sk_reset(struct sock *sk)
llc->remote_busy_flag = 0; llc->remote_busy_flag = 0;
llc->cause_flag = 0; llc->cause_flag = 0;
llc->retry_count = 0; llc->retry_count = 0;
llc->p_flag = 0; llc_conn_set_p_flag(sk, 0);
llc->f_flag = 0; llc->f_flag = 0;
llc->s_flag = 0; llc->s_flag = 0;
llc->ack_pf = 0; llc->ack_pf = 0;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
#include <net/llc_conn.h> #include <net/llc_conn.h>
#include <net/llc_mac.h> #include <net/llc_mac.h>
#include <net/llc_main.h>
#include <linux/llc.h> #include <linux/llc.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
...@@ -144,52 +145,6 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) ...@@ -144,52 +145,6 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
return rc; return rc;
} }
/**
* llc_ui_find_sap - returns sap struct that matches sap number specified
* @sap: Sap number to search for.
*
* Search the local socket list and return the first instance of the sap
* structure which matches the sap number the user specified.
* Returns llc_sap upon match, %NULL otherwise.
*/
static __inline__ struct llc_sap *llc_ui_find_sap(u8 sap)
{
struct sock *sk;
struct llc_sap *s = NULL;
read_lock_bh(&llc_ui_sockets_lock);
for (sk = llc_ui_sockets; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk);
if (!llc->sap)
continue;
if (llc->sap->laddr.lsap == sap) {
s = llc->sap;
break;
}
}
read_unlock_bh(&llc_ui_sockets_lock);
return s;
}
static struct sock *__llc_ui_find_sk_by_exact(struct llc_addr *laddr,
struct llc_addr *daddr)
{
struct sock *sk;
for (sk = llc_ui_sockets; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk);
if (llc->addr.sllc_ssap == laddr->lsap &&
llc->addr.sllc_dsap == daddr->lsap &&
llc_mac_null(llc->addr.sllc_mmac) &&
llc_mac_match(llc->addr.sllc_smac, laddr->mac) &&
llc_mac_match(llc->addr.sllc_dmac, daddr->mac))
break;
}
return sk;
}
/** /**
* __llc_ui_find_sk_by_addr - return socket matching local mac + sap. * __llc_ui_find_sk_by_addr - return socket matching local mac + sap.
* @addr: Local address to match. * @addr: Local address to match.
...@@ -204,7 +159,7 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr, ...@@ -204,7 +159,7 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr,
struct llc_addr *daddr, struct llc_addr *daddr,
struct net_device *dev) struct net_device *dev)
{ {
struct sock *sk, *tmp_sk; struct sock *sk;
for (sk = llc_ui_sockets; sk; sk = sk->next) { for (sk = llc_ui_sockets; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
...@@ -226,11 +181,6 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr, ...@@ -226,11 +181,6 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr,
break; break;
if (!llc_mac_match(llc->addr.sllc_smac, laddr->mac)) if (!llc_mac_match(llc->addr.sllc_smac, laddr->mac))
continue; continue;
tmp_sk = __llc_ui_find_sk_by_exact(laddr, daddr);
if (tmp_sk) {
sk = tmp_sk;
break;
}
if (llc_mac_null(llc->addr.sllc_dmac)) if (llc_mac_null(llc->addr.sllc_dmac))
break; break;
} }
...@@ -251,20 +201,6 @@ static struct sock *llc_ui_find_sk_by_addr(struct llc_addr *addr, ...@@ -251,20 +201,6 @@ static struct sock *llc_ui_find_sk_by_addr(struct llc_addr *addr,
return sk; return sk;
} }
static struct sock *llc_ui_bh_find_sk_by_addr(struct llc_addr *addr,
struct llc_addr *daddr,
struct net_device *dev)
{
struct sock *sk;
read_lock_bh(&llc_ui_sockets_lock);
sk = __llc_ui_find_sk_by_addr(addr, daddr, dev);
if (sk)
sock_hold(sk);
read_unlock_bh(&llc_ui_sockets_lock);
return sk;
}
/** /**
* llc_ui_insert_socket - insert socket into list * llc_ui_insert_socket - insert socket into list
* @sk: Socket to insert. * @sk: Socket to insert.
...@@ -388,7 +324,7 @@ static int llc_ui_autoport(void) ...@@ -388,7 +324,7 @@ static int llc_ui_autoport(void)
while (tries < LLC_SAP_DYN_TRIES) { while (tries < LLC_SAP_DYN_TRIES) {
for (i = llc_ui_sap_last_autoport; for (i = llc_ui_sap_last_autoport;
i < LLC_SAP_DYN_STOP; i += 2) { i < LLC_SAP_DYN_STOP; i += 2) {
sap = llc_ui_find_sap(i); sap = llc_sap_find(i);
if (!sap) { if (!sap) {
llc_ui_sap_last_autoport = i + 2; llc_ui_sap_last_autoport = i + 2;
goto out; goto out;
...@@ -446,7 +382,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) ...@@ -446,7 +382,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
if (!addr->sllc_ssap) if (!addr->sllc_ssap)
goto out; goto out;
} }
sap = llc_ui_find_sap(addr->sllc_ssap); sap = llc_sap_find(addr->sllc_ssap);
if (!sap) { if (!sap) {
sap = llc_sap_open(llc_ui_indicate, llc_ui_confirm, sap = llc_sap_open(llc_ui_indicate, llc_ui_confirm,
addr->sllc_ssap); addr->sllc_ssap);
...@@ -472,7 +408,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) ...@@ -472,7 +408,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
memcpy(laddr.mac, addr->sllc_smac, IFHWADDRLEN); memcpy(laddr.mac, addr->sllc_smac, IFHWADDRLEN);
laddr.lsap = addr->sllc_ssap; laddr.lsap = addr->sllc_ssap;
rc = -EADDRINUSE; /* mac + sap clash. */ rc = -EADDRINUSE; /* mac + sap clash. */
ask = llc_ui_bh_find_sk_by_addr(&laddr, &daddr, dev); ask = llc_lookup_established(sap, &daddr, &laddr);
if (ask) { if (ask) {
sock_put(ask); sock_put(ask);
goto out; goto out;
...@@ -1384,18 +1320,26 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1384,18 +1320,26 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
{ {
off_t pos = 0; off_t pos = 0;
off_t begin = 0; off_t begin = 0;
struct sock *s; struct llc_opt *llc;
struct llc_sap *sap;
struct list_head *sap_entry, *llc_entry;
struct llc_station *station = llc_station_get();
int len = sprintf(buffer, "SKt Mc local_mac_sap " int len = sprintf(buffer, "SKt Mc local_mac_sap "
"remote_mac_sap tx_queue rx_queue st uid " "remote_mac_sap tx_queue rx_queue st uid "
"link\n"); "link\n");
/* Output the LLC socket data for the /proc filesystem */ /* Output the LLC socket data for the /proc filesystem */
read_lock_bh(&llc_ui_sockets_lock); spin_lock_bh(&station->sap_list.lock);
for (s = llc_ui_sockets; s; s = s->next) { list_for_each(sap_entry, &station->sap_list.list) {
struct llc_opt *llc = llc_sk(s); sap = list_entry(sap_entry, struct llc_sap, node);
len += sprintf(buffer + len, "%2X %2X ", s->type, spin_lock_bh(&sap->sk_list.lock);
!llc_mac_null(llc->addr.sllc_mmac)); list_for_each(llc_entry, &sap->sk_list.list) {
if (llc->sap) { llc = list_entry(llc_entry, struct llc_opt, node);
len += sprintf(buffer + len, "%2X %2X ",
llc->sk->type,
!llc_mac_null(llc->addr.sllc_mmac));
if (llc->dev && llc_mac_null(llc->addr.sllc_mmac)) if (llc->dev && llc_mac_null(llc->addr.sllc_mmac))
llc_ui_format_mac(buffer + len, llc_ui_format_mac(buffer + len,
llc->dev->dev_addr); llc->dev->dev_addr);
...@@ -1408,30 +1352,32 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1408,30 +1352,32 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
"00:00:00:00:00:00"); "00:00:00:00:00:00");
} }
len += MAC_FORMATTED_SIZE; len += MAC_FORMATTED_SIZE;
len += sprintf(buffer + len, "@%02X ", len += sprintf(buffer + len, "@%02X ", sap->laddr.lsap);
llc->sap->laddr.lsap); llc_ui_format_mac(buffer + len, llc->addr.sllc_dmac);
} else len += MAC_FORMATTED_SIZE;
len += sprintf(buffer + len, "00:00:00:00:00:00@00 "); len += sprintf(buffer + len,
llc_ui_format_mac(buffer + len, llc->addr.sllc_dmac); "@%02X %8d %8d %2d %3d ",
len += MAC_FORMATTED_SIZE; llc->addr.sllc_dsap,
len += sprintf(buffer + len, atomic_read(&llc->sk->wmem_alloc),
"@%02X %8d %8d %2d %-3d ", atomic_read(&llc->sk->rmem_alloc),
llc->addr.sllc_dsap, llc->sk->state,
atomic_read(&s->wmem_alloc), llc->sk->socket ?
atomic_read(&s->rmem_alloc), s->state, SOCK_INODE(llc->sk->socket)->i_uid :
SOCK_INODE(s->socket)->i_uid); -1);
len += sprintf(buffer + len, "%-4d\n", llc->link); len += sprintf(buffer + len, "%4d\n", llc->link);
/* Are we still dumping unwanted data then discard the record */ /* Are we still dumping unwanted data then discard the record */
pos = begin + len; pos = begin + len;
if (pos < offset) { if (pos < offset) {
len = 0; /* Keep dumping into the buffer start */ len = 0; /* Keep dumping into the buffer start */
begin = pos; begin = pos;
}
if (pos > offset + length) /* We have dumped enough */
break;
} }
if (pos > offset + length) /* We have dumped enough */ spin_unlock_bh(&sap->sk_list.lock);
break;
} }
read_unlock_bh(&llc_ui_sockets_lock); spin_unlock_bh(&station->sap_list.lock);
/* The data in question runs from begin to begin + len */ /* The data in question runs from begin to begin + len */
*start = buffer + offset - begin; /* Start of wanted data */ *start = buffer + offset - begin; /* Start of wanted data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment