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*56530Sbostic * @(#)pk_output.c 7.12 (Berkeley) 10/11/92 1341709Ssklower */ 1441592Ssklower 15*56530Sbostic #include <sys/param.h> 16*56530Sbostic #include <sys/systm.h> 17*56530Sbostic #include <sys/mbuf.h> 18*56530Sbostic #include <sys/socket.h> 19*56530Sbostic #include <sys/socketvar.h> 20*56530Sbostic #include <sys/protosw.h> 21*56530Sbostic #include <sys/errno.h> 2241592Ssklower 23*56530Sbostic #include <net/if.h> 2441592Ssklower 25*56530Sbostic #include <netccitt/x25.h> 26*56530Sbostic #include <netccitt/pk.h> 27*56530Sbostic #include <netccitt/pk_var.h> 2841592Ssklower 2950427Ssklower struct mbuf_cache pk_output_cache = {0 }, pk_input_cache; 3041592Ssklower struct mbuf *nextpk (); 3141592Ssklower 3241592Ssklower pk_output (lcp) 3341592Ssklower register struct pklcd *lcp; 3441592Ssklower { 3541592Ssklower register struct x25_packet *xp; 3641592Ssklower register struct mbuf *m; 3741592Ssklower register struct pkcb *pkp = lcp -> lcd_pkp; 3841592Ssklower 3941592Ssklower if (lcp == 0 || pkp == 0) { 4041592Ssklower printf ("pk_output: zero arg\n"); 4141592Ssklower return; 4241592Ssklower } 4341592Ssklower 4441592Ssklower while ((m = nextpk (lcp)) != NULL) { 4541592Ssklower xp = mtod (m, struct x25_packet *); 4641592Ssklower 4741592Ssklower switch (pk_decode (xp) + lcp -> lcd_state) { 4841592Ssklower /* 4941592Ssklower * All the work is already done - just set the state and 5041592Ssklower * pass to peer. 5141592Ssklower */ 5241592Ssklower case CALL + READY: 5341592Ssklower lcp -> lcd_state = SENT_CALL; 5441592Ssklower lcp -> lcd_timer = pk_t21; 5541592Ssklower break; 5641592Ssklower 5741592Ssklower /* 5841592Ssklower * Just set the state to allow packet to flow and send the 5941592Ssklower * confirmation. 6041592Ssklower */ 6141592Ssklower case CALL_ACCEPTED + RECEIVED_CALL: 6241592Ssklower lcp -> lcd_state = DATA_TRANSFER; 6341592Ssklower break; 6441592Ssklower 6541592Ssklower /* 6641592Ssklower * Just set the state. Keep the LCD around till the clear 6741592Ssklower * confirmation is returned. 6841592Ssklower */ 6941592Ssklower case CLEAR + RECEIVED_CALL: 7041592Ssklower case CLEAR + SENT_CALL: 7141592Ssklower case CLEAR + DATA_TRANSFER: 7241592Ssklower lcp -> lcd_state = SENT_CLEAR; 7341592Ssklower lcp -> lcd_retry = 0; 7441592Ssklower /* fall through */ 7541592Ssklower 7641592Ssklower case CLEAR + SENT_CLEAR: 7741592Ssklower lcp -> lcd_timer = pk_t23; 7841592Ssklower lcp -> lcd_retry++; 7941592Ssklower break; 8041592Ssklower 8141592Ssklower case CLEAR_CONF + RECEIVED_CLEAR: 8241592Ssklower case CLEAR_CONF + SENT_CLEAR: 8341592Ssklower case CLEAR_CONF + READY: 8441592Ssklower lcp -> lcd_state = READY; 8541592Ssklower break; 8641592Ssklower 8741592Ssklower case DATA + DATA_TRANSFER: 8841592Ssklower PS(xp) = lcp -> lcd_ssn; 8949931Ssklower lcp -> lcd_input_window = 9049931Ssklower (lcp -> lcd_rsn + 1) % MODULUS; 9141592Ssklower PR(xp) = lcp -> lcd_input_window; 9241592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 9341592Ssklower lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS; 9447269Ssklower if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS)) 9541592Ssklower lcp -> lcd_window_condition = TRUE; 9641592Ssklower break; 9741592Ssklower 9841592Ssklower case INTERRUPT + DATA_TRANSFER: 9945895Ssklower #ifdef ancient_history 10041592Ssklower xp -> packet_data = 0; 10145895Ssklower #endif 10241592Ssklower lcp -> lcd_intrconf_pending = TRUE; 10341592Ssklower break; 10441592Ssklower 10541592Ssklower case INTERRUPT_CONF + DATA_TRANSFER: 10641592Ssklower break; 10741592Ssklower 10841592Ssklower case RR + DATA_TRANSFER: 10941592Ssklower case RNR + DATA_TRANSFER: 11049931Ssklower lcp -> lcd_input_window = 11149931Ssklower (lcp -> lcd_rsn + 1) % MODULUS; 11241592Ssklower PR(xp) = lcp -> lcd_input_window; 11341592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 11441592Ssklower break; 11541592Ssklower 11641592Ssklower case RESET + DATA_TRANSFER: 11741592Ssklower lcp -> lcd_reset_condition = TRUE; 11841592Ssklower break; 11941592Ssklower 12041592Ssklower case RESET_CONF + DATA_TRANSFER: 12141592Ssklower lcp -> lcd_reset_condition = FALSE; 12241592Ssklower break; 12341592Ssklower 12441592Ssklower /* 12541592Ssklower * A restart should be only generated internally. Therefore 12641592Ssklower * all logic for restart is in the pk_restart routine. 12741592Ssklower */ 12841592Ssklower case RESTART + READY: 12941592Ssklower lcp -> lcd_timer = pk_t20; 13041592Ssklower break; 13141592Ssklower 13241592Ssklower /* 13341592Ssklower * Restarts are all handled internally. Therefore all the 13441592Ssklower * logic for the incoming restart packet is handled in the 13541592Ssklower * pk_input routine. 13641592Ssklower */ 13741592Ssklower case RESTART_CONF + READY: 13841592Ssklower break; 13941592Ssklower 14041592Ssklower default: 14141592Ssklower m_freem (m); 14241592Ssklower return; 14341592Ssklower } 14441592Ssklower 14541592Ssklower /* Trace the packet. */ 14645895Ssklower pk_trace (pkp -> pk_xcp, m, "P-Out"); 14741592Ssklower 14841592Ssklower /* Pass the packet on down to the link layer */ 14950427Ssklower if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) { 15050427Ssklower m->m_flags |= 0x08; 15150427Ssklower mbuf_cache(&pk_input_cache, m); 15250427Ssklower } 15345297Ssklower (*pkp -> pk_lloutput) (pkp -> pk_llnext, m); 15441592Ssklower } 15541592Ssklower } 15641592Ssklower 15741592Ssklower /* 15841592Ssklower * This procedure returns the next packet to send or null. A 15941592Ssklower * packet is composed of one or more mbufs. 16041592Ssklower */ 16141592Ssklower 16241592Ssklower struct mbuf * 16341592Ssklower nextpk (lcp) 16441592Ssklower struct pklcd *lcp; 16541592Ssklower { 16643361Ssklower register struct mbuf *m, *n; 16743361Ssklower struct socket *so = lcp -> lcd_so; 16843361Ssklower register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb); 16941592Ssklower 17041592Ssklower if (lcp -> lcd_template) { 17145895Ssklower m = lcp -> lcd_template; 17241592Ssklower lcp -> lcd_template = NULL; 17341592Ssklower } else { 17441592Ssklower if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition || 17541592Ssklower lcp -> lcd_reset_condition) 17641592Ssklower return (NULL); 17741592Ssklower 17843361Ssklower if ((m = sb -> sb_mb) == 0) 17941592Ssklower return (NULL); 18041592Ssklower 18143361Ssklower sb -> sb_mb = m -> m_nextpkt; 18241592Ssklower m->m_act = 0; 18343361Ssklower for (n = m; n; n = n -> m_next) 18443361Ssklower sbfree (sb, n); 18541592Ssklower } 18641592Ssklower return (m); 18741592Ssklower } 188