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);
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_rej_tmr_cb(unsigned long timeout_data);
extern void llc_conn_set_p_flag(struct sock *sk, u8 value);
#endif /* LLC_C_AC_H */
......@@ -126,7 +126,6 @@ struct llc_conn_ev_prim_if {
/* Event LLC_CONN_EV_TYPE_PDU interface */
struct llc_conn_ev_pdu_if {
u8 ev;
u8 reason;
};
union llc_conn_ev_if {
......@@ -137,6 +136,7 @@ union llc_conn_ev_if {
struct llc_conn_state_ev {
u8 type;
u8 reason;
u8 status;
u8 flag;
struct llc_prim_if_block *ind_prim;
......
......@@ -41,18 +41,14 @@ struct llc_stat_ev_prim_if {
u8 type; /* request, indicate, response, confirm */
};
struct llc_stat_ev_pdu_if {
u8 reason;
};
union llc_stat_ev_if {
struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_stat_ev_prim_if prim;
struct llc_stat_ev_pdu_if pdu;
};
struct llc_station_state_ev {
u8 type;
u8 reason;
union llc_stat_ev_if data;
struct list_head node; /* node in station->ev_q.list */
};
......
......@@ -70,7 +70,6 @@ struct llc_addr {
struct llc_prim_reset {
struct sock *sk;
u16 link;
u8 reason; /* used only by indicate */
};
/* Sending data in conection-less mode */
......
......@@ -49,7 +49,6 @@ struct llc_sap_ev_prim_if {
struct llc_sap_ev_pdu_if {
u8 ev;
u8 reason;
};
union llc_sap_ev_if {
......@@ -62,6 +61,7 @@ struct llc_prim_if_block;
struct llc_sap_state_ev {
u8 type;
u8 reason;
u8 ind_cfm_flag;
struct llc_prim_if_block *prim;
union llc_sap_ev_if data;
......
......@@ -7,6 +7,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/string.h>
#include <net/tcp.h>
......
......@@ -50,7 +50,7 @@
#include <linux/netfilter_ipv4/ipt_ULOG.h>
#include <linux/netfilter_ipv4/lockhelp.h>
#include <net/sock.h>
#include <asm/bitops.h>
#include <linux/bitops.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
......
......@@ -211,7 +211,7 @@ check_udp(const struct iphdr *iph,
/* Bad checksum? Don't print, just say it's unclean. */
/* 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_partial((char *)udph, datalen, 0)) != 0)
return 0;
......
......@@ -1493,6 +1493,9 @@ int ip6t_register_table(struct ip6t_table *table)
duprintf("table->private->number = %u\n",
table->private->number);
/* save number of initial entries */
table->private->initial_entries = table->private->number;
table->lock = RW_LOCK_UNLOCKED;
list_prepend(&ip6t_tables, table);
......
......@@ -50,6 +50,18 @@
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
* 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)
udp_port_rover = snum = result;
} else {
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)];
sk2 != NULL;
sk2 = sk2->next) {
struct inet_opt *inet2 = inet_sk(sk2);
struct ipv6_pinfo *np2 = inet6_sk(sk2);
if (inet2->num == snum &&
if (inet_sk(sk2)->num == snum &&
sk2 != sk &&
sk2->bound_dev_if == sk->bound_dev_if &&
(!inet2->rcv_saddr ||
addr_type == IPV6_ADDR_ANY ||
!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))
(!sk2->reuse || !sk->reuse) &&
udv6_rcv_saddr_equal(sk, sk2))
goto fail;
}
}
......
......@@ -129,13 +129,7 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
rc = 1;
}
if (!rc) {
/*
* 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->reason = reason;
ev->flag = LLC_DISC_PRIM + 1;
ev->ind_prim = (void *)1;
}
......@@ -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);
/* here we use the ev->status, humm */
/* prim_data->disc.reason = ev->status; */
ev->reason = ev->status;
ev->flag = LLC_DISC_PRIM + 1;
ev->cfm_prim = (void *)1;
return 0;
......@@ -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;
prim_data->res.sk = sk;
prim_data->res.reason = reason;
prim_data->res.link = llc->link;
prim->data = prim_data;
prim->prim = LLC_RESET_PRIM;
prim->sap = sap;
ev->reason = reason;
ev->flag = 1;
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)
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 rc = 1;
......@@ -834,7 +837,8 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
rc = 0;
llc_conn_send_pdu(sk, nskb);
}
llc->p_flag = p_bit;
llc_conn_set_p_flag(sk, p_bit);
return rc;
}
......@@ -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);
llc->p_flag = 1;
llc_conn_set_p_flag(sk, 1);
mod_timer(&llc->pf_cycle_timer.timer,
jiffies + llc->pf_cycle_timer.expire * HZ);
return 0;
......@@ -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);
del_timer(&llc->pf_cycle_timer.timer);
llc->p_flag = 0;
llc_conn_set_p_flag(sk, 0);
return 0;
}
......@@ -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);
if (f_bit) {
llc_sk(sk)->p_flag = 0;
llc_conn_set_p_flag(sk, 0);
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,
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;
}
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;
}
......
......@@ -39,22 +39,20 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
/* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
static void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
u8 ua, u8 test, u8 xid)
void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
{
struct llc_opt *llc = llc_sk(sk);
struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
/* save primitive for use by the user. */
addr->sllc_family = sk->family;
addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = test;
addr->sllc_xid = xid;
addr->sllc_ua = ua;
addr->sllc_dsap = llc->sap->laddr.lsap;
memcpy(addr->sllc_dmac, llc->laddr.mac, IFHWADDRLEN);
addr->sllc_ssap = llc->daddr.lsap;
memcpy(addr->sllc_smac, llc->daddr.mac, IFHWADDRLEN);
addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = prim == LLC_XID_PRIM;
addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
llc_pdu_decode_sa(skb, addr->sllc_smac);
llc_pdu_decode_da(skb, addr->sllc_dmac);
llc_pdu_decode_dsap(skb, &addr->sllc_dsap);
llc_pdu_decode_ssap(skb, &addr->sllc_ssap);
}
/**
......@@ -96,7 +94,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
*/
switch (flag) {
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)) {
/*
* FIXME: have to sync the LLC state
......@@ -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)
{
int rc = 1;
struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state_trans *trans;
if (llc_sk(sk)->state > NBR_CONN_STATES)
if (llc->state > NBR_CONN_STATES)
goto out;
rc = 0;
trans = llc_qualify_conn_ev(sk, skb);
if (trans) {
rc = llc_exec_conn_trans_actions(sk, trans, skb);
if (!rc && trans->next_state != NO_STATE_CHANGE)
llc_sk(sk)->state = trans->next_state;
if (!rc && trans->next_state != NO_STATE_CHANGE) {
llc->state = trans->next_state;
if (!llc_data_accept_state(llc->state))
sk->state_change(sk);
}
}
out:
return rc;
......
......@@ -216,8 +216,8 @@ static void llc_station_rcv(struct sk_buff *skb)
struct llc_station *station = llc_station_get();
struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
ev->type = LLC_STATION_EV_TYPE_PDU;
ev->reason = 0;
llc_station_state_process(station, skb);
}
......@@ -236,8 +236,8 @@ int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
if (!llc->dev)
llc->dev = skb->dev;
ev->type = LLC_CONN_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
ev->type = LLC_CONN_EV_TYPE_PDU;
ev->reason = 0;
return llc_conn_state_process(sk, 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);
ev->type = LLC_SAP_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
ev->type = LLC_SAP_EV_TYPE_PDU;
ev->reason = 0;
llc_sap_state_process(sap, skb);
}
......
......@@ -304,7 +304,7 @@ void llc_sk_reset(struct sock *sk)
llc->remote_busy_flag = 0;
llc->cause_flag = 0;
llc->retry_count = 0;
llc->p_flag = 0;
llc_conn_set_p_flag(sk, 0);
llc->f_flag = 0;
llc->s_flag = 0;
llc->ack_pf = 0;
......
......@@ -40,6 +40,7 @@
#include <net/llc_pdu.h>
#include <net/llc_conn.h>
#include <net/llc_mac.h>
#include <net/llc_main.h>
#include <linux/llc.h>
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
......@@ -144,52 +145,6 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
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.
* @addr: Local address to match.
......@@ -204,7 +159,7 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr,
struct llc_addr *daddr,
struct net_device *dev)
{
struct sock *sk, *tmp_sk;
struct sock *sk;
for (sk = llc_ui_sockets; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk);
......@@ -226,11 +181,6 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr,
break;
if (!llc_mac_match(llc->addr.sllc_smac, laddr->mac))
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))
break;
}
......@@ -251,20 +201,6 @@ static struct sock *llc_ui_find_sk_by_addr(struct llc_addr *addr,
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
* @sk: Socket to insert.
......@@ -388,7 +324,7 @@ static int llc_ui_autoport(void)
while (tries < LLC_SAP_DYN_TRIES) {
for (i = llc_ui_sap_last_autoport;
i < LLC_SAP_DYN_STOP; i += 2) {
sap = llc_ui_find_sap(i);
sap = llc_sap_find(i);
if (!sap) {
llc_ui_sap_last_autoport = i + 2;
goto out;
......@@ -446,7 +382,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
if (!addr->sllc_ssap)
goto out;
}
sap = llc_ui_find_sap(addr->sllc_ssap);
sap = llc_sap_find(addr->sllc_ssap);
if (!sap) {
sap = llc_sap_open(llc_ui_indicate, llc_ui_confirm,
addr->sllc_ssap);
......@@ -472,7 +408,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
memcpy(laddr.mac, addr->sllc_smac, IFHWADDRLEN);
laddr.lsap = addr->sllc_ssap;
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) {
sock_put(ask);
goto out;
......@@ -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 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 "
"remote_mac_sap tx_queue rx_queue st uid "
"link\n");
/* Output the LLC socket data for the /proc filesystem */
read_lock_bh(&llc_ui_sockets_lock);
for (s = llc_ui_sockets; s; s = s->next) {
struct llc_opt *llc = llc_sk(s);
spin_lock_bh(&station->sap_list.lock);
list_for_each(sap_entry, &station->sap_list.list) {
sap = list_entry(sap_entry, struct llc_sap, node);
len += sprintf(buffer + len, "%2X %2X ", s->type,
!llc_mac_null(llc->addr.sllc_mmac));
if (llc->sap) {
spin_lock_bh(&sap->sk_list.lock);
list_for_each(llc_entry, &sap->sk_list.list) {
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))
llc_ui_format_mac(buffer + len,
llc->dev->dev_addr);
......@@ -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");
}
len += MAC_FORMATTED_SIZE;
len += sprintf(buffer + len, "@%02X ",
llc->sap->laddr.lsap);
} else
len += sprintf(buffer + len, "00:00:00:00:00:00@00 ");
llc_ui_format_mac(buffer + len, llc->addr.sllc_dmac);
len += MAC_FORMATTED_SIZE;
len += sprintf(buffer + len,
"@%02X %8d %8d %2d %-3d ",
llc->addr.sllc_dsap,
atomic_read(&s->wmem_alloc),
atomic_read(&s->rmem_alloc), s->state,
SOCK_INODE(s->socket)->i_uid);
len += sprintf(buffer + len, "%-4d\n", llc->link);
/* Are we still dumping unwanted data then discard the record */
pos = begin + len;
if (pos < offset) {
len = 0; /* Keep dumping into the buffer start */
begin = pos;
len += sprintf(buffer + len, "@%02X ", sap->laddr.lsap);
llc_ui_format_mac(buffer + len, llc->addr.sllc_dmac);
len += MAC_FORMATTED_SIZE;
len += sprintf(buffer + len,
"@%02X %8d %8d %2d %3d ",
llc->addr.sllc_dsap,
atomic_read(&llc->sk->wmem_alloc),
atomic_read(&llc->sk->rmem_alloc),
llc->sk->state,
llc->sk->socket ?
SOCK_INODE(llc->sk->socket)->i_uid :
-1);
len += sprintf(buffer + len, "%4d\n", llc->link);
/* Are we still dumping unwanted data then discard the record */
pos = begin + len;
if (pos < offset) {
len = 0; /* Keep dumping into the buffer start */
begin = pos;
}
if (pos > offset + length) /* We have dumped enough */
break;
}
if (pos > offset + length) /* We have dumped enough */
break;
spin_unlock_bh(&sap->sk_list.lock);
}
read_unlock_bh(&llc_ui_sockets_lock);
spin_unlock_bh(&station->sap_list.lock);
/* The data in question runs from begin to begin + len */
*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