Exemplo n.º 1
0
/*
 *	This is where all X.25 information frames pass.
 *
 *      Returns the amount of user data bytes sent on success
 *      or a negative error code on failure.
 */
int x25_output(struct sock *sk, struct sk_buff *skb)
{
	struct sk_buff *skbn;
	unsigned char header[X25_EXT_MIN_LEN];
	int err, frontlen, len, header_len, max_len;
	int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT;

	header_len = (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN;
	max_len    = x25_pacsize_to_bytes(sk->protinfo.x25->facilities.pacsize_out);

	if (skb->len - header_len > max_len) {
		/* Save a copy of the Header */
		memcpy(header, skb->data, header_len);
		skb_pull(skb, header_len);

		frontlen = skb_headroom(skb);

		while (skb->len > 0) {
			if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, noblock, &err)) == NULL){
				if(err == -EWOULDBLOCK && noblock){
					kfree_skb(skb);
					return sent;
				}
				SOCK_DEBUG(sk, "x25_output: fragment allocation failed, err=%d, %d bytes sent\n", err, sent);
				return err;
			}
				
			skb_reserve(skbn, frontlen);

			len = (max_len > skb->len) ? skb->len : max_len;

			/* Copy the user data */
			memcpy(skb_put(skbn, len), skb->data, len);
			skb_pull(skb, len);

			/* Duplicate the Header */
			skb_push(skbn, header_len);
			memcpy(skbn->data, header, header_len);

			if (skb->len > 0) {
				if (sk->protinfo.x25->neighbour->extended)
					skbn->data[3] |= X25_EXT_M_BIT;
				else
					skbn->data[2] |= X25_STD_M_BIT;
			}

			skb_queue_tail(&sk->write_queue, skbn);
			sent += len;
		}
		
		kfree_skb(skb);
	} else {
		skb_queue_tail(&sk->write_queue, skb);
		sent = skb->len - header_len;
	}
	return sent;
}
Exemplo n.º 2
0
/*
 *	This is where all X.25 information frames pass.
 *
 *      Returns the amount of user data bytes sent on success
 *      or a negative error code on failure.
 */
int x25_output(struct sock *sk, struct sk_buff *skb)
{
	struct sk_buff *skbn;
	unsigned char header[X25_EXT_MIN_LEN];
	int err, frontlen, len;
	int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT;
	struct x25_sock *x25 = x25_sk(sk);
	int header_len = x25->neighbour->extended ? X25_EXT_MIN_LEN :
						    X25_STD_MIN_LEN;
	int max_len = x25_pacsize_to_bytes(x25->facilities.pacsize_out);

	if (skb->len - header_len > max_len) {
		/* Save a copy of the Header */
		skb_copy_from_linear_data(skb, header, header_len);
		skb_pull(skb, header_len);

		frontlen = skb_headroom(skb);

		while (skb->len > 0) {
<<<<<<< HEAD
			release_sock(sk);
			skbn = sock_alloc_send_skb(sk, frontlen + max_len,
						   noblock, &err);
			lock_sock(sk);
			if (!skbn) {
=======
			if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len,
							noblock, &err)) == NULL){
>>>>>>> 296c66da8a02d52243f45b80521febece5ed498a
				if (err == -EWOULDBLOCK && noblock){
					kfree_skb(skb);
					return sent;
				}
				SOCK_DEBUG(sk, "x25_output: fragment alloc"
					       " failed, err=%d, %d bytes "
					       "sent\n", err, sent);
				return err;
			}
Exemplo n.º 3
0
/*
 *	This is where all X.25 information frames pass.
 *
 *      Returns the amount of user data bytes sent on success
 *      or a negative error code on failure.
 */
int x25_output(struct sock *sk, struct sk_buff *skb)
{
	struct sk_buff *skbn;
	unsigned char header[X25_EXT_MIN_LEN];
	int err, frontlen, len;
	int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT;
	struct x25_sock *x25 = x25_sk(sk);
	int header_len = x25->neighbour->extended ? X25_EXT_MIN_LEN :
						    X25_STD_MIN_LEN;
	int max_len = x25_pacsize_to_bytes(x25->facilities.pacsize_out);

	if (skb->len - header_len > max_len) {
		/* Save a copy of the Header */
		skb_copy_from_linear_data(skb, header, header_len);
		skb_pull(skb, header_len);

		frontlen = skb_headroom(skb);

		while (skb->len > 0) {
			release_sock(sk);
			skbn = sock_alloc_send_skb(sk, frontlen + max_len,
						   noblock, &err);
			lock_sock(sk);
			if (!skbn) {
				if (err == -EWOULDBLOCK && noblock){
					kfree_skb(skb);
					return sent;
				}
				SOCK_DEBUG(sk, "x25_output: fragment alloc"
					       " failed, err=%d, %d bytes "
					       "sent\n", err, sent);
				return err;
			}

			skb_reserve(skbn, frontlen);

			len = max_len > skb->len ? skb->len : max_len;

			/* Copy the user data */
			skb_copy_from_linear_data(skb, skb_put(skbn, len), len);
			skb_pull(skb, len);

			/* Duplicate the Header */
			skb_push(skbn, header_len);
			skb_copy_to_linear_data(skbn, header, header_len);

			if (skb->len > 0) {
				if (x25->neighbour->extended)
					skbn->data[3] |= X25_EXT_M_BIT;
				else
					skbn->data[2] |= X25_STD_M_BIT;
			}

			skb_queue_tail(&sk->sk_write_queue, skbn);
			sent += len;
		}

		kfree_skb(skb);
	} else {
		skb_queue_tail(&sk->sk_write_queue, skb);
		sent = skb->len - header_len;
	}
	return sent;
}
Exemplo n.º 4
0
int x25_register(struct x25_callbacks *callbacks, struct x25_params * params, struct x25_cs ** x25) {
	(void)params;
	int rc = X25_CALLBACK_ERR;

	/* Check callbacks */
	if (!callbacks->add_timer ||
		!callbacks->del_timer ||
		!callbacks->start_timer ||
		!callbacks->stop_timer ||
		!callbacks->link_connect_request ||
		!callbacks->link_disconnect_request ||
		!callbacks->link_send_frame)
		goto out;

	*x25 = x25_mem_get(sizeof(struct x25_cs));
	rc = X25_NOMEM;
	if (!*x25)
		goto out;


	x25_mem_zero(*x25, sizeof(struct x25_cs));

	struct x25_cs_internal * x25_int = x25_mem_get(sizeof(struct x25_cs_internal));
	x25_mem_zero(x25_int, sizeof(struct x25_cs_internal));
	(*x25)->internal_struct = x25_int;

	if (!callbacks->debug)
		callbacks->debug = x25_default_debug;
	(*x25)->callbacks = callbacks;

	if (params)
		x25_set_params(*x25, params);
	else {
		/* Set default values */
		x25_int->RestartTimer.interval = X25_DEFAULT_RESTART_TIMER;
		(*x25)->RestartTimer_NR = 2;
		x25_int->CallTimer.interval = X25_DEFAULT_CALL_TIMER;
		(*x25)->CallTimer_NR = 2;
		x25_int->ResetTimer.interval = X25_DEFAULT_RESET_TIMER;
		(*x25)->ResetTimer_NR = 2;
		x25_int->ClearTimer.interval = X25_DEFAULT_CLEAR_TIMER;
		(*x25)->ClearTimer_NR = 2;
		x25_int->AckTimer.interval  = X25_DEFAULT_ACK_TIMER;
		(*x25)->AckTimer_NR = 2;
		x25_int->DataTimer.interval  = X25_DEFAULT_DATA_TIMER;
		(*x25)->DataTimer_NR = 2;
		/* Create timers */
		x25_int->RestartTimer.timer_ptr  = (*x25)->callbacks->add_timer(x25_int->RestartTimer.interval,  *x25, x25_timer_expiry);
		x25_int->CallTimer.timer_ptr = (*x25)->callbacks->add_timer(x25_int->CallTimer.interval, *x25, x25_timer_expiry);
		x25_int->ResetTimer.timer_ptr = (*x25)->callbacks->add_timer(x25_int->ResetTimer.interval, *x25, x25_timer_expiry);
		x25_int->ClearTimer.timer_ptr = (*x25)->callbacks->add_timer(x25_int->ClearTimer.interval, *x25, x25_timer_expiry);
		x25_int->AckTimer.timer_ptr = (*x25)->callbacks->add_timer(x25_int->AckTimer.interval, *x25, x25_timer_expiry);
		x25_int->DataTimer.timer_ptr = (*x25)->callbacks->add_timer(x25_int->DataTimer.interval, *x25, x25_timer_expiry);
	};


	x25_int->state = X25_STATE_0;
	(*x25)->cudmatchlength = 0;		/* normally no cud on call accept */
	x25_int->flags |= X25_ACCPT_APPRV_FLAG;

	x25_int->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;
	x25_int->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
	x25_int->facilities.pacsize_in  = X25_DEFAULT_PACKET_SIZE;
	x25_int->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
	x25_int->facilities.throughput  = 0;	/* by default don't negotiate throughput */
	x25_int->facilities.reverse     = X25_DEFAULT_REVERSE;
	x25_int->dte_facilities.calling_len = 0;
	x25_int->dte_facilities.called_len = 0;
	x25_mem_zero(x25_int->dte_facilities.called_ae, sizeof(x25_int->dte_facilities.called_ae));
	x25_mem_zero(x25_int->dte_facilities.calling_ae, sizeof(x25_int->dte_facilities.calling_ae));

	/* Create queues */
	cb_init(&x25_int->ack_queue, X25_SMODULUS, x25_pacsize_to_bytes(X25_DEFAULT_PACKET_SIZE)*X25_DEFAULT_WINDOW_SIZE);
	cb_init(&x25_int->write_queue, X25_SMODULUS, x25_pacsize_to_bytes(X25_DEFAULT_PACKET_SIZE)*X25_DEFAULT_WINDOW_SIZE);
	cb_init(&x25_int->interrupt_in_queue, X25_SMODULUS, x25_pacsize_to_bytes(x25_int->facilities.pacsize_out));
	cb_init(&x25_int->interrupt_out_queue, X25_SMODULUS, x25_pacsize_to_bytes(x25_int->facilities.pacsize_out));


	rc = X25_OK;
out:
	return rc;
}