Example #1
0
/*
 * disc_conf messages are also called no_resources or no_link
 * messages depending upon the "reason" field.
 */
static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
{
	struct dn_scp *scp = DN_SK(sk);
	unsigned short reason;

	if (skb->len != 2)
		goto out;

	reason = dn_ntohs(*(__u16 *)skb->data);

	sk->state = TCP_CLOSE;

	switch(scp->state) {
		case DN_CI:
			scp->state = DN_NR;
			break;
		case DN_DR:
			if (reason == NSP_REASON_DC)
				scp->state = DN_DRC;
			if (reason == NSP_REASON_NL)
				scp->state = DN_CN;
			break;
		case DN_DI:
			scp->state = DN_DIC;
			break;
		case DN_RUN:
			sk->shutdown |= SHUTDOWN_MASK;
		case DN_CC:
			scp->state = DN_CN;
	}

	if (!sk->dead) {
		if (sk->socket->state != SS_UNCONNECTED)
			sk->socket->state = SS_DISCONNECTING;
		sk->state_change(sk);
	}

	scp->persist_fxn = dn_destroy_timer;
	scp->persist = dn_nsp_persist(sk);

out:
	kfree_skb(skb);
}
Example #2
0
void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval)
{
	struct dn_scp *scp = DN_SK(sk);
	struct sk_buff *skb;
	unsigned char *ptr;
	gfp_t gfp = GFP_ATOMIC;

	if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL)
		return;

	skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
	ptr = skb_put(skb, 2);
	DN_SKB_CB(skb)->nsp_flags = 0x10;
	*ptr++ = lsflags;
	*ptr = fcval;

	dn_nsp_queue_xmit(sk, skb, gfp, 1);

	scp->persist = dn_nsp_persist(sk);
	scp->persist_fxn = dn_nsp_xmit_timeout;
}
Example #3
0
void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg)
{
	struct dn_scp *scp = DN_SK(sk);
	struct nsp_conn_init_msg *msg;
	unsigned char aux;
	unsigned char menuver;
	struct dn_skb_cb *cb;
	unsigned char type = 1;
	gfp_t allocation = (msgflg == NSP_CI) ? sk->sk_allocation : GFP_ATOMIC;
	struct sk_buff *skb = dn_alloc_skb(sk, 200, allocation);

	if (!skb)
		return;

	cb  = DN_SKB_CB(skb);
	msg = (struct nsp_conn_init_msg *)skb_put(skb,sizeof(*msg));

	msg->msgflg	= msgflg;
	msg->dstaddr	= 0x0000;		/* Remote Node will assign it*/

	msg->srcaddr	= scp->addrloc;
	msg->services	= scp->services_loc;	/* Requested flow control    */
	msg->info	= scp->info_loc;	/* Version Number            */
	msg->segsize	= cpu_to_le16(scp->segsize_loc);	/* Max segment size  */

	if (scp->peer.sdn_objnum)
		type = 0;

	skb_put(skb, dn_sockaddr2username(&scp->peer,
					  skb_tail_pointer(skb), type));
	skb_put(skb, dn_sockaddr2username(&scp->addr,
					  skb_tail_pointer(skb), 2));

	menuver = DN_MENUVER_ACC | DN_MENUVER_USR;
	if (scp->peer.sdn_flags & SDF_PROXY)
		menuver |= DN_MENUVER_PRX;
	if (scp->peer.sdn_flags & SDF_UICPROXY)
		menuver |= DN_MENUVER_UIC;

	*skb_put(skb, 1) = menuver;	/* Menu Version		*/

	aux = scp->accessdata.acc_userl;
	*skb_put(skb, 1) = aux;
	if (aux > 0)
	memcpy(skb_put(skb, aux), scp->accessdata.acc_user, aux);

	aux = scp->accessdata.acc_passl;
	*skb_put(skb, 1) = aux;
	if (aux > 0)
	memcpy(skb_put(skb, aux), scp->accessdata.acc_pass, aux);

	aux = scp->accessdata.acc_accl;
	*skb_put(skb, 1) = aux;
	if (aux > 0)
	memcpy(skb_put(skb, aux), scp->accessdata.acc_acc, aux);

	aux = (__u8)le16_to_cpu(scp->conndata_out.opt_optl);
	*skb_put(skb, 1) = aux;
	if (aux > 0)
	memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux);

	scp->persist = dn_nsp_persist(sk);
	scp->persist_fxn = dn_nsp_retrans_conninit;

	cb->rt_flags = DN_RT_F_RQR;

	dn_nsp_send(skb);
}
Example #4
0
static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
{
	struct dn_scp *scp = DN_SK(sk);
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	unsigned short reason;

	if (skb->len < 2)
		goto out;

	reason = le16_to_cpu(*(__le16 *)skb->data);
	skb_pull(skb, 2);

	scp->discdata_in.opt_status = cpu_to_le16(reason);
	scp->discdata_in.opt_optl   = 0;
	memset(scp->discdata_in.opt_data, 0, 16);

	if (skb->len > 0) {
		u16 dlen = *skb->data;
		if ((dlen <= 16) && (dlen <= skb->len)) {
			scp->discdata_in.opt_optl = cpu_to_le16(dlen);
			skb_copy_from_linear_data_offset(skb, 1, scp->discdata_in.opt_data, dlen);
		}
	}

	scp->addrrem = cb->src_port;
	sk->sk_state = TCP_CLOSE;

	switch (scp->state) {
	case DN_CI:
	case DN_CD:
		scp->state = DN_RJ;
		sk->sk_err = ECONNREFUSED;
		break;
	case DN_RUN:
		sk->sk_shutdown |= SHUTDOWN_MASK;
		scp->state = DN_DN;
		break;
	case DN_DI:
		scp->state = DN_DIC;
		break;
	}

	if (!sock_flag(sk, SOCK_DEAD)) {
		if (sk->sk_socket->state != SS_UNCONNECTED)
			sk->sk_socket->state = SS_DISCONNECTING;
		sk->sk_state_change(sk);
	}

	/*
	 * It appears that its possible for remote machines to send disc
	 * init messages with no port identifier if we are in the CI and
	 * possibly also the CD state. Obviously we shouldn't reply with
	 * a message if we don't know what the end point is.
	 */
	if (scp->addrrem) {
		dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
	}
	scp->persist_fxn = dn_destroy_timer;
	scp->persist = dn_nsp_persist(sk);

out:
	kfree_skb(skb);
}