* Copyright (c) University of British Columbia, 1984
* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* the Laboratory for Computation Vision and the Computer Science Department
* of the University of British Columbia.
* %sccs.include.redist.c%
* @(#)hd_subr.c 7.2 (Berkeley) %G%
#include "../h/protosw.h"
#include "../netccitt/hdlc.h"
#include "../netccitt/hd_var.h"
#include "../netccitt/x25.h"
hdintrq
.ifq_maxlen
= IFQ_MAXLEN
;
register struct x25config
*xcp
= (struct x25config
*)addr
;
register struct ifnet
*ifp
;
register struct hdcb
*hdp
;
register struct ifaddr
*ifa
;
if (xcp
->xc_family
!= AF_CCITT
)
if (xcp
->xc_lptype
!= HDLCPROTO_LAPB
)
return (EPROTONOSUPPORT
);
for (ifa
= ifa_ifwithaddr ((struct sockaddr
*)xcp
); ifa
; ifa
= ifa
->ifa_next
)
if (ifa
->ifa_addr
.sa_family
== AF_CCITT
)
if (ifa
== 0 || (ifp
= ifa
->ifa_ifp
) == 0)
for (hdp
= hdcbhead
; hdp
; hdp
= hdp
->hd_next
)
if (hdp
== 0) { /* new interface */
m
= m_getclr (M_DONTWAIT
, MT_PCB
);
if (error
= pk_ctlinput (PRC_LINKDOWN
, xcp
)) {
hdp
= mtod (m
, struct hdcb
*);
if (xcp
->xc_lwsize
== 0 ||
xcp
->xc_lwsize
> MAX_WINDOW_SIZE
)
xcp
->xc_lwsize
= MAX_WINDOW_SIZE
;
if (hdp
->hd_state
== INIT
)
if (hdp
->hd_state
== ABM
)
hd_message (hdp
, "Operator shutdown: link closed");
(void) pk_ctlinput (PRC_LINKDOWN
, xcp
);
hd_writeinternal (hdp
, DISC
, POLLON
);
hdp
->hd_state
= DISC_SENT
;
register struct hdcb
*hdp
;
/* Clear Transmit queue. */
while ((m
= hd_remove (&hdp
->hd_txq
)) != NULL
)
/* Clear Retransmit queue. */
while (i
!= hdp
->hd_retxqi
) {
m_freem (hdp
->hd_retxq
[i
]);
hdp
->hd_vs
= hdp
->hd_vr
= 0;
hdp
->hd_lasttxnr
= hdp
->hd_lastrxnr
= 0;
register struct hdcb
*hdp
;
struct Hdlc_frame
*frame
;
register int frametype
= ILLEGAL
;
register struct Hdlc_iframe
*iframe
= (struct Hdlc_iframe
*) frame
;
register struct Hdlc_sframe
*sframe
= (struct Hdlc_sframe
*) frame
;
register struct Hdlc_uframe
*uframe
= (struct Hdlc_uframe
*) frame
;
if (iframe
-> hdlc_0
== 0) {
else if (sframe
-> hdlc_01
== 1) {
/* Supervisory format. */
else if (uframe
-> hdlc_11
== 3) {
* This routine is called when the HDLC layer internally generates a
* command or response for the remote machine ( eg. RR, UA etc. ).
* Only supervisory or unnumbered frames are processed.
hd_writeinternal (hdp
, frametype
, pf
)
register struct hdcb
*hdp
;
register int frametype
, pf
;
register struct mbuf
*buf
;
struct Hdlc_frame
*frame
;
register struct Hdlc_sframe
*sframe
;
register struct Hdlc_uframe
*uframe
;
MGET (buf
, M_DONTWAIT
, MT_HEADER
);
frame
= mtod (buf
, struct Hdlc_frame
*);
sframe
= mtod (buf
, struct Hdlc_sframe
*);
uframe
= mtod (buf
, struct Hdlc_uframe
*);
/* Assume a response - address structure for DTE */
frame
-> address
= ADDRESS_A
;
buf
-> m_act
= buf
-> m_next
= NULL
;
frame
-> control
= RR_CONTROL
;
frame
-> control
= RNR_CONTROL
;
frame
-> control
= REJ_CONTROL
;
frame
-> control
= SABM_CONTROL
;
frame
-> address
= ADDRESS_B
;
frame
-> control
= DISC_CONTROL
;
frame
-> address
= ADDRESS_B
;
frame
-> control
= DM_CONTROL
;
frame
-> control
= UA_CONTROL
;
frame
-> control
= FRMR_CONTROL
;
bcopy ((caddr_t
)&hd_frmr
, (caddr_t
)frame
-> info
, 3);
if (sframe
-> hdlc_01
== 1) {
/* Supervisory format - RR, REJ, or RNR. */
sframe
-> nr
= hdp
->hd_vr
;
hdp
->hd_lasttxnr
= hdp
->hd_vr
;
hd_trace (hdp
, TX
, frame
);
(*hdp
-> hd_ifp
-> if_output
) (hdp
-> hd_ifp
, buf
,
(struct sockaddr
*)hdp
->hd_xcp
);
if ((q
-> head
= m
-> m_act
) == NULL
)
register struct hdtxq
*q
;
s
= spl6 (); /* XXX SHOULDN'T THIS BE splimp? */
IF_DEQUEUE (&ifp
->if_snd
, m
);
printf ("HDLC(%s): %s\n", format_ntn (hdp
->hd_xcp
), msg
);
printf ("HDLC: %s\n", msg
);
printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n",
hdp
->hd_vs
, hdp
->hd_vr
, hdp
->hd_retxqi
);
printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n",
hdp
->hd_lastrxnr
, hdp
->hd_lasttxnr
, hdp
->hd_condition
, hdp
->hd_xx
);