141709Ssklower /* 241709Ssklower * Copyright (c) University of British Columbia, 1984 341709Ssklower * Copyright (c) 1990 The Regents of the University of California. 441709Ssklower * All rights reserved. 541709Ssklower * 641709Ssklower * This code is derived from software contributed to Berkeley by 741709Ssklower * the Laboratory for Computation Vision and the Computer Science Department 841709Ssklower * of the University of British Columbia. 941709Ssklower * 1041709Ssklower * %sccs.include.redist.c% 1141709Ssklower * 12*43361Ssklower * @(#)pk_output.c 7.4 (Berkeley) 06/21/90 1341709Ssklower */ 1441592Ssklower 1541592Ssklower #include "../h/param.h" 1641592Ssklower #include "../h/systm.h" 1741592Ssklower #include "../h/mbuf.h" 1841592Ssklower #include "../h/socket.h" 1941592Ssklower #include "../h/socketvar.h" 2041592Ssklower #include "../h/protosw.h" 2141592Ssklower #include "../h/errno.h" 2241592Ssklower 2341592Ssklower #include "../net/if.h" 2441592Ssklower 2541592Ssklower #include "../netccitt/pk.h" 2641592Ssklower #include "../netccitt/pk_var.h" 2741592Ssklower #include "../netccitt/x25.h" 2841592Ssklower 2941592Ssklower struct mbuf *nextpk (); 3041592Ssklower 3141592Ssklower pk_output (lcp) 3241592Ssklower register struct pklcd *lcp; 3341592Ssklower { 3441592Ssklower register struct x25_packet *xp; 3541592Ssklower register struct mbuf *m; 3641592Ssklower register struct pkcb *pkp = lcp -> lcd_pkp; 3741592Ssklower 3841592Ssklower if (lcp == 0 || pkp == 0) { 3941592Ssklower printf ("pk_output: zero arg\n"); 4041592Ssklower return; 4141592Ssklower } 4241592Ssklower 4341592Ssklower while ((m = nextpk (lcp)) != NULL) { 4441592Ssklower xp = mtod (m, struct x25_packet *); 4541592Ssklower 4641592Ssklower switch (pk_decode (xp) + lcp -> lcd_state) { 4741592Ssklower /* 4841592Ssklower * All the work is already done - just set the state and 4941592Ssklower * pass to peer. 5041592Ssklower */ 5141592Ssklower case CALL + READY: 5241592Ssklower lcp -> lcd_state = SENT_CALL; 5341592Ssklower lcp -> lcd_timer = pk_t21; 5441592Ssklower break; 5541592Ssklower 5641592Ssklower /* 5741592Ssklower * Just set the state to allow packet to flow and send the 5841592Ssklower * confirmation. 5941592Ssklower */ 6041592Ssklower case CALL_ACCEPTED + RECEIVED_CALL: 6141592Ssklower lcp -> lcd_state = DATA_TRANSFER; 6241592Ssklower break; 6341592Ssklower 6441592Ssklower /* 6541592Ssklower * Just set the state. Keep the LCD around till the clear 6641592Ssklower * confirmation is returned. 6741592Ssklower */ 6841592Ssklower case CLEAR + RECEIVED_CALL: 6941592Ssklower case CLEAR + SENT_CALL: 7041592Ssklower case CLEAR + DATA_TRANSFER: 7141592Ssklower lcp -> lcd_state = SENT_CLEAR; 7241592Ssklower lcp -> lcd_retry = 0; 7341592Ssklower /* fall through */ 7441592Ssklower 7541592Ssklower case CLEAR + SENT_CLEAR: 7641592Ssklower lcp -> lcd_timer = pk_t23; 7741592Ssklower lcp -> lcd_retry++; 7841592Ssklower break; 7941592Ssklower 8041592Ssklower case CLEAR_CONF + RECEIVED_CLEAR: 8141592Ssklower case CLEAR_CONF + SENT_CLEAR: 8241592Ssklower case CLEAR_CONF + READY: 8341592Ssklower lcp -> lcd_state = READY; 8441592Ssklower break; 8541592Ssklower 8641592Ssklower case DATA + DATA_TRANSFER: 8741592Ssklower PS(xp) = lcp -> lcd_ssn; 8841592Ssklower PR(xp) = lcp -> lcd_input_window; 8941592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 9041592Ssklower lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS; 9141592Ssklower if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + pkp->pk_xcp->xc_pwsize) % MODULUS)) 9241592Ssklower lcp -> lcd_window_condition = TRUE; 9341592Ssklower break; 9441592Ssklower 9541592Ssklower case INTERRUPT + DATA_TRANSFER: 9641592Ssklower xp -> packet_data = 0; 9741592Ssklower lcp -> lcd_intrconf_pending = TRUE; 9841592Ssklower break; 9941592Ssklower 10041592Ssklower case INTERRUPT_CONF + DATA_TRANSFER: 10141592Ssklower break; 10241592Ssklower 10341592Ssklower case RR + DATA_TRANSFER: 10441592Ssklower lcp -> lcd_input_window = (lcp -> lcd_input_window + 1) % MODULUS; 10541592Ssklower PR(xp) = lcp -> lcd_input_window; 10641592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 10741592Ssklower break; 10841592Ssklower 10941592Ssklower case RNR + DATA_TRANSFER: 11041592Ssklower PR(xp) = lcp -> lcd_input_window; 11141592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 11241592Ssklower break; 11341592Ssklower 11441592Ssklower case RESET + DATA_TRANSFER: 11541592Ssklower lcp -> lcd_reset_condition = TRUE; 11641592Ssklower break; 11741592Ssklower 11841592Ssklower case RESET_CONF + DATA_TRANSFER: 11941592Ssklower lcp -> lcd_reset_condition = FALSE; 12041592Ssklower break; 12141592Ssklower 12241592Ssklower /* 12341592Ssklower * A restart should be only generated internally. Therefore 12441592Ssklower * all logic for restart is in the pk_restart routine. 12541592Ssklower */ 12641592Ssklower case RESTART + READY: 12741592Ssklower lcp -> lcd_timer = pk_t20; 12841592Ssklower break; 12941592Ssklower 13041592Ssklower /* 13141592Ssklower * Restarts are all handled internally. Therefore all the 13241592Ssklower * logic for the incoming restart packet is handled in the 13341592Ssklower * pk_input routine. 13441592Ssklower */ 13541592Ssklower case RESTART_CONF + READY: 13641592Ssklower break; 13741592Ssklower 13841592Ssklower default: 13941592Ssklower m_freem (m); 14041592Ssklower return; 14141592Ssklower } 14241592Ssklower 14341592Ssklower /* Trace the packet. */ 14441592Ssklower pk_trace (pkp -> pk_xcp, xp, "P-Out"); 14541592Ssklower 14641592Ssklower /* Pass the packet on down to the link layer */ 147*43361Ssklower (*pkp -> pk_lloutput) (m, pkp -> llnext); 14841592Ssklower } 14941592Ssklower } 15041592Ssklower 15141592Ssklower /* 15241592Ssklower * This procedure returns the next packet to send or null. A 15341592Ssklower * packet is composed of one or more mbufs. 15441592Ssklower */ 15541592Ssklower 15641592Ssklower struct mbuf * 15741592Ssklower nextpk (lcp) 15841592Ssklower struct pklcd *lcp; 15941592Ssklower { 160*43361Ssklower register struct mbuf *m, *n; 161*43361Ssklower struct socket *so = lcp -> lcd_so; 162*43361Ssklower register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb); 16341592Ssklower 16441592Ssklower if (lcp -> lcd_template) { 16541592Ssklower m = dtom (lcp -> lcd_template); 16641592Ssklower lcp -> lcd_template = NULL; 16741592Ssklower } else { 16841592Ssklower if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition || 16941592Ssklower lcp -> lcd_reset_condition) 17041592Ssklower return (NULL); 17141592Ssklower 172*43361Ssklower if ((m = sb -> sb_mb) == 0) 17341592Ssklower return (NULL); 17441592Ssklower 175*43361Ssklower sb -> sb_mb = m -> m_nextpkt; 17641592Ssklower m->m_act = 0; 177*43361Ssklower for (n = m; n; n = n -> m_next) 178*43361Ssklower sbfree (sb, n); 17941592Ssklower } 18041592Ssklower return (m); 18141592Ssklower } 182