aboutsummaryrefslogtreecommitdiffstats
path: root/net/llc/llc_conn.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/llc/llc_conn.c')
-rw-r--r--net/llc/llc_conn.c212
1 files changed, 123 insertions, 89 deletions
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 4c644bc70eae..042b24a8ca4c 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -40,6 +40,11 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
40/* Offset table on connection states transition diagram */ 40/* Offset table on connection states transition diagram */
41static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; 41static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
42 42
43int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;
44int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;
45int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;
46int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;
47
43/** 48/**
44 * llc_conn_state_process - sends event to connection state machine 49 * llc_conn_state_process - sends event to connection state machine
45 * @sk: connection 50 * @sk: connection
@@ -53,7 +58,7 @@ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
53int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) 58int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
54{ 59{
55 int rc; 60 int rc;
56 struct llc_sock *llc = llc_sk(sk); 61 struct llc_sock *llc = llc_sk(skb->sk);
57 struct llc_conn_state_ev *ev = llc_conn_ev(skb); 62 struct llc_conn_state_ev *ev = llc_conn_ev(skb);
58 63
59 /* 64 /*
@@ -63,13 +68,16 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
63 */ 68 */
64 skb_get(skb); 69 skb_get(skb);
65 ev->ind_prim = ev->cfm_prim = 0; 70 ev->ind_prim = ev->cfm_prim = 0;
66 rc = llc_conn_service(sk, skb); /* sending event to state machine */ 71 /*
67 if (rc) { 72 * Send event to state machine
73 */
74 rc = llc_conn_service(skb->sk, skb);
75 if (unlikely(rc != 0)) {
68 printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__); 76 printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
69 goto out_kfree_skb; 77 goto out_kfree_skb;
70 } 78 }
71 79
72 if (!ev->ind_prim && !ev->cfm_prim) { 80 if (unlikely(!ev->ind_prim && !ev->cfm_prim)) {
73 /* indicate or confirm not required */ 81 /* indicate or confirm not required */
74 /* XXX this is not very pretty, perhaps we should store 82 /* XXX this is not very pretty, perhaps we should store
75 * XXX indicate/confirm-needed state in the llc_conn_state_ev 83 * XXX indicate/confirm-needed state in the llc_conn_state_ev
@@ -80,13 +88,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
80 goto out_skb_put; 88 goto out_skb_put;
81 } 89 }
82 90
83 if (ev->ind_prim && ev->cfm_prim) /* Paranoia */ 91 if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */
84 skb_get(skb); 92 skb_get(skb);
85 93
86 switch (ev->ind_prim) { 94 switch (ev->ind_prim) {
87 case LLC_DATA_PRIM: 95 case LLC_DATA_PRIM:
88 llc_save_primitive(skb, LLC_DATA_PRIM); 96 llc_save_primitive(sk, skb, LLC_DATA_PRIM);
89 if (sock_queue_rcv_skb(sk, skb)) { 97 if (unlikely(sock_queue_rcv_skb(sk, skb))) {
90 /* 98 /*
91 * shouldn't happen 99 * shouldn't happen
92 */ 100 */
@@ -95,13 +103,14 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
95 kfree_skb(skb); 103 kfree_skb(skb);
96 } 104 }
97 break; 105 break;
98 case LLC_CONN_PRIM: { 106 case LLC_CONN_PRIM:
99 struct sock *parent = skb->sk; 107 /*
100 108 * Can't be sock_queue_rcv_skb, because we have to leave the
101 skb->sk = sk; 109 * skb->sk pointing to the newly created struct sock in
102 skb_queue_tail(&parent->sk_receive_queue, skb); 110 * llc_conn_handler. -acme
103 sk->sk_state_change(parent); 111 */
104 } 112 skb_queue_tail(&sk->sk_receive_queue, skb);
113 sk->sk_state_change(sk);
105 break; 114 break;
106 case LLC_DISC_PRIM: 115 case LLC_DISC_PRIM:
107 sock_hold(sk); 116 sock_hold(sk);
@@ -111,8 +120,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
111 sk->sk_socket->state = SS_UNCONNECTED; 120 sk->sk_socket->state = SS_UNCONNECTED;
112 sk->sk_state = TCP_CLOSE; 121 sk->sk_state = TCP_CLOSE;
113 if (!sock_flag(sk, SOCK_DEAD)) { 122 if (!sock_flag(sk, SOCK_DEAD)) {
114 sk->sk_state_change(sk);
115 sock_set_flag(sk, SOCK_DEAD); 123 sock_set_flag(sk, SOCK_DEAD);
124 sk->sk_state_change(sk);
116 } 125 }
117 } 126 }
118 kfree_skb(skb); 127 kfree_skb(skb);
@@ -465,7 +474,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
465} 474}
466 475
467/** 476/**
468 * llc_lookup_established - Finds connection for the remote/local sap/mac 477 * __llc_lookup_established - Finds connection for the remote/local sap/mac
469 * @sap: SAP 478 * @sap: SAP
470 * @daddr: address of remote LLC (MAC + SAP) 479 * @daddr: address of remote LLC (MAC + SAP)
471 * @laddr: address of local LLC (MAC + SAP) 480 * @laddr: address of local LLC (MAC + SAP)
@@ -473,14 +482,16 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
473 * Search connection list of the SAP and finds connection using the remote 482 * Search connection list of the SAP and finds connection using the remote
474 * mac, remote sap, local mac, and local sap. Returns pointer for 483 * mac, remote sap, local mac, and local sap. Returns pointer for
475 * connection found, %NULL otherwise. 484 * connection found, %NULL otherwise.
485 * Caller has to make sure local_bh is disabled.
476 */ 486 */
477struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, 487static struct sock *__llc_lookup_established(struct llc_sap *sap,
478 struct llc_addr *laddr) 488 struct llc_addr *daddr,
489 struct llc_addr *laddr)
479{ 490{
480 struct sock *rc; 491 struct sock *rc;
481 struct hlist_node *node; 492 struct hlist_node *node;
482 493
483 read_lock_bh(&sap->sk_list.lock); 494 read_lock(&sap->sk_list.lock);
484 sk_for_each(rc, node, &sap->sk_list.list) { 495 sk_for_each(rc, node, &sap->sk_list.list) {
485 struct llc_sock *llc = llc_sk(rc); 496 struct llc_sock *llc = llc_sk(rc);
486 497
@@ -494,10 +505,22 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
494 } 505 }
495 rc = NULL; 506 rc = NULL;
496found: 507found:
497 read_unlock_bh(&sap->sk_list.lock); 508 read_unlock(&sap->sk_list.lock);
498 return rc; 509 return rc;
499} 510}
500 511
512struct sock *llc_lookup_established(struct llc_sap *sap,
513 struct llc_addr *daddr,
514 struct llc_addr *laddr)
515{
516 struct sock *sk;
517
518 local_bh_disable();
519 sk = __llc_lookup_established(sap, daddr, laddr);
520 local_bh_enable();
521 return sk;
522}
523
501/** 524/**
502 * llc_lookup_listener - Finds listener for local MAC + SAP 525 * llc_lookup_listener - Finds listener for local MAC + SAP
503 * @sap: SAP 526 * @sap: SAP
@@ -506,6 +529,7 @@ found:
506 * Search connection list of the SAP and finds connection listening on 529 * Search connection list of the SAP and finds connection listening on
507 * local mac, and local sap. Returns pointer for parent socket found, 530 * local mac, and local sap. Returns pointer for parent socket found,
508 * %NULL otherwise. 531 * %NULL otherwise.
532 * Caller has to make sure local_bh is disabled.
509 */ 533 */
510static struct sock *llc_lookup_listener(struct llc_sap *sap, 534static struct sock *llc_lookup_listener(struct llc_sap *sap,
511 struct llc_addr *laddr) 535 struct llc_addr *laddr)
@@ -513,7 +537,7 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
513 struct sock *rc; 537 struct sock *rc;
514 struct hlist_node *node; 538 struct hlist_node *node;
515 539
516 read_lock_bh(&sap->sk_list.lock); 540 read_lock(&sap->sk_list.lock);
517 sk_for_each(rc, node, &sap->sk_list.list) { 541 sk_for_each(rc, node, &sap->sk_list.list) {
518 struct llc_sock *llc = llc_sk(rc); 542 struct llc_sock *llc = llc_sk(rc);
519 543
@@ -527,10 +551,19 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
527 } 551 }
528 rc = NULL; 552 rc = NULL;
529found: 553found:
530 read_unlock_bh(&sap->sk_list.lock); 554 read_unlock(&sap->sk_list.lock);
531 return rc; 555 return rc;
532} 556}
533 557
558static struct sock *__llc_lookup(struct llc_sap *sap,
559 struct llc_addr *daddr,
560 struct llc_addr *laddr)
561{
562 struct sock *sk = __llc_lookup_established(sap, daddr, laddr);
563
564 return sk ? : llc_lookup_listener(sap, laddr);
565}
566
534/** 567/**
535 * llc_data_accept_state - designates if in this state data can be sent. 568 * llc_data_accept_state - designates if in this state data can be sent.
536 * @state: state of connection. 569 * @state: state of connection.
@@ -544,14 +577,14 @@ u8 llc_data_accept_state(u8 state)
544} 577}
545 578
546/** 579/**
547 * find_next_offset - finds offset for next category of transitions 580 * llc_find_next_offset - finds offset for next category of transitions
548 * @state: state table. 581 * @state: state table.
549 * @offset: start offset. 582 * @offset: start offset.
550 * 583 *
551 * Finds offset of next category of transitions in transition table. 584 * Finds offset of next category of transitions in transition table.
552 * Returns the start index of next category. 585 * Returns the start index of next category.
553 */ 586 */
554static u16 find_next_offset(struct llc_conn_state *state, u16 offset) 587static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset)
555{ 588{
556 u16 cnt = 0; 589 u16 cnt = 0;
557 struct llc_conn_state_trans **next_trans; 590 struct llc_conn_state_trans **next_trans;
@@ -578,8 +611,8 @@ void __init llc_build_offset_table(void)
578 next_offset = 0; 611 next_offset = 0;
579 for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) { 612 for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {
580 llc_offset_table[state][ev_type] = next_offset; 613 llc_offset_table[state][ev_type] = next_offset;
581 next_offset += find_next_offset(curr_state, 614 next_offset += llc_find_next_offset(curr_state,
582 next_offset) + 1; 615 next_offset) + 1;
583 } 616 }
584 } 617 }
585} 618}
@@ -623,6 +656,7 @@ static int llc_find_offset(int state, int ev_type)
623 */ 656 */
624void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) 657void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
625{ 658{
659 llc_sap_hold(sap);
626 write_lock_bh(&sap->sk_list.lock); 660 write_lock_bh(&sap->sk_list.lock);
627 llc_sk(sk)->sap = sap; 661 llc_sk(sk)->sap = sap;
628 sk_add_node(sk, &sap->sk_list.list); 662 sk_add_node(sk, &sap->sk_list.list);
@@ -642,6 +676,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
642 write_lock_bh(&sap->sk_list.lock); 676 write_lock_bh(&sap->sk_list.lock);
643 sk_del_node_init(sk); 677 sk_del_node_init(sk);
644 write_unlock_bh(&sap->sk_list.lock); 678 write_unlock_bh(&sap->sk_list.lock);
679 llc_sap_put(sap);
645} 680}
646 681
647/** 682/**
@@ -654,15 +689,34 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
654static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb) 689static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
655{ 690{
656 struct llc_conn_state_ev *ev = llc_conn_ev(skb); 691 struct llc_conn_state_ev *ev = llc_conn_ev(skb);
657 struct llc_sock *llc = llc_sk(sk);
658 692
659 if (!llc->dev)
660 llc->dev = skb->dev;
661 ev->type = LLC_CONN_EV_TYPE_PDU; 693 ev->type = LLC_CONN_EV_TYPE_PDU;
662 ev->reason = 0; 694 ev->reason = 0;
663 return llc_conn_state_process(sk, skb); 695 return llc_conn_state_process(sk, skb);
664} 696}
665 697
698static struct sock *llc_create_incoming_sock(struct sock *sk,
699 struct net_device *dev,
700 struct llc_addr *saddr,
701 struct llc_addr *daddr)
702{
703 struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,
704 sk->sk_prot);
705 struct llc_sock *newllc, *llc = llc_sk(sk);
706
707 if (!newsk)
708 goto out;
709 newllc = llc_sk(newsk);
710 memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr));
711 memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr));
712 newllc->dev = dev;
713 dev_hold(dev);
714 llc_sap_add_socket(llc->sap, newsk);
715 llc_sap_hold(llc->sap);
716out:
717 return newsk;
718}
719
666void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) 720void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
667{ 721{
668 struct llc_addr saddr, daddr; 722 struct llc_addr saddr, daddr;
@@ -673,35 +727,35 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
673 llc_pdu_decode_da(skb, daddr.mac); 727 llc_pdu_decode_da(skb, daddr.mac);
674 llc_pdu_decode_dsap(skb, &daddr.lsap); 728 llc_pdu_decode_dsap(skb, &daddr.lsap);
675 729
676 sk = llc_lookup_established(sap, &saddr, &daddr); 730 sk = __llc_lookup(sap, &saddr, &daddr);
677 if (!sk) { 731 if (!sk)
732 goto drop;
733
734 bh_lock_sock(sk);
735 /*
736 * This has to be done here and not at the upper layer ->accept
737 * method because of the way the PROCOM state machine works:
738 * it needs to set several state variables (see, for instance,
739 * llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to
740 * the originator of the new connection, and this state has to be
741 * in the newly created struct sock private area. -acme
742 */
743 if (unlikely(sk->sk_state == TCP_LISTEN)) {
744 struct sock *newsk = llc_create_incoming_sock(sk, skb->dev,
745 &saddr, &daddr);
746 if (!newsk)
747 goto drop_unlock;
748 skb_set_owner_r(skb, newsk);
749 } else {
678 /* 750 /*
679 * Didn't find an active connection; verify if there 751 * Can't be skb_set_owner_r, this will be done at the
680 * is a listening socket for this llc addr 752 * llc_conn_state_process function, later on, when we will use
753 * skb_queue_rcv_skb to send it to upper layers, this is
754 * another trick required to cope with how the PROCOM state
755 * machine works. -acme
681 */ 756 */
682 struct llc_sock *llc;
683 struct sock *parent = llc_lookup_listener(sap, &daddr);
684
685 if (!parent) {
686 dprintk("llc_lookup_listener failed!\n");
687 goto drop;
688 }
689
690 sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);
691 if (!sk) {
692 sock_put(parent);
693 goto drop;
694 }
695 llc = llc_sk(sk);
696 memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));
697 memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));
698 llc_sap_add_socket(sap, sk);
699 sock_hold(sk);
700 sock_put(parent);
701 skb->sk = parent;
702 } else
703 skb->sk = sk; 757 skb->sk = sk;
704 bh_lock_sock(sk); 758 }
705 if (!sock_owned_by_user(sk)) 759 if (!sock_owned_by_user(sk))
706 llc_conn_rcv(sk, skb); 760 llc_conn_rcv(sk, skb);
707 else { 761 else {
@@ -709,11 +763,16 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
709 llc_set_backlog_type(skb, LLC_PACKET); 763 llc_set_backlog_type(skb, LLC_PACKET);
710 sk_add_backlog(sk, skb); 764 sk_add_backlog(sk, skb);
711 } 765 }
766out:
712 bh_unlock_sock(sk); 767 bh_unlock_sock(sk);
713 sock_put(sk); 768 sock_put(sk);
714 return; 769 return;
715drop: 770drop:
716 kfree_skb(skb); 771 kfree_skb(skb);
772 return;
773drop_unlock:
774 kfree_skb(skb);
775 goto out;
717} 776}
718 777
719#undef LLC_REFCNT_DEBUG 778#undef LLC_REFCNT_DEBUG
@@ -722,32 +781,6 @@ static atomic_t llc_sock_nr;
722#endif 781#endif
723 782
724/** 783/**
725 * llc_release_sockets - releases all sockets in a sap
726 * @sap: sap to release its sockets
727 *
728 * Releases all connections of a sap. Returns 0 if all actions complete
729 * successfully, nonzero otherwise
730 */
731int llc_release_sockets(struct llc_sap *sap)
732{
733 int rc = 0;
734 struct sock *sk;
735 struct hlist_node *node;
736
737 write_lock_bh(&sap->sk_list.lock);
738
739 sk_for_each(sk, node, &sap->sk_list.list) {
740 llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
741
742 if (llc_send_disc(sk))
743 rc = 1;
744 }
745
746 write_unlock_bh(&sap->sk_list.lock);
747 return rc;
748}
749
750/**
751 * llc_backlog_rcv - Processes rx frames and expired timers. 784 * llc_backlog_rcv - Processes rx frames and expired timers.
752 * @sk: LLC sock (p8022 connection) 785 * @sk: LLC sock (p8022 connection)
753 * @skb: queued rx frame or event 786 * @skb: queued rx frame or event
@@ -762,14 +795,14 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
762 int rc = 0; 795 int rc = 0;
763 struct llc_sock *llc = llc_sk(sk); 796 struct llc_sock *llc = llc_sk(sk);
764 797
765 if (llc_backlog_type(skb) == LLC_PACKET) { 798 if (likely(llc_backlog_type(skb) == LLC_PACKET)) {
766 if (llc->state > 1) /* not closed */ 799 if (likely(llc->state > 1)) /* not closed */
767 rc = llc_conn_rcv(sk, skb); 800 rc = llc_conn_rcv(sk, skb);
768 else 801 else
769 goto out_kfree_skb; 802 goto out_kfree_skb;
770 } else if (llc_backlog_type(skb) == LLC_EVENT) { 803 } else if (llc_backlog_type(skb) == LLC_EVENT) {
771 /* timer expiration event */ 804 /* timer expiration event */
772 if (llc->state > 1) /* not closed */ 805 if (likely(llc->state > 1)) /* not closed */
773 rc = llc_conn_state_process(sk, skb); 806 rc = llc_conn_state_process(sk, skb);
774 else 807 else
775 goto out_kfree_skb; 808 goto out_kfree_skb;
@@ -799,22 +832,22 @@ static void llc_sk_init(struct sock* sk)
799 llc->dec_step = llc->connect_step = 1; 832 llc->dec_step = llc->connect_step = 1;
800 833
801 init_timer(&llc->ack_timer.timer); 834 init_timer(&llc->ack_timer.timer);
802 llc->ack_timer.expire = LLC_ACK_TIME; 835 llc->ack_timer.expire = sysctl_llc2_ack_timeout;
803 llc->ack_timer.timer.data = (unsigned long)sk; 836 llc->ack_timer.timer.data = (unsigned long)sk;
804 llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; 837 llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
805 838
806 init_timer(&llc->pf_cycle_timer.timer); 839 init_timer(&llc->pf_cycle_timer.timer);
807 llc->pf_cycle_timer.expire = LLC_P_TIME; 840 llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout;
808 llc->pf_cycle_timer.timer.data = (unsigned long)sk; 841 llc->pf_cycle_timer.timer.data = (unsigned long)sk;
809 llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb; 842 llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
810 843
811 init_timer(&llc->rej_sent_timer.timer); 844 init_timer(&llc->rej_sent_timer.timer);
812 llc->rej_sent_timer.expire = LLC_REJ_TIME; 845 llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout;
813 llc->rej_sent_timer.timer.data = (unsigned long)sk; 846 llc->rej_sent_timer.timer.data = (unsigned long)sk;
814 llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb; 847 llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
815 848
816 init_timer(&llc->busy_state_timer.timer); 849 init_timer(&llc->busy_state_timer.timer);
817 llc->busy_state_timer.expire = LLC_BUSY_TIME; 850 llc->busy_state_timer.expire = sysctl_llc2_busy_timeout;
818 llc->busy_state_timer.timer.data = (unsigned long)sk; 851 llc->busy_state_timer.timer.data = (unsigned long)sk;
819 llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb; 852 llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
820 853
@@ -834,7 +867,8 @@ static void llc_sk_init(struct sock* sk)
834 * Allocates a LLC sock and initializes it. Returns the new LLC sock 867 * Allocates a LLC sock and initializes it. Returns the new LLC sock
835 * or %NULL if there's no memory available for one 868 * or %NULL if there's no memory available for one
836 */ 869 */
837struct sock *llc_sk_alloc(int family, int priority, struct proto *prot) 870struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,
871 struct proto *prot)
838{ 872{
839 struct sock *sk = sk_alloc(family, priority, prot, 1); 873 struct sock *sk = sk_alloc(family, priority, prot, 1);
840 874