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*49747Ssklower * @(#)pk_subr.c 7.14 (Berkeley) 05/16/91 1341709Ssklower */ 1441593Ssklower 1542140Ssklower #include "param.h" 1642140Ssklower #include "systm.h" 1742140Ssklower #include "mbuf.h" 1842140Ssklower #include "socket.h" 1942140Ssklower #include "protosw.h" 2042140Ssklower #include "socketvar.h" 2142140Ssklower #include "errno.h" 2242140Ssklower #include "time.h" 2342140Ssklower #include "kernel.h" 2441593Ssklower 2542277Ssklower #include "../net/if.h" 2642277Ssklower 2742140Ssklower #include "x25.h" 2842140Ssklower #include "pk.h" 2942140Ssklower #include "pk_var.h" 3042140Ssklower #include "x25err.h" 3141593Ssklower 3241593Ssklower int pk_sendspace = 1024 * 2 + 8; 3341593Ssklower int pk_recvspace = 1024 * 2 + 8; 3441593Ssklower 3547271Ssklower struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q}; 3647271Ssklower 3741593Ssklower /* 3841593Ssklower * Attach X.25 protocol to socket, allocate logical channel descripter 3941593Ssklower * and buffer space, and enter LISTEN state if we are to accept 4041593Ssklower * IN-COMMING CALL packets. 4141593Ssklower * 4241593Ssklower */ 4341593Ssklower 4442277Ssklower struct pklcd * 4541593Ssklower pk_attach (so) 4641593Ssklower struct socket *so; 4741593Ssklower { 4841593Ssklower register struct pklcd *lcp; 4942277Ssklower register int error = ENOBUFS; 5049018Ssklower int pk_output(); 5141593Ssklower 5247271Ssklower MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT); 5342277Ssklower if (lcp) { 5447271Ssklower bzero ((caddr_t)lcp, sizeof (*lcp)); 5547271Ssklower insque (&lcp -> lcd_q, &pklcd_q); 5649595Ssklower lcp -> lcd_state = READY; 5749595Ssklower lcp -> lcd_send = pk_output; 5842277Ssklower if (so) { 5942277Ssklower error = soreserve (so, pk_sendspace, pk_recvspace); 6042277Ssklower lcp -> lcd_so = so; 6142277Ssklower if (so -> so_options & SO_ACCEPTCONN) 6242277Ssklower lcp -> lcd_state = LISTEN; 6343361Ssklower } else 6445165Ssklower sbreserve (&lcp -> lcd_sb, pk_sendspace); 6542277Ssklower } 6642277Ssklower if (so) { 6742277Ssklower so -> so_pcb = (caddr_t) lcp; 6842277Ssklower so -> so_error = error; 6942277Ssklower } 7042277Ssklower return (lcp); 7141593Ssklower } 7241593Ssklower 7341593Ssklower /* 7441593Ssklower * Disconnect X.25 protocol from socket. 7541593Ssklower */ 7641593Ssklower 7741593Ssklower pk_disconnect (lcp) 7841593Ssklower register struct pklcd *lcp; 7941593Ssklower { 8041593Ssklower register struct socket *so = lcp -> lcd_so; 8141593Ssklower register struct pklcd *l, *p; 8241593Ssklower 8341593Ssklower switch (lcp -> lcd_state) { 8441593Ssklower case LISTEN: 8541593Ssklower for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 8641593Ssklower if (p == 0) { 8741593Ssklower if (l != 0) 8841593Ssklower pk_listenhead = l -> lcd_listen; 8941593Ssklower } 9041593Ssklower else 9141593Ssklower if (l != 0) 9241593Ssklower p -> lcd_listen = l -> lcd_listen; 9341593Ssklower pk_close (lcp); 9441593Ssklower break; 9541593Ssklower 9641593Ssklower case READY: 9741593Ssklower pk_acct (lcp); 9841593Ssklower pk_close (lcp); 9941593Ssklower break; 10041593Ssklower 10141593Ssklower case SENT_CLEAR: 10241593Ssklower case RECEIVED_CLEAR: 10341593Ssklower break; 10441593Ssklower 10541593Ssklower default: 10641593Ssklower pk_acct (lcp); 10742140Ssklower if (so) { 10842140Ssklower soisdisconnecting (so); 10942140Ssklower sbflush (&so -> so_rcv); 11042140Ssklower } 11145895Ssklower pk_clear (lcp, 241, 0); /* Normal Disconnect */ 11241593Ssklower 11341593Ssklower } 11441593Ssklower } 11541593Ssklower 11641593Ssklower /* 11741593Ssklower * Close an X.25 Logical Channel. Discard all space held by the 11841593Ssklower * connection and internal descriptors. Wake up any sleepers. 11941593Ssklower */ 12041593Ssklower 12141593Ssklower pk_close (lcp) 12241593Ssklower struct pklcd *lcp; 12341593Ssklower { 12441593Ssklower register struct socket *so = lcp -> lcd_so; 12541593Ssklower 12641593Ssklower pk_freelcd (lcp); 12741593Ssklower 12841593Ssklower if (so == NULL) 12941593Ssklower return; 13041593Ssklower 13141593Ssklower so -> so_pcb = 0; 13241593Ssklower soisdisconnected (so); 13345895Ssklower /* sofree (so); /* gak!!! you can't do that here */ 13441593Ssklower } 13541593Ssklower 13641593Ssklower /* 13741593Ssklower * Create a template to be used to send X.25 packets on a logical 13841593Ssklower * channel. It allocates an mbuf and fills in a skeletal packet 13941593Ssklower * depending on its type. This packet is passed to pk_output where 14041593Ssklower * the remainer of the packet is filled in. 14141593Ssklower */ 14241593Ssklower 14345895Ssklower struct mbuf * 14441593Ssklower pk_template (lcn, type) 14541593Ssklower int lcn, type; 14641593Ssklower { 14741593Ssklower register struct mbuf *m; 14841593Ssklower register struct x25_packet *xp; 14941593Ssklower 15045297Ssklower MGETHDR (m, M_DONTWAIT, MT_HEADER); 15141593Ssklower if (m == 0) 15241593Ssklower panic ("pk_template"); 15341593Ssklower m -> m_act = 0; 15441593Ssklower 15541593Ssklower /* 15641593Ssklower * Efficiency hack: leave a four byte gap at the beginning 15741593Ssklower * of the packet level header with the hope that this will 15841593Ssklower * be enough room for the link level to insert its header. 15941593Ssklower */ 16045297Ssklower m -> m_data += max_linkhdr; 16149595Ssklower m -> m_pkthdr.len = m -> m_len = PKHEADERLN; 16241593Ssklower 16341593Ssklower xp = mtod (m, struct x25_packet *); 16441593Ssklower *(long *)xp = 0; /* ugly, but fast */ 16541593Ssklower /* xp -> q_bit = 0;*/ 16641593Ssklower xp -> fmt_identifier = 1; 16741593Ssklower /* xp -> lc_group_number = 0;*/ 16841593Ssklower 16945574Ssklower SET_LCN(xp, lcn); 17041593Ssklower xp -> packet_type = type; 17141593Ssklower 17245895Ssklower return (m); 17341593Ssklower } 17441593Ssklower 17541593Ssklower /* 17641593Ssklower * This routine restarts all the virtual circuits. Actually, 17741593Ssklower * the virtual circuits are not "restarted" as such. Instead, 17841593Ssklower * any active switched circuit is simply returned to READY 17941593Ssklower * state. 18041593Ssklower */ 18141593Ssklower 18241593Ssklower pk_restart (pkp, restart_cause) 18341593Ssklower register struct pkcb *pkp; 18441593Ssklower int restart_cause; 18541593Ssklower { 18645895Ssklower register struct mbuf *m; 18741593Ssklower register struct pklcd *lcp; 18841593Ssklower register int i; 18941593Ssklower 19041593Ssklower /* Restart all logical channels. */ 19145297Ssklower if (pkp -> pk_chan == 0) 19242140Ssklower return; 19345297Ssklower for (i = 1; i <= pkp -> pk_maxlcn; ++i) 19445297Ssklower if ((lcp = pkp -> pk_chan[i]) != NULL) { 19545895Ssklower if (lcp -> lcd_so) { 19645297Ssklower lcp -> lcd_so -> so_error = ENETRESET; 19745895Ssklower pk_close (lcp); 19845895Ssklower } else { 19945895Ssklower pk_flush (lcp); 20045895Ssklower lcp -> lcd_state = READY; 20145895Ssklower if (lcp -> lcd_upper) 20247271Ssklower lcp -> lcd_upper (lcp, 0); 20345895Ssklower } 20441593Ssklower } 20541593Ssklower 20641593Ssklower if (restart_cause < 0) 20741593Ssklower return; 20841593Ssklower 20945297Ssklower pkp -> pk_state = DTE_SENT_RESTART; 21045297Ssklower lcp = pkp -> pk_chan[0]; 21145895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 21249595Ssklower m -> m_pkthdr.len = m -> m_len += 2; 21347271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; /* DTE only */ 21447271Ssklower mtod (m, octet *)[4] = restart_cause; 21541593Ssklower pk_output (lcp); 21641593Ssklower } 21741593Ssklower 21841593Ssklower 21941593Ssklower /* 22041593Ssklower * This procedure frees up the Logical Channel Descripter. 22141593Ssklower */ 22241593Ssklower 22341593Ssklower pk_freelcd (lcp) 22441593Ssklower register struct pklcd *lcp; 22541593Ssklower { 22641593Ssklower if (lcp == NULL) 22741593Ssklower return; 22841593Ssklower 22941593Ssklower if (lcp -> lcd_lcn > 0) 23041593Ssklower lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 23141593Ssklower 23247271Ssklower pk_flush (lcp); 23347271Ssklower remque (&lcp -> lcd_q); 23447271Ssklower free ((caddr_t)lcp, M_PCB); 23541593Ssklower } 23641593Ssklower 23741593Ssklower 23841593Ssklower /* 23941593Ssklower * Bind a address and protocol value to a socket. The important 24041593Ssklower * part is the protocol value - the first four characters of the 24141593Ssklower * Call User Data field. 24241593Ssklower */ 24341593Ssklower 24441593Ssklower pk_bind (lcp, nam) 24541593Ssklower struct pklcd *lcp; 24641593Ssklower struct mbuf *nam; 24741593Ssklower { 24841593Ssklower register struct pkcb *pkp; 24941593Ssklower register struct pklcd *pp; 25042277Ssklower register struct sockaddr_x25 *sa; 25141593Ssklower 25241593Ssklower if (nam == NULL) 25341593Ssklower return (EADDRNOTAVAIL); 25441593Ssklower if (lcp -> lcd_ceaddr) /* XXX */ 25541593Ssklower return (EADDRINUSE); 25645895Ssklower if (pk_checksockaddr (nam)) 25741593Ssklower return (EINVAL); 25841593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 25941593Ssklower 26041593Ssklower /* 26141593Ssklower * If the user wishes to accept calls only from a particular 26241593Ssklower * net (net != 0), make sure the net is known 26341593Ssklower */ 26441593Ssklower 26541593Ssklower if (sa -> x25_net) 26641593Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 26741593Ssklower if (pkp == 0) 26841593Ssklower return (ENETUNREACH); 26945165Ssklower if (pkp -> pk_xcp -> xc_addr.x25_net == sa -> x25_net) 27041593Ssklower break; 27141593Ssklower } 27241593Ssklower 27345895Ssklower /* 27445895Ssklower * For ISO's sake permit default listeners, but only one such . . . 27545895Ssklower */ 27645895Ssklower for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) { 27745895Ssklower register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr; 27845895Ssklower if ((sa2 -> x25_udlen == sa -> x25_udlen) && 27945895Ssklower (sa2 -> x25_udlen == 0 || 28045895Ssklower (bcmp (sa2 -> x25_udata, sa -> x25_udata, 28145895Ssklower min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0))) 28245895Ssklower return (EADDRINUSE); 28345895Ssklower } 28442277Ssklower lcp -> lcd_laddr = *sa; 28542277Ssklower lcp -> lcd_ceaddr = &lcp -> lcd_laddr; 28641593Ssklower return (0); 28741593Ssklower } 28841593Ssklower 28941593Ssklower /* 29045895Ssklower * Include a bound control block in the list of listeners. 29145895Ssklower */ 29245895Ssklower pk_listen (lcp) 29345895Ssklower register struct pklcd *lcp; 29445895Ssklower { 29545895Ssklower register struct pklcd **pp; 29645895Ssklower 29745895Ssklower if (lcp -> lcd_ceaddr == 0) 29845895Ssklower return (EDESTADDRREQ); 29945895Ssklower 30045895Ssklower lcp -> lcd_state = LISTEN; 30145895Ssklower /* 30245895Ssklower * Add default listener at end, any others at start. 30345895Ssklower */ 30445895Ssklower if (lcp -> lcd_ceaddr -> x25_udlen == 0) { 30545895Ssklower for (pp = &pk_listenhead; *pp; ) 30645895Ssklower pp = &((*pp) -> lcd_listen); 30745895Ssklower *pp = lcp; 30845895Ssklower } else { 30945895Ssklower lcp -> lcd_listen = pk_listenhead; 31045895Ssklower pk_listenhead = lcp; 31145895Ssklower } 31245895Ssklower return (0); 31345895Ssklower } 31445895Ssklower /* 31545895Ssklower * Include a listening control block for the benefit of other protocols. 31645895Ssklower */ 31745895Ssklower pk_protolisten (spi, spilen, callee) 31847271Ssklower int (*callee) (); 31945895Ssklower { 32045895Ssklower register struct pklcd *lcp = pk_attach ((struct socket *)0); 32145895Ssklower register struct mbuf *nam; 32245895Ssklower register struct sockaddr_x25 *sa; 32345895Ssklower int error = ENOBUFS; 32445895Ssklower 32545895Ssklower if (lcp) { 32647271Ssklower if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) { 32747271Ssklower sa = mtod (nam, struct sockaddr_x25 *); 32845895Ssklower sa -> x25_family = AF_CCITT; 32945895Ssklower sa -> x25_len = nam -> m_len = sizeof (*sa); 33045895Ssklower sa -> x25_udlen = spilen; 33145895Ssklower sa -> x25_udata[0] = spi; 33245895Ssklower lcp -> lcd_upper = callee; 33345895Ssklower lcp -> lcd_flags = X25_MBS_HOLD; 33445895Ssklower error = pk_bind (lcp, nam) || pk_listen (lcp); 33545895Ssklower (void) m_free (nam); 33645895Ssklower } 33745895Ssklower if (error) 33847271Ssklower pk_freelcd (lcp); 33945895Ssklower } 34045895Ssklower return error; /* Hopefully Zero !*/ 34145895Ssklower } 34245895Ssklower 34345895Ssklower /* 34441593Ssklower * Associate a logical channel descriptor with a network. 34541593Ssklower * Fill in the default network specific parameters and then 34641593Ssklower * set any parameters explicitly specified by the user or 34741593Ssklower * by the remote DTE. 34841593Ssklower */ 34941593Ssklower 35041593Ssklower pk_assoc (pkp, lcp, sa) 35141593Ssklower register struct pkcb *pkp; 35241593Ssklower register struct pklcd *lcp; 35341593Ssklower register struct sockaddr_x25 *sa; 35441593Ssklower { 35541593Ssklower 35641593Ssklower lcp -> lcd_pkp = pkp; 35741593Ssklower lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 35841593Ssklower lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 35941593Ssklower lcp -> lcd_rsn = MODULUS - 1; 36041593Ssklower pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 36141593Ssklower 36241593Ssklower if (sa -> x25_opts.op_psize) 36341593Ssklower lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 36441593Ssklower else 36541593Ssklower sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 36641593Ssklower if (sa -> x25_opts.op_wsize) 36741593Ssklower lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 36841593Ssklower else 36941593Ssklower sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 37045165Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net; 37141593Ssklower lcp -> lcd_flags = sa -> x25_opts.op_flags; 37241593Ssklower lcp -> lcd_stime = time.tv_sec; 37341593Ssklower } 37441593Ssklower 37545895Ssklower pk_connect (lcp, sa) 37641593Ssklower register struct pklcd *lcp; 37742277Ssklower register struct sockaddr_x25 *sa; 37841593Ssklower { 37941593Ssklower register struct pkcb *pkp; 38041593Ssklower 38141593Ssklower if (sa -> x25_addr[0] == '\0') 38241593Ssklower return (EDESTADDRREQ); 38345297Ssklower if (lcp -> lcd_pkp == 0) 38445297Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 38541593Ssklower if (pkp == 0) 38641593Ssklower return (ENETUNREACH); 38741593Ssklower /* 38841593Ssklower * use first net configured (last in list 38941593Ssklower * headed by pkcbhead) if net is zero 39041593Ssklower */ 39141593Ssklower if (sa -> x25_net == 0 && pkp -> pk_next == 0) 39241593Ssklower break; 39345165Ssklower if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_net) 39441593Ssklower break; 39541593Ssklower } 39641593Ssklower 39741593Ssklower if (pkp -> pk_state != DTE_READY) 39841593Ssklower return (ENETDOWN); 39941593Ssklower if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 40041593Ssklower return (EMFILE); 40142277Ssklower lcp -> lcd_faddr = *sa; 40245297Ssklower lcp -> lcd_ceaddr = & lcp -> lcd_faddr; 40341593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 40445165Ssklower if (lcp -> lcd_so) 40542140Ssklower soisconnecting (lcp -> lcd_so); 40641593Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 40742277Ssklower pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp); 40847271Ssklower return (*pkp -> pk_start) (lcp); 40941593Ssklower } 41041593Ssklower 411*49747Ssklower struct bcdinfo { 412*49747Ssklower octet *cp; 413*49747Ssklower unsigned posn; 414*49747Ssklower }; 41541593Ssklower /* 41641593Ssklower * Build the rest of the CALL REQUEST packet. Fill in calling 41741593Ssklower * address, facilities fields and the user data field. 41841593Ssklower */ 41941593Ssklower 42042277Ssklower pk_callrequest (lcp, sa, xcp) 42141593Ssklower struct pklcd *lcp; 42242277Ssklower register struct sockaddr_x25 *sa; 42341593Ssklower register struct x25config *xcp; 42441593Ssklower { 42541593Ssklower register struct x25_calladdr *a; 42645895Ssklower register struct mbuf *m = lcp -> lcd_template; 42747271Ssklower register struct x25_packet *xp = mtod (m, struct x25_packet *); 428*49747Ssklower struct bcdinfo b; 42941593Ssklower 43045574Ssklower if (lcp -> lcd_flags & X25_DBIT) 43145895Ssklower xp -> d_bit = 1; 43245895Ssklower a = (struct x25_calladdr *) &xp -> packet_data; 433*49747Ssklower b.cp = (octet *) a -> address_field; 434*49747Ssklower b.posn = 0; 435*49747Ssklower a -> called_addrlen = to_bcd (&b, sa, xcp); 436*49747Ssklower a -> calling_addrlen = to_bcd (&b, &xcp -> xc_addr, xcp); 437*49747Ssklower if (b.posn & 0x01) 438*49747Ssklower *b.cp++ &= 0xf0; 439*49747Ssklower m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a; 44041593Ssklower 44145895Ssklower if (lcp -> lcd_facilities) { 44247271Ssklower m -> m_pkthdr.len += 443*49747Ssklower (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len; 44445895Ssklower lcp -> lcd_facilities = 0; 44545895Ssklower } else 446*49747Ssklower pk_build_facilities (m, sa, (int)xcp -> xc_type); 44741593Ssklower 44847271Ssklower m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata); 44941593Ssklower } 45041593Ssklower 451*49747Ssklower pk_build_facilities (m, sa, type) 45245895Ssklower register struct mbuf *m; 45341593Ssklower struct sockaddr_x25 *sa; 45441593Ssklower { 45545895Ssklower register octet *cp; 45641593Ssklower register octet *fcp; 45741593Ssklower register int revcharge; 45841593Ssklower 45947271Ssklower cp = mtod (m, octet *) + m -> m_len; 46045895Ssklower fcp = cp + 1; 46141593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 46241593Ssklower /* 46341593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 46441593Ssklower * calls must have the "hi priority" bit on. 46541593Ssklower */ 46641593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 46741593Ssklower revcharge |= 02; 46841593Ssklower if (revcharge) { 46941593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 47041593Ssklower *fcp++ = revcharge; 47141593Ssklower } 47241593Ssklower switch (type) { 47341593Ssklower case X25_1980: 47441593Ssklower case X25_1984: 47541593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 47641593Ssklower *fcp++ = sa -> x25_opts.op_psize; 47741593Ssklower *fcp++ = sa -> x25_opts.op_psize; 47841593Ssklower 47941593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 48041593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 48141593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 48241593Ssklower } 48345895Ssklower *cp = fcp - cp - 1; 48445895Ssklower m -> m_pkthdr.len = (m -> m_len += *cp + 1); 48541593Ssklower } 48641593Ssklower 487*49747Ssklower to_bcd (b, sa, xcp) 488*49747Ssklower register struct bcdinfo *b; 489*49747Ssklower struct sockaddr_x25 *sa; 490*49747Ssklower register struct x25config *xcp; 49141593Ssklower { 492*49747Ssklower register char *x = sa -> x25_addr; 493*49747Ssklower unsigned start = b -> posn; 494*49747Ssklower /* 495*49747Ssklower * The nodnic and prepnd0 stuff looks tedious, 496*49747Ssklower * but it does allow full X.121 addresses to be used, 497*49747Ssklower * which is handy for routing info (& OSI type 37 addresses). 498*49747Ssklower */ 499*49747Ssklower if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) { 500*49747Ssklower char dnicname[sizeof(long) * NBBY/3 + 2]; 501*49747Ssklower register char *p = dnicname; 502*49747Ssklower 503*49747Ssklower sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff); 504*49747Ssklower for (; *p; p++) /* *p == 0 means dnic matched */ 505*49747Ssklower if ((*p ^ *x++) & 0x0f) 506*49747Ssklower break; 507*49747Ssklower if (*p || xcp -> xc_nodnic == 0) 508*49747Ssklower x = sa -> x25_addr; 509*49747Ssklower if (*p && xcp -> xc_prepnd0) { 510*49747Ssklower if ((b -> posn)++ & 0x01) 511*49747Ssklower *(b -> cp)++; 512*49747Ssklower else 513*49747Ssklower *(b -> cp) = 0; 514*49747Ssklower } 515*49747Ssklower } 516*49747Ssklower while (*x) 517*49747Ssklower if ((b -> posn)++ & 0x01) 518*49747Ssklower *(b -> cp)++ |= *x++ & 0x0F; 51941593Ssklower else 520*49747Ssklower *(b -> cp) = *x++ << 4; 521*49747Ssklower return ((b -> posn) - start); 52241593Ssklower } 52341593Ssklower 52441593Ssklower /* 52541593Ssklower * This routine gets the first available logical channel number. The 52641593Ssklower * search is from the highest number to lowest number (DTE). 52741593Ssklower */ 52841593Ssklower 52941593Ssklower pk_getlcn (pkp) 53041593Ssklower register struct pkcb *pkp; 53141593Ssklower { 53241593Ssklower register int i; 53341593Ssklower 53445297Ssklower if (pkp -> pk_chan == 0) 53542140Ssklower return (0); 53641593Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 53741593Ssklower if (pkp -> pk_chan[i] == NULL) 53841593Ssklower break; 53941593Ssklower return (i); 54041593Ssklower 54141593Ssklower } 54241593Ssklower 54341593Ssklower /* 54441593Ssklower * This procedure sends a CLEAR request packet. The lc state is 54541593Ssklower * set to "SENT_CLEAR". 54641593Ssklower */ 54741593Ssklower 54845895Ssklower pk_clear (lcp, diagnostic, abortive) 54945895Ssklower register struct pklcd *lcp; 55041593Ssklower { 55145895Ssklower register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR); 55241593Ssklower 55345895Ssklower m -> m_len += 2; 55447271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; 55547271Ssklower mtod (m, octet *)[4] = diagnostic; 55645895Ssklower if (lcp -> lcd_facilities) { 55745895Ssklower m -> m_next = lcp -> lcd_facilities; 55845895Ssklower m -> m_pkthdr.len += m -> m_next -> m_len; 55945895Ssklower lcp -> lcd_facilities = 0; 56045895Ssklower } 56145895Ssklower if (abortive) 56245895Ssklower lcp -> lcd_template = m; 56345895Ssklower else { 56445895Ssklower struct socket *so = lcp -> lcd_so; 56545895Ssklower struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb; 56647271Ssklower sbappendrecord (sb, m); 56745895Ssklower } 56841593Ssklower pk_output (lcp); 56941593Ssklower 57041593Ssklower } 57141593Ssklower 57247271Ssklower /* 57347271Ssklower * This procedure generates RNR's or RR's to inhibit or enable 57447271Ssklower * inward data flow, if the current state changes (blocked ==> open or 57547271Ssklower * vice versa), or if forced to generate one. One forces RNR's to ack data. 57647271Ssklower */ 57747271Ssklower pk_flowcontrol (lcp, inhibit, forced) 57847271Ssklower register struct pklcd *lcp; 57947271Ssklower { 58047271Ssklower inhibit = (inhibit != 0); 58147271Ssklower if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER || 58247271Ssklower (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit)) 58347271Ssklower return; 58447271Ssklower lcp -> lcd_rxrnr_condition = inhibit; 58547271Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, inhibit ? RNR : RR); 58647271Ssklower pk_output (lcp); 58747271Ssklower } 58847271Ssklower 58941593Ssklower /* 59047271Ssklower * This procedure sends a RESET request packet. It re-intializes 59141593Ssklower * virtual circuit. 59241593Ssklower */ 59341593Ssklower 59441593Ssklower static 59545895Ssklower pk_reset (lcp, diagnostic) 59641593Ssklower register struct pklcd *lcp; 59741593Ssklower { 59845895Ssklower register struct mbuf *m; 59945895Ssklower register struct socket *so = lcp -> lcd_so; 60041593Ssklower 60141593Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 60241593Ssklower return; 60341593Ssklower 60445895Ssklower if (so) 60545895Ssklower so -> so_error = ECONNRESET; 60641593Ssklower lcp -> lcd_reset_condition = TRUE; 60741593Ssklower 60841593Ssklower /* Reset all the control variables for the channel. */ 60945895Ssklower pk_flush (lcp); 61041593Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 61141593Ssklower lcp -> lcd_intrconf_pending = FALSE; 61241593Ssklower lcp -> lcd_rsn = MODULUS - 1; 61341593Ssklower lcp -> lcd_ssn = 0; 61441593Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 61541593Ssklower lcp -> lcd_last_transmitted_pr = 0; 61645895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 61749595Ssklower m -> m_pkthdr.len = m -> m_len += 2; 61847271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; 61947271Ssklower mtod (m, octet *)[4] = diagnostic; 62045895Ssklower pk_output (lcp); 62145895Ssklower 62245895Ssklower } 62345895Ssklower 62445895Ssklower /* 62545895Ssklower * This procedure frees all data queued for output or delivery on a 62645895Ssklower * virtual circuit. 62745895Ssklower */ 62845895Ssklower 62945895Ssklower pk_flush (lcp) 63045895Ssklower register struct pklcd *lcp; 63145895Ssklower { 63245895Ssklower register struct socket *so; 63345895Ssklower 63445895Ssklower if (lcp -> lcd_template) 63545895Ssklower m_freem (lcp -> lcd_template); 63645895Ssklower 63745895Ssklower if (lcp -> lcd_cps) { 63847271Ssklower m_freem (lcp -> lcd_cps); 63945895Ssklower lcp -> lcd_cps = 0; 64045895Ssklower } 64147271Ssklower if (lcp -> lcd_facilities) { 64247271Ssklower m_freem (lcp -> lcd_facilities); 64347271Ssklower lcp -> lcd_facilities = 0; 64447271Ssklower } 64547271Ssklower if (so = lcp -> lcd_so) { 64642140Ssklower sbflush (&so -> so_rcv); 64742140Ssklower sbflush (&so -> so_snd); 64845895Ssklower } else 64945895Ssklower sbflush (&lcp -> lcd_sb); 65041593Ssklower } 65141593Ssklower 65241593Ssklower /* 65341593Ssklower * This procedure handles all local protocol procedure errors. 65441593Ssklower */ 65541593Ssklower 65645895Ssklower pk_procerror (error, lcp, errstr, diagnostic) 65741593Ssklower register struct pklcd *lcp; 65841593Ssklower char *errstr; 65941593Ssklower { 66041593Ssklower 66141593Ssklower pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 66241593Ssklower 66341593Ssklower switch (error) { 66441593Ssklower case CLEAR: 66545297Ssklower if (lcp -> lcd_so) { 66645297Ssklower lcp -> lcd_so -> so_error = ECONNABORTED; 66745297Ssklower soisdisconnecting (lcp -> lcd_so); 66841593Ssklower } 66945895Ssklower pk_clear (lcp, diagnostic, 1); 67041593Ssklower break; 67141593Ssklower 67241593Ssklower case RESET: 67345895Ssklower pk_reset (lcp, diagnostic); 67441593Ssklower } 67541593Ssklower } 67641593Ssklower 67741593Ssklower /* 67841593Ssklower * This procedure is called during the DATA TRANSFER state to check 67941593Ssklower * and process the P(R) values received in the DATA, RR OR RNR 68041593Ssklower * packets. 68141593Ssklower */ 68241593Ssklower 68341593Ssklower pk_ack (lcp, pr) 68441593Ssklower struct pklcd *lcp; 68541593Ssklower unsigned pr; 68641593Ssklower { 68741593Ssklower register struct socket *so = lcp -> lcd_so; 68841593Ssklower 68941593Ssklower if (lcp -> lcd_output_window == pr) 69041593Ssklower return (PACKET_OK); 69141593Ssklower if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 69241593Ssklower if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 69345895Ssklower pk_procerror (RESET, lcp, 69445895Ssklower "p(r) flow control error", 2); 69541593Ssklower return (ERROR_PACKET); 69641593Ssklower } 69741593Ssklower } 69841593Ssklower else { 69941593Ssklower if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 70045895Ssklower pk_procerror (RESET, lcp, 70147271Ssklower "p(r) flow control error #2", 2); 70241593Ssklower return (ERROR_PACKET); 70341593Ssklower } 70441593Ssklower } 70541593Ssklower 70641593Ssklower lcp -> lcd_output_window = pr; /* Rotate window. */ 70741593Ssklower if (lcp -> lcd_window_condition == TRUE) 70841593Ssklower lcp -> lcd_window_condition = FALSE; 70941593Ssklower 71042140Ssklower if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel)) 71141593Ssklower sowwakeup (so); 71241593Ssklower 71341593Ssklower return (PACKET_OK); 71441593Ssklower } 71541593Ssklower 71641593Ssklower /* 71741593Ssklower * This procedure decodes the X.25 level 3 packet returning a 71841593Ssklower * code to be used in switchs or arrays. 71941593Ssklower */ 72041593Ssklower 72141593Ssklower pk_decode (xp) 72241593Ssklower register struct x25_packet *xp; 72341593Ssklower { 72441593Ssklower register int type; 72541593Ssklower 72641593Ssklower if (xp -> fmt_identifier != 1) 72741593Ssklower return (INVALID_PACKET); 72845895Ssklower #ifdef ancient_history 72941593Ssklower /* 73041593Ssklower * Make sure that the logical channel group number is 0. 73141593Ssklower * This restriction may be removed at some later date. 73241593Ssklower */ 73341593Ssklower if (xp -> lc_group_number != 0) 73441593Ssklower return (INVALID_PACKET); 73545895Ssklower #endif 73641593Ssklower /* 73741593Ssklower * Test for data packet first. 73841593Ssklower */ 73941593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 74041593Ssklower return (DATA); 74141593Ssklower 74241593Ssklower /* 74341593Ssklower * Test if flow control packet (RR or RNR). 74441593Ssklower */ 74541593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 74647271Ssklower switch (xp -> packet_type & 0x1f) { 74747271Ssklower case X25_RR: 74841593Ssklower return (RR); 74947271Ssklower case X25_RNR: 75041593Ssklower return (RNR); 75147271Ssklower case X25_REJECT: 75247271Ssklower return (REJECT); 75347271Ssklower } 75441593Ssklower 75541593Ssklower /* 75641593Ssklower * Determine the rest of the packet types. 75741593Ssklower */ 75841593Ssklower switch (xp -> packet_type) { 75941593Ssklower case X25_CALL: 76041593Ssklower type = CALL; 76141593Ssklower break; 76241593Ssklower 76341593Ssklower case X25_CALL_ACCEPTED: 76441593Ssklower type = CALL_ACCEPTED; 76541593Ssklower break; 76641593Ssklower 76741593Ssklower case X25_CLEAR: 76841593Ssklower type = CLEAR; 76941593Ssklower break; 77041593Ssklower 77141593Ssklower case X25_CLEAR_CONFIRM: 77241593Ssklower type = CLEAR_CONF; 77341593Ssklower break; 77441593Ssklower 77541593Ssklower case X25_INTERRUPT: 77641593Ssklower type = INTERRUPT; 77741593Ssklower break; 77841593Ssklower 77941593Ssklower case X25_INTERRUPT_CONFIRM: 78041593Ssklower type = INTERRUPT_CONF; 78141593Ssklower break; 78241593Ssklower 78341593Ssklower case X25_RESET: 78441593Ssklower type = RESET; 78541593Ssklower break; 78641593Ssklower 78741593Ssklower case X25_RESET_CONFIRM: 78841593Ssklower type = RESET_CONF; 78941593Ssklower break; 79041593Ssklower 79141593Ssklower case X25_RESTART: 79241593Ssklower type = RESTART; 79341593Ssklower break; 79441593Ssklower 79541593Ssklower case X25_RESTART_CONFIRM: 79641593Ssklower type = RESTART_CONF; 79741593Ssklower break; 79841593Ssklower 79947271Ssklower case X25_DIAGNOSTIC: 80048873Ssklower type = DIAG_TYPE; 80147271Ssklower break; 80247271Ssklower 80341593Ssklower default: 80441593Ssklower type = INVALID_PACKET; 80541593Ssklower } 80641593Ssklower return (type); 80741593Ssklower } 80841593Ssklower 80941593Ssklower /* 81041593Ssklower * A restart packet has been received. Print out the reason 81141593Ssklower * for the restart. 81241593Ssklower */ 81341593Ssklower 81441593Ssklower pk_restartcause (pkp, xp) 81541593Ssklower struct pkcb *pkp; 81641593Ssklower register struct x25_packet *xp; 81741593Ssklower { 81841593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 81945574Ssklower register int lcn = LCN(xp); 82041593Ssklower 82141593Ssklower switch (xp -> packet_data) { 82241593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 82341593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 82441593Ssklower break; 82541593Ssklower 82641593Ssklower case X25_RESTART_NETWORK_CONGESTION: 82741593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 82841593Ssklower break; 82941593Ssklower 83041593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 83141593Ssklower pk_message (lcn, xcp, "restart: network operational"); 83241593Ssklower break; 83341593Ssklower 83441593Ssklower default: 83541593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 83641593Ssklower } 83741593Ssklower } 83841593Ssklower 83941593Ssklower #define MAXRESETCAUSE 7 84041593Ssklower 84141593Ssklower int Reset_cause[] = { 84241593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 84341593Ssklower }; 84441593Ssklower 84541593Ssklower /* 84641593Ssklower * A reset packet has arrived. Return the cause to the user. 84741593Ssklower */ 84841593Ssklower 84941593Ssklower pk_resetcause (pkp, xp) 85041593Ssklower struct pkcb *pkp; 85141593Ssklower register struct x25_packet *xp; 85241593Ssklower { 85345297Ssklower register struct pklcd *lcp = 85445574Ssklower pkp -> pk_chan[LCN(xp)]; 85541593Ssklower register int code = xp -> packet_data; 85641593Ssklower 85741593Ssklower if (code > MAXRESETCAUSE) 85841593Ssklower code = 7; /* EXRNCG */ 85941593Ssklower 86047271Ssklower pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x", 86147271Ssklower xp -> packet_data, 4[(u_char *)xp]); 86247271Ssklower 86345297Ssklower lcp -> lcd_so -> so_error = Reset_cause[code]; 86441593Ssklower } 86541593Ssklower 86641593Ssklower #define MAXCLEARCAUSE 25 86741593Ssklower 86841593Ssklower int Clear_cause[] = { 86941593Ssklower EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 87041593Ssklower 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 87141593Ssklower 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 87241593Ssklower }; 87341593Ssklower 87441593Ssklower /* 87541593Ssklower * A clear packet has arrived. Return the cause to the user. 87641593Ssklower */ 87741593Ssklower 87841593Ssklower pk_clearcause (pkp, xp) 87941593Ssklower struct pkcb *pkp; 88041593Ssklower register struct x25_packet *xp; 88141593Ssklower { 88245297Ssklower register struct pklcd *lcp = 88345574Ssklower pkp -> pk_chan[LCN(xp)]; 88441593Ssklower register int code = xp -> packet_data; 88541593Ssklower 88641593Ssklower if (code > MAXCLEARCAUSE) 88741593Ssklower code = 5; /* EXRNCG */ 88849595Ssklower if (lcp -> lcd_so) 88949595Ssklower lcp -> lcd_so -> so_error = Clear_cause[code]; 89041593Ssklower } 89141593Ssklower 89241593Ssklower char * 89341593Ssklower format_ntn (xcp) 89441593Ssklower register struct x25config *xcp; 89541593Ssklower { 89641593Ssklower 89745165Ssklower return (xcp -> xc_addr.x25_addr); 89841593Ssklower } 89941593Ssklower 90041593Ssklower /* VARARGS1 */ 90141593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 90241593Ssklower struct x25config *xcp; 90341593Ssklower char *fmt; 90441593Ssklower { 90541593Ssklower 90641593Ssklower if (lcn) 90741593Ssklower if (pkcbhead -> pk_next) 90841593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 90941593Ssklower else 91041593Ssklower printf ("X.25: lcn %d: ", lcn); 91141593Ssklower else 91241593Ssklower if (pkcbhead -> pk_next) 91341593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 91441593Ssklower else 91541593Ssklower printf ("X.25: "); 91641593Ssklower 91741593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 91841593Ssklower printf ("\n"); 91941593Ssklower } 92045297Ssklower 92147271Ssklower pk_ifattach (ia, lloutput, llnext) 92245297Ssklower register struct x25_ifaddr *ia; 92347271Ssklower int (*lloutput) (); 92445297Ssklower caddr_t llnext; 92545297Ssklower { 92645297Ssklower /* this is here because you can't include both pk_var and hd_var */ 92745297Ssklower /* this will probably be replace by a streams gluing mechanism */ 92845297Ssklower ia -> ia_pkcb.pk_lloutput = lloutput; 92945297Ssklower ia -> ia_pkcb.pk_llnext = llnext; 93045297Ssklower } 93145297Ssklower 93247271Ssklower pk_fragment (lcp, m0, qbit, mbit, wait) 93345297Ssklower struct mbuf *m0; 93445297Ssklower register struct pklcd *lcp; 93545297Ssklower { 93645297Ssklower register struct mbuf *m = m0; 93745297Ssklower register struct x25_packet *xp; 93845297Ssklower register struct sockbuf *sb; 93947271Ssklower struct mbuf *head = 0, *next, **mp = &head, *m_split (); 94045297Ssklower int totlen, psize = 1 << (lcp -> lcd_packetsize); 94145297Ssklower 94245297Ssklower if (m == 0) 94349595Ssklower return 0; 94445895Ssklower if (m -> m_flags & M_PKTHDR == 0) 94547271Ssklower panic ("pk_fragment"); 94645297Ssklower totlen = m -> m_pkthdr.len; 94745574Ssklower m -> m_act = 0; 94845297Ssklower sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb; 94945297Ssklower do { 95045297Ssklower if (totlen > psize) { 95147271Ssklower if ((next = m_split (m, psize, wait)) == 0) 95245297Ssklower goto abort; 95345297Ssklower totlen -= psize; 95445574Ssklower } else 95545574Ssklower next = 0; 95645297Ssklower M_PREPEND(m, PKHEADERLN, wait); 95745297Ssklower if (m == 0) 95845297Ssklower goto abort; 95945574Ssklower *mp = m; 96045574Ssklower mp = & m -> m_act; 96145574Ssklower *mp = 0; 96247271Ssklower xp = mtod (m, struct x25_packet *); 96345297Ssklower 0[(char *)xp] = 0; 96445297Ssklower if (qbit) 96545574Ssklower xp -> q_bit = 1; 96645574Ssklower if (lcp -> lcd_flags & X25_DBIT) 96745574Ssklower xp -> d_bit = 1; 96845297Ssklower xp -> fmt_identifier = 1; 96945297Ssklower xp -> packet_type = X25_DATA; 97045574Ssklower SET_LCN(xp, lcp -> lcd_lcn); 97145574Ssklower if (next || (mbit && (totlen == psize || 97245574Ssklower (lcp -> lcd_flags & X25_DBIT)))) 97345297Ssklower MBIT(xp) = 1; 97445297Ssklower } while (m = next); 97545574Ssklower for (m = head; m; m = next) { 97645297Ssklower next = m -> m_act; 97745297Ssklower m -> m_act = 0; 97847271Ssklower sbappendrecord (sb, m); 97945297Ssklower } 98045297Ssklower return 0; 98145297Ssklower abort: 98245574Ssklower if (wait) 98347271Ssklower panic ("pk_fragment null mbuf after wait"); 98445574Ssklower if (next) 98547271Ssklower m_freem (next); 98645574Ssklower for (m = head; m; m = next) { 98745297Ssklower next = m -> m_act; 98847271Ssklower m_freem (m); 98945297Ssklower } 99045297Ssklower return ENOBUFS; 99145297Ssklower } 99245574Ssklower 99345574Ssklower struct mbuf * 99447271Ssklower m_split (m0, len0, wait) 99545574Ssklower register struct mbuf *m0; 99645574Ssklower int len0; 99745574Ssklower { 99845574Ssklower register struct mbuf *m, *n; 99945574Ssklower unsigned len = len0; 100045574Ssklower 100145574Ssklower for (m = m0; m && len > m -> m_len; m = m -> m_next) 100245574Ssklower len -= m -> m_len; 100345574Ssklower if (m == 0) 100445574Ssklower return (0); 100545574Ssklower if (m0 -> m_flags & M_PKTHDR) { 100645574Ssklower MGETHDR(n, wait, m0 -> m_type); 100745574Ssklower if (n == 0) 100845574Ssklower return (0); 100945574Ssklower n -> m_pkthdr.rcvif = m0 -> m_pkthdr.rcvif; 101045574Ssklower n -> m_pkthdr.len = m0 -> m_pkthdr.len - len0; 101145574Ssklower m0 -> m_pkthdr.len = len0; 101245574Ssklower if (m -> m_flags & M_EXT) 101345574Ssklower goto extpacket; 101445574Ssklower if (len > MHLEN) { 101545574Ssklower /* m can't be the lead packet */ 101645574Ssklower MH_ALIGN(n, 0); 101747271Ssklower n -> m_next = m_split (m, len, wait); 101845574Ssklower if (n -> m_next == 0) { 101947271Ssklower (void) m_free (n); 102045574Ssklower return (0); 102145574Ssklower } else 102245574Ssklower return (n); 102345574Ssklower } else 102445574Ssklower MH_ALIGN(n, len); 102545574Ssklower } else if (len == m -> m_len) { 102645574Ssklower n = m -> m_next; 102745574Ssklower m -> m_next = 0; 102845574Ssklower return (n); 102945574Ssklower } 103045574Ssklower extpacket: 103145574Ssklower len = m -> m_len - len; /* remainder to be copied */ 103245574Ssklower m -> m_len -= len; /* now equals original len */ 103345895Ssklower if (m -> m_flags & M_EXT) { 103445574Ssklower n -> m_flags |= M_EXT; 103545574Ssklower n -> m_ext = m -> m_ext; 103647271Ssklower mclrefcnt[mtocl (m -> m_ext.ext_buf)]++; 103745574Ssklower n -> m_data = m -> m_data + m -> m_len; 103845574Ssklower } else { 103945574Ssklower MGET(n, wait, m -> m_type); 104045574Ssklower if (n == 0) { 104145574Ssklower m -> m_len += len; 104245574Ssklower return (0); 104345574Ssklower } 104445574Ssklower M_ALIGN(n, len); 104547271Ssklower bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len); 104645574Ssklower } 104745574Ssklower n -> m_len = len; 104845574Ssklower n -> m_next = m -> m_next; 104945574Ssklower m -> m_next = 0; 105045574Ssklower return (n); 105145574Ssklower } 1052