1 /* Copyright (c) University of British Columbia, 1984 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/socket.h" 7 #include "../h/socketvar.h" 8 #include "../h/protosw.h" 9 #include "../h/errno.h" 10 11 #include "../net/if.h" 12 13 #include "../netccitt/pk.h" 14 #include "../netccitt/pk_var.h" 15 #include "../netccitt/x25.h" 16 17 struct mbuf *nextpk (); 18 19 pk_output (lcp) 20 register struct pklcd *lcp; 21 { 22 register struct x25_packet *xp; 23 register struct mbuf *m; 24 register struct pkcb *pkp = lcp -> lcd_pkp; 25 26 if (lcp == 0 || pkp == 0) { 27 printf ("pk_output: zero arg\n"); 28 return; 29 } 30 31 while ((m = nextpk (lcp)) != NULL) { 32 xp = mtod (m, struct x25_packet *); 33 34 switch (pk_decode (xp) + lcp -> lcd_state) { 35 /* 36 * All the work is already done - just set the state and 37 * pass to peer. 38 */ 39 case CALL + READY: 40 lcp -> lcd_state = SENT_CALL; 41 lcp -> lcd_timer = pk_t21; 42 break; 43 44 /* 45 * Just set the state to allow packet to flow and send the 46 * confirmation. 47 */ 48 case CALL_ACCEPTED + RECEIVED_CALL: 49 lcp -> lcd_state = DATA_TRANSFER; 50 break; 51 52 /* 53 * Just set the state. Keep the LCD around till the clear 54 * confirmation is returned. 55 */ 56 case CLEAR + RECEIVED_CALL: 57 case CLEAR + SENT_CALL: 58 case CLEAR + DATA_TRANSFER: 59 lcp -> lcd_state = SENT_CLEAR; 60 lcp -> lcd_retry = 0; 61 /* fall through */ 62 63 case CLEAR + SENT_CLEAR: 64 lcp -> lcd_timer = pk_t23; 65 lcp -> lcd_retry++; 66 break; 67 68 case CLEAR_CONF + RECEIVED_CLEAR: 69 case CLEAR_CONF + SENT_CLEAR: 70 case CLEAR_CONF + READY: 71 lcp -> lcd_state = READY; 72 break; 73 74 case DATA + DATA_TRANSFER: 75 PS(xp) = lcp -> lcd_ssn; 76 PR(xp) = lcp -> lcd_input_window; 77 lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 78 lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS; 79 if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + pkp->pk_xcp->xc_pwsize) % MODULUS)) 80 lcp -> lcd_window_condition = TRUE; 81 break; 82 83 case INTERRUPT + DATA_TRANSFER: 84 xp -> packet_data = 0; 85 lcp -> lcd_intrconf_pending = TRUE; 86 break; 87 88 case INTERRUPT_CONF + DATA_TRANSFER: 89 break; 90 91 case RR + DATA_TRANSFER: 92 lcp -> lcd_input_window = (lcp -> lcd_input_window + 1) % MODULUS; 93 PR(xp) = lcp -> lcd_input_window; 94 lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 95 break; 96 97 case RNR + DATA_TRANSFER: 98 PR(xp) = lcp -> lcd_input_window; 99 lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 100 break; 101 102 case RESET + DATA_TRANSFER: 103 lcp -> lcd_reset_condition = TRUE; 104 break; 105 106 case RESET_CONF + DATA_TRANSFER: 107 lcp -> lcd_reset_condition = FALSE; 108 break; 109 110 /* 111 * A restart should be only generated internally. Therefore 112 * all logic for restart is in the pk_restart routine. 113 */ 114 case RESTART + READY: 115 lcp -> lcd_timer = pk_t20; 116 break; 117 118 /* 119 * Restarts are all handled internally. Therefore all the 120 * logic for the incoming restart packet is handled in the 121 * pk_input routine. 122 */ 123 case RESTART_CONF + READY: 124 break; 125 126 default: 127 m_freem (m); 128 return; 129 } 130 131 /* Trace the packet. */ 132 pk_trace (pkp -> pk_xcp, xp, "P-Out"); 133 134 /* Pass the packet on down to the link layer */ 135 (*pkp -> pk_output) (m, pkp -> pk_xcp); 136 } 137 } 138 139 /* 140 * This procedure returns the next packet to send or null. A 141 * packet is composed of one or more mbufs. 142 */ 143 144 struct mbuf * 145 nextpk (lcp) 146 struct pklcd *lcp; 147 { 148 register struct socket *so = lcp -> lcd_so; 149 register struct mbuf *m = 0, *n; 150 151 if (lcp -> lcd_template) { 152 m = dtom (lcp -> lcd_template); 153 lcp -> lcd_template = NULL; 154 } else { 155 if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition || 156 lcp -> lcd_reset_condition) 157 return (NULL); 158 159 if (so == 0) 160 return (NULL); 161 162 if ((m = so -> so_snd.sb_mb) == 0) 163 return (NULL); 164 165 n = m; 166 while (n) { 167 sbfree (&so -> so_snd, n); 168 #ifndef BSD4_3 169 if ((int) n -> m_act == 1) 170 break; 171 #endif 172 n = n -> m_next; 173 } 174 175 #ifdef BSD4_3 176 so->so_snd.sb_mb = m->m_act; 177 m->m_act = 0; 178 #else 179 if (n) { 180 so -> so_snd.sb_mb = n -> m_next; 181 n -> m_next = 0; 182 } 183 #endif 184 } 185 186 return (m); 187 } 188