Ejemplo n.º 1
0
int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 nr = LLC_I_GET_NR(pdu);

	llc_conn_resend_i_pdu_as_rsp(sk, nr, 1);
	return 0;
}
int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	return llc_conn_space(sk, skb) &&
	       LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
Ejemplo n.º 3
0
int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 nr = LLC_I_GET_NR(pdu);

	llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
	return 0;
}
int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
	       LLC_S_PF_IS_1(pdu) &&
	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
}
int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
	       LLC_S_PF_IS_0(pdu) &&
	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
}
Ejemplo n.º 6
0
int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
	       LLC_S_PF_IS_0(pdu) &&
	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
}
Ejemplo n.º 7
0
int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
	       LLC_S_PF_IS_1(pdu) &&
	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
}
int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	return llc_conn_space(sk, skb) &&
	       LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
	       LLC_I_PF_IS_1(pdu) &&
	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
Ejemplo n.º 9
0
int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 nr = PDU_SUPV_GET_Nr(pdu);

	if (llc_circular_between(llc_sk(sk)->vS, nr, llc_sk(sk)->X))
		llc_conn_ac_set_vs_nr(sk, skb);
	return 0;
}
Ejemplo n.º 10
0
int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
					      struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 vr = llc_sk(sk)->vR;
	u8 ns = LLC_I_GET_NS(pdu);

	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
Ejemplo n.º 11
0
void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	pdu->ctrl_1  = LLC_PDU_TYPE_I;
	pdu->ctrl_2  = 0;
	pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); 
	pdu->ctrl_1 |= (ns << 1) & 0xFE;   
	pdu->ctrl_2 |= (nr << 1) & 0xFE;   
}
Ejemplo n.º 12
0
void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	pdu->ctrl_1  = LLC_PDU_TYPE_S;
	pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
	pdu->ctrl_2  = p_bit & LLC_S_PF_BIT_MASK;
	pdu->ctrl_1 &= 0x0F;    
	pdu->ctrl_2 |= (nr << 1) & 0xFE; 
}
Ejemplo n.º 13
0
int llc_conn_ac_resend_i_cmd_p_set_1_or_send_rr(struct sock *sk,
						struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 nr = LLC_I_GET_NR(pdu);
	int rc = llc_conn_ac_send_rr_cmd_p_set_1(sk, skb);

	if (!rc)
		llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
	return rc;
}
Ejemplo n.º 14
0
void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	pdu->ctrl_1  = LLC_PDU_TYPE_S;
	pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
	pdu->ctrl_2  = 0;
	pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
	pdu->ctrl_1 &= 0x0F;    
	pdu->ctrl_2 |= (nr << 1) & 0xFE;  
}
Ejemplo n.º 15
0
int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
					    struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	if (LLC_PDU_IS_RSP(pdu) &&
	    LLC_PDU_TYPE_IS_I(pdu) &&
	    LLC_I_PF_IS_1(pdu) && llc_sk(sk)->ack_pf)
		llc_conn_ac_clear_remote_busy(sk, skb);
	return 0;
}
Ejemplo n.º 16
0
int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
					      struct sk_buff *skb)
{
	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	const u8 vr = llc_sk(sk)->vR;
	const u8 ns = LLC_I_GET_NS(pdu);

	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
	       LLC_I_PF_IS_1(pdu) && ns != vr &&
	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
Ejemplo n.º 17
0
/**
 *	llc_rcv - 802.2 entry point from net lower layers
 *	@skb: received pdu
 *	@dev: device that receive pdu
 *	@pt: packet type
 *
 *	When the system receives a 802.2 frame this function is called. It
 *	checks SAP and connection of received pdu and passes frame to
 *	llc_{station,sap,conn}_rcv for sending to proper state machine. If
 *	the frame is related to a busy connection (a connection is sending
 *	data now), it queues this frame in the connection's backlog.
 */
int llc_rcv(struct sk_buff *skb, struct net_device *dev,
	    struct packet_type *pt)
{
	struct llc_sap *sap;
	struct llc_pdu_sn *pdu;
	int dest;

	/*
	 * When the interface is in promisc. mode, drop all the crap that it
	 * receives, do not try to analyse it.
	 */
	if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
		dprintk("%s: PACKET_OTHERHOST\n", __FUNCTION__);
		goto drop;
	}
	skb = skb_share_check(skb, GFP_ATOMIC);
	if (unlikely(!skb))
		goto out;
	if (unlikely(!llc_fixup_skb(skb)))
		goto drop;
	pdu = llc_pdu_sn_hdr(skb);
	if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
	       goto handle_station;
	sap = llc_sap_find(pdu->dsap);
	if (unlikely(!sap)) {/* unknown SAP */
		dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__,
		        pdu->dsap);
		goto drop;
	}
	/*
	 * First the upper layer protocols that don't need the full
	 * LLC functionality
	 */
	if (sap->rcv_func) {
		sap->rcv_func(skb, dev, pt);
		goto out;
	}
	dest = llc_pdu_type(skb);
	if (unlikely(!dest || !llc_type_handlers[dest - 1]))
		goto drop;
	llc_type_handlers[dest - 1](sap, skb);
out:
	return 0;
drop:
	kfree_skb(skb);
	goto out;
handle_station:
	if (!llc_station_handler)
		goto drop;
	llc_station_handler(skb);
	goto out;
}
Ejemplo n.º 18
0
int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
					     struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 vr = llc_sk(sk)->vR;
	u8 ns = LLC_I_GET_NS(pdu);
	u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
		 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
	if (!rc)
		dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
			__FUNCTION__, llc_sk(sk)->state, ns, vr);
	return rc;
}
Ejemplo n.º 19
0
/**
 *	llc_util_nr_inside_tx_window - check if sequence number is in tx window
 *	@sk: current connection.
 *	@nr: N(R) of received PDU.
 *
 *	This routine checks if N(R) of received PDU is in range of transmit
 *	window; on the other hand checks if received PDU acknowledges some
 *	outstanding PDUs that are in transmit window. Returns 0 for success, 1
 *	otherwise.
 */
static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
{
	u8 nr1, nr2;
	struct sk_buff *skb;
	struct llc_pdu_sn *pdu;
	struct llc_opt *llc = llc_sk(sk);
	int rc = 0;

	if (llc->dev->flags & IFF_LOOPBACK)
		goto out;
	rc = 1;
	if (!skb_queue_len(&llc->pdu_unack_q))
		goto out;
	skb = skb_peek(&llc->pdu_unack_q);
	pdu = llc_pdu_sn_hdr(skb);
	nr1 = LLC_I_GET_NS(pdu);
	skb = skb_peek_tail(&llc->pdu_unack_q);
	pdu = llc_pdu_sn_hdr(skb);
	nr2 = LLC_I_GET_NS(pdu);
	rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO);
out:
	return rc;
}
Ejemplo n.º 20
0
int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
	u16 rc = 1;
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	if (LLC_PDU_IS_CMD(pdu)) {
		if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
			if (LLC_I_PF_IS_1(pdu))
				rc = 0;
		} else if (LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PF_IS_1(pdu))
			rc = 0;
	}
	return rc;
}
Ejemplo n.º 21
0
int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb)
{
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	if (LLC_PDU_IS_RSP(pdu)) {
		u8 f_bit;

		llc_pdu_decode_pf_bit(skb, &f_bit);
		if (f_bit) {
			llc_conn_set_p_flag(sk, 0);
			llc_conn_ac_stop_p_timer(sk, skb);
		}
	}
	return 0;
}
Ejemplo n.º 22
0
int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
{
	struct llc_sock *llc = llc_sk(sk);

	if (llc->remote_busy_flag) {
		u8 nr;
		struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

		llc->remote_busy_flag = 0;
		del_timer(&llc->busy_state_timer.timer);
		nr = LLC_I_GET_NR(pdu);
		llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
	}
	return 0;
}
Ejemplo n.º 23
0
int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
					       struct sk_buff *skb)
{
	u16 rc = 1;
	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	const u8 vs = llc_sk(sk)->vS;
	const u8 nr = LLC_I_GET_NR(pdu);

	if (LLC_PDU_IS_CMD(pdu) &&
	    (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
	    nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
		dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
			__func__, llc_sk(sk)->state, vs, nr);
		rc = 0;
	}
	return rc;
}
Ejemplo n.º 24
0
int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
					       struct sk_buff *skb)
{
	u16 rc = 1;
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
	u8 vs = llc_sk(sk)->vS;
	u8 nr = LLC_I_GET_NR(pdu);

	if (LLC_PDU_IS_RSP(pdu) &&
	    (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
	    nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
		rc = 0;
		dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
			__FUNCTION__, llc_sk(sk)->state, vs, nr);
	}
	return rc;
}
Ejemplo n.º 25
0
void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
{
	u8 pdu_type;
	struct llc_pdu_sn *pdu;

	llc_pdu_decode_pdu_type(skb, &pdu_type);
	pdu = llc_pdu_sn_hdr(skb);

	switch (pdu_type) {
	case LLC_PDU_TYPE_I:
	case LLC_PDU_TYPE_S:
		pdu->ctrl_2 = (pdu->ctrl_2 & 0xFE) | bit_value;
		break;
	case LLC_PDU_TYPE_U:
		pdu->ctrl_1 |= (pdu->ctrl_1 & 0xEF) | (bit_value << 4);
		break;
	}
}
Ejemplo n.º 26
0
void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
{
	u8 pdu_type;
	struct llc_pdu_sn *pdu;

	llc_pdu_decode_pdu_type(skb, &pdu_type);
	pdu = llc_pdu_sn_hdr(skb);

	switch (pdu_type) {
	case LLC_PDU_TYPE_I:
	case LLC_PDU_TYPE_S:
		*pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
		break;
	case LLC_PDU_TYPE_U:
		*pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
		break;
	}
}
Ejemplo n.º 27
0
/**
 *	llc_conn_send_pdus - Sends queued PDUs
 *	@sk: active connection
 *
 *	Sends queued pdus to MAC layer for transmission.
 */
static void llc_conn_send_pdus(struct sock *sk)
{
	struct sk_buff *skb;

	while ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL) {
		struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

		if (LLC_PDU_TYPE_IS_I(pdu) &&
		    !(skb->dev->flags & IFF_LOOPBACK)) {
			struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);

			skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb);
			if (!skb2)
				break;
			skb = skb2;
		}
		dev_queue_xmit(skb);
	}
}
Ejemplo n.º 28
0
int llc_conn_ev_rx_xxx_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
	u16 rc = 1;
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	if (LLC_PDU_IS_CMD(pdu)) {
		if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
			if (LLC_I_PF_IS_0(pdu))
				rc = 0;
		} else if (LLC_PDU_TYPE_IS_U(pdu))
			switch (LLC_U_PDU_CMD(pdu)) {
			case LLC_2_PDU_CMD_SABME:
			case LLC_2_PDU_CMD_DISC:
				if (LLC_U_PF_IS_0(pdu))
					rc = 0;
				break;
			}
	}
	return rc;
}
Ejemplo n.º 29
0
int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
	u16 rc = 1;
	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);

	if (LLC_PDU_IS_RSP(pdu)) {
		if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
			if (LLC_I_PF_IS_1(pdu))
				rc = 0;
		} else if (LLC_PDU_TYPE_IS_U(pdu))
			switch (LLC_U_PDU_RSP(pdu)) {
			case LLC_2_PDU_RSP_UA:
			case LLC_2_PDU_RSP_DM:
			case LLC_2_PDU_RSP_FRMR:
				if (LLC_U_PF_IS_1(pdu))
					rc = 0;
				break;
			}
	}
	return rc;
}
Ejemplo n.º 30
0
/**
 *	llc_rcv - 802.2 entry point from net lower layers
 *	@skb: received pdu
 *	@dev: device that receive pdu
 *	@pt: packet type
 *
 *	When the system receives a 802.2 frame this function is called. It
 *	checks SAP and connection of received pdu and passes frame to
 *	llc_{station,sap,conn}_rcv for sending to proper state machine. If
 *	the frame is related to a busy connection (a connection is sending
 *	data now), it queues this frame in the connection's backlog.
 */
int llc_rcv(struct sk_buff *skb, struct net_device *dev,
	    struct packet_type *pt, struct net_device *orig_dev)
{
	struct llc_sap *sap;
	struct llc_pdu_sn *pdu;
	int dest;
	int (*rcv)(struct sk_buff *, struct net_device *,
		   struct packet_type *, struct net_device *);
	void (*sta_handler)(struct sk_buff *skb);
	void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);

	if (!net_eq(dev_net(dev), &init_net))
		goto drop;

	/*
	 * When the interface is in promisc. mode, drop all the crap that it
	 * receives, do not try to analyse it.
	 */
	if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
		dprintk("%s: PACKET_OTHERHOST\n", __func__);
		goto drop;
	}
	skb = skb_share_check(skb, GFP_ATOMIC);
	if (unlikely(!skb))
		goto out;
	if (unlikely(!llc_fixup_skb(skb)))
		goto drop;
	pdu = llc_pdu_sn_hdr(skb);
	if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
	       goto handle_station;
	sap = llc_sap_find(pdu->dsap);
	if (unlikely(!sap)) {/* unknown SAP */
		dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
			pdu->dsap);
		goto drop;
	}
	/*
	 * First the upper layer protocols that don't need the full
	 * LLC functionality
	 */
	rcv = rcu_dereference(sap->rcv_func);
	dest = llc_pdu_type(skb);
	sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL;
	if (unlikely(!sap_handler)) {
		if (rcv)
			rcv(skb, dev, pt, orig_dev);
		else
			kfree_skb(skb);
	} else {
		if (rcv) {
			struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
			if (cskb)
				rcv(cskb, dev, pt, orig_dev);
		}
		sap_handler(sap, skb);
	}
	llc_sap_put(sap);
out:
	return 0;
drop:
	kfree_skb(skb);
	goto out;
handle_station:
	sta_handler = ACCESS_ONCE(llc_station_handler);
	if (!sta_handler)
		goto drop;
	sta_handler(skb);
	goto out;
}