141709Ssklower /* 241709Ssklower * Copyright (c) University of British Columbia, 1984 357024Ssklower * Copyright (C) Computer Science Department IV, 457024Ssklower * University of Erlangen-Nuremberg, Germany, 1992 5*63216Sbostic * Copyright (c) 1991, 1992, 1993 6*63216Sbostic * The Regents of the University of California. All rights reserved. 741709Ssklower * 857024Ssklower * This code is derived from software contributed to Berkeley by the 957024Ssklower * Laboratory for Computation Vision and the Computer Science Department 1057024Ssklower * of the the University of British Columbia and the Computer Science 1157024Ssklower * Department (IV) of the University of Erlangen-Nuremberg, Germany. 1241709Ssklower * 1341709Ssklower * %sccs.include.redist.c% 1441709Ssklower * 15*63216Sbostic * @(#)pk_output.c 8.1 (Berkeley) 06/10/93 1641709Ssklower */ 1741592Ssklower 1856530Sbostic #include <sys/param.h> 1956530Sbostic #include <sys/systm.h> 2056530Sbostic #include <sys/mbuf.h> 2156530Sbostic #include <sys/socket.h> 2256530Sbostic #include <sys/socketvar.h> 2356530Sbostic #include <sys/protosw.h> 2456530Sbostic #include <sys/errno.h> 2541592Ssklower 2656530Sbostic #include <net/if.h> 2741592Ssklower 2856530Sbostic #include <netccitt/x25.h> 2956530Sbostic #include <netccitt/pk.h> 3056530Sbostic #include <netccitt/pk_var.h> 3141592Ssklower 3250427Ssklower struct mbuf_cache pk_output_cache = {0 }, pk_input_cache; 3341592Ssklower struct mbuf *nextpk (); 3441592Ssklower 3541592Ssklower pk_output (lcp) 3641592Ssklower register struct pklcd *lcp; 3741592Ssklower { 3841592Ssklower register struct x25_packet *xp; 3941592Ssklower register struct mbuf *m; 4041592Ssklower register struct pkcb *pkp = lcp -> lcd_pkp; 4141592Ssklower 4241592Ssklower if (lcp == 0 || pkp == 0) { 4341592Ssklower printf ("pk_output: zero arg\n"); 4441592Ssklower return; 4541592Ssklower } 4641592Ssklower 4741592Ssklower while ((m = nextpk (lcp)) != NULL) { 4841592Ssklower xp = mtod (m, struct x25_packet *); 4941592Ssklower 5041592Ssklower switch (pk_decode (xp) + lcp -> lcd_state) { 5141592Ssklower /* 5241592Ssklower * All the work is already done - just set the state and 5341592Ssklower * pass to peer. 5441592Ssklower */ 5541592Ssklower case CALL + READY: 5641592Ssklower lcp -> lcd_state = SENT_CALL; 5741592Ssklower lcp -> lcd_timer = pk_t21; 5841592Ssklower break; 5941592Ssklower 6041592Ssklower /* 6141592Ssklower * Just set the state to allow packet to flow and send the 6241592Ssklower * confirmation. 6341592Ssklower */ 6441592Ssklower case CALL_ACCEPTED + RECEIVED_CALL: 6541592Ssklower lcp -> lcd_state = DATA_TRANSFER; 6641592Ssklower break; 6741592Ssklower 6841592Ssklower /* 6941592Ssklower * Just set the state. Keep the LCD around till the clear 7041592Ssklower * confirmation is returned. 7141592Ssklower */ 7241592Ssklower case CLEAR + RECEIVED_CALL: 7341592Ssklower case CLEAR + SENT_CALL: 7441592Ssklower case CLEAR + DATA_TRANSFER: 7541592Ssklower lcp -> lcd_state = SENT_CLEAR; 7641592Ssklower lcp -> lcd_retry = 0; 7741592Ssklower /* fall through */ 7841592Ssklower 7941592Ssklower case CLEAR + SENT_CLEAR: 8041592Ssklower lcp -> lcd_timer = pk_t23; 8141592Ssklower lcp -> lcd_retry++; 8241592Ssklower break; 8341592Ssklower 8441592Ssklower case CLEAR_CONF + RECEIVED_CLEAR: 8541592Ssklower case CLEAR_CONF + SENT_CLEAR: 8641592Ssklower case CLEAR_CONF + READY: 8741592Ssklower lcp -> lcd_state = READY; 8841592Ssklower break; 8941592Ssklower 9041592Ssklower case DATA + DATA_TRANSFER: 9157024Ssklower SPS(xp, lcp -> lcd_ssn); 9249931Ssklower lcp -> lcd_input_window = 9349931Ssklower (lcp -> lcd_rsn + 1) % MODULUS; 9457024Ssklower SPR(xp, lcp -> lcd_input_window); 9541592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 9641592Ssklower lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS; 9747269Ssklower if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS)) 9841592Ssklower lcp -> lcd_window_condition = TRUE; 9941592Ssklower break; 10041592Ssklower 10141592Ssklower case INTERRUPT + DATA_TRANSFER: 10245895Ssklower #ifdef ancient_history 10341592Ssklower xp -> packet_data = 0; 10445895Ssklower #endif 10541592Ssklower lcp -> lcd_intrconf_pending = TRUE; 10641592Ssklower break; 10741592Ssklower 10841592Ssklower case INTERRUPT_CONF + DATA_TRANSFER: 10941592Ssklower break; 11041592Ssklower 11141592Ssklower case RR + DATA_TRANSFER: 11241592Ssklower case RNR + DATA_TRANSFER: 11349931Ssklower lcp -> lcd_input_window = 11449931Ssklower (lcp -> lcd_rsn + 1) % MODULUS; 11557024Ssklower SPR(xp, lcp -> lcd_input_window); 11641592Ssklower lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window; 11741592Ssklower break; 11841592Ssklower 11941592Ssklower case RESET + DATA_TRANSFER: 12041592Ssklower lcp -> lcd_reset_condition = TRUE; 12141592Ssklower break; 12241592Ssklower 12341592Ssklower case RESET_CONF + DATA_TRANSFER: 12441592Ssklower lcp -> lcd_reset_condition = FALSE; 12541592Ssklower break; 12641592Ssklower 12741592Ssklower /* 12841592Ssklower * A restart should be only generated internally. Therefore 12941592Ssklower * all logic for restart is in the pk_restart routine. 13041592Ssklower */ 13141592Ssklower case RESTART + READY: 13241592Ssklower lcp -> lcd_timer = pk_t20; 13341592Ssklower break; 13441592Ssklower 13541592Ssklower /* 13641592Ssklower * Restarts are all handled internally. Therefore all the 13741592Ssklower * logic for the incoming restart packet is handled in the 13841592Ssklower * pk_input routine. 13941592Ssklower */ 14041592Ssklower case RESTART_CONF + READY: 14141592Ssklower break; 14241592Ssklower 14341592Ssklower default: 14441592Ssklower m_freem (m); 14541592Ssklower return; 14641592Ssklower } 14741592Ssklower 14841592Ssklower /* Trace the packet. */ 14945895Ssklower pk_trace (pkp -> pk_xcp, m, "P-Out"); 15041592Ssklower 15141592Ssklower /* Pass the packet on down to the link layer */ 15250427Ssklower if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) { 15350427Ssklower m->m_flags |= 0x08; 15450427Ssklower mbuf_cache(&pk_input_cache, m); 15550427Ssklower } 15657024Ssklower (*pkp -> pk_lloutput) (pkp -> pk_llnext, m, pkp -> pk_rt); 15741592Ssklower } 15841592Ssklower } 15941592Ssklower 16041592Ssklower /* 16141592Ssklower * This procedure returns the next packet to send or null. A 16241592Ssklower * packet is composed of one or more mbufs. 16341592Ssklower */ 16441592Ssklower 16541592Ssklower struct mbuf * 16641592Ssklower nextpk (lcp) 16741592Ssklower struct pklcd *lcp; 16841592Ssklower { 16943361Ssklower register struct mbuf *m, *n; 17043361Ssklower struct socket *so = lcp -> lcd_so; 17143361Ssklower register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb); 17241592Ssklower 17341592Ssklower if (lcp -> lcd_template) { 17445895Ssklower m = lcp -> lcd_template; 17541592Ssklower lcp -> lcd_template = NULL; 17641592Ssklower } else { 17741592Ssklower if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition || 17841592Ssklower lcp -> lcd_reset_condition) 17941592Ssklower return (NULL); 18041592Ssklower 18143361Ssklower if ((m = sb -> sb_mb) == 0) 18241592Ssklower return (NULL); 18341592Ssklower 18443361Ssklower sb -> sb_mb = m -> m_nextpkt; 18541592Ssklower m->m_act = 0; 18643361Ssklower for (n = m; n; n = n -> m_next) 18743361Ssklower sbfree (sb, n); 18841592Ssklower } 18941592Ssklower return (m); 19041592Ssklower } 191