|
|
1.1 root 1: /*
2: * C H A O S L D
3: *
4: * Chaosnet line discipline, to be pushed on an ethernet controller.
5: * Handles xmit and rcv windows, packet numbering, and connection states.
6: *
7: *
8: * (c) Copyright 1985 Nirvonics, Inc.
9: *
10: * Written by Kurt Gollhardt
11: * Last update Tue Mar 12 04:18:58 1985
12: *
13: * This software is the property of Nirvonics, Inc.
14: * All rights reserved.
15: *
16: */
17:
18: #include "ch.h"
19: #if NCH
20: #include "../h/param.h"
21: #include "../h/systm.h"
22: #include "../h/stream.h"
23: #include "../h/ioctl.h"
24: #include "../h/ttyld.h"
25: #include "../h/map.h"
26: #include "../h/buf.h"
27: #include "../h/conf.h"
28: #include "../chaosld/types.h"
29: #define CHDEFINE
30: #include "../chaosld/globals.h"
31:
32:
33: extern int chrcv(), chb_put();
34: int chopen(), chclose(), chosrv(), chisrv();
35: static struct qinit chrinit = { chb_put, chisrv, chopen, chclose, 512, 64 };
36: static struct qinit chwinit = { putq, chosrv, chopen, chclose, 512, 64 };
37: struct streamtab chinfo = { &chrinit, &chwinit };
38:
39: chopen(q, dev)
40: register struct queue *q;
41: {
42: if (q->ptr)
43: return(1);
44: if (ChaosQ != (struct queue *)0) /* Already open */
45: return(0);
46: ChaosQ = q; /* that's the RD q */
47: q->flag |= QDELIM|QNOENB; /* chiput calls qenable() */
48: WR(q)->flag |= QDELIM;
49: return(1);
50: }
51:
52: chclose(q)
53: struct queue *q;
54: {
55: struct connection **connp;
56: int ps = spl6();
57:
58: for (connp = Chconn; connp < &Chconn[NCH]; ++connp)
59: if (*connp != NOCONN)
60: chld_close(*connp, NOPKT);
61:
62: freelist(Chlsnlist);
63: freelist(Chrfclist);
64: Chlsnlist = Chrfclist = Chrfctail = NOPKT;
65: Chmyaddr.ch_addr = 0;
66:
67: ChaosQ = (struct queue *)0;
68: splx(ps);
69: }
70:
71:
72: chisrv(q)
73: struct queue *q;
74: {
75: register struct block *bp;
76:
77: chrcv(q); /* Receive the packet */
78:
79: /* See if there's another packet on the queue */
80: for (bp = q->first; bp != NOBLOCK; bp = bp->next)
81: if (bp->type == M_DELIM) {
82: qenable(q); /* re-enable queue for the next packet */
83: break;
84: }
85: }
86:
87:
88: chosrv(q)
89: register struct queue *q;
90: {
91: register union stmsg *sp;
92: register struct block *bp;
93:
94: while(bp = getq(q)){
95: if(bp->type == M_IOCTL){
96: sp = (union stmsg *)bp->rptr;
97: switch(sp->ioc0.com){
98: case CHIOCNAME:
99: copyin(*(caddr_t *)sp->iocx.xxx, Chmyname, CHSTATNAME);
100: bp->rptr = bp->wptr;
101: bp->type = M_IOCACK;
102: qreply(q, bp);
103: break;
104: case CHIOCADDR:
105: Chmyaddr.ch_addr = *(int *)sp->iocx.xxx;
106: /* fall through */
107: default:
108: (*q->next->qinfo->putp)(q->next, bp);
109: break;
110: }
111: } else
112: (*q->next->qinfo->putp)(q->next, bp);
113: }
114: }
115:
116: chld_write(conn, pkt)
117: register struct connection *conn;
118: register struct packet *pkt;
119: {
120: setconn(conn, pkt);
121:
122: switch (pkt->pk_op) {
123: case ANSOP:
124: case FWDOP:
125: if (conn->cn_state != CSRFCRCVD ||
126: (conn->cn_flags & CHANSWER) == 0)
127: goto err;
128: chld_close(conn, pkt);
129: return 0;
130: case RFCOP:
131: case BRDOP:
132: if (conn->cn_state != CSRFCSENT)
133: goto err;
134: break;
135: case UNCOP:
136: pkt->pk_pkn = 0;
137: pkt->next = NOPKT;
138: senddata(pkt);
139: return 0;
140: default:
141: if (!ISDATA(pkt))
142: goto err;
143: case OPNOP:
144: case EOFOP:
145: if (conn->cn_state != CSOPEN)
146: goto err;
147: setack(conn, pkt);
148: break;
149: }
150:
151: pkt->pk_pkn = ++conn->cn_tlast;
152: senddata(pkt);
153: return 0;
154:
155: err:
156: free_packet(pkt);
157: return -1;
158: }
159:
160:
161: chld_eof(conn)
162: struct connection *conn;
163: {
164: register struct packet *pkt;
165:
166: if ((pkt = new_packet()) != NOPKT) {
167: setconn(conn, pkt);
168: pkt->pk_op = EOFOP;
169: return chld_write(conn, pkt);
170: }
171: return 0;
172: }
173:
174:
175: chld_accept(conn)
176: struct connection *conn;
177: {
178: conn->cn_state = CSOPEN;
179: sendopn(conn);
180: }
181:
182:
183: chld_open(conn, daddr, rwsize, pkt)
184: register struct connection *conn;
185: register struct packet *pkt;
186: {
187: conn->cn_faddr.ch_addr = daddr;
188: conn->cn_state = CSRFCSENT;
189: conn->cn_rwsize = rwsize;
190: conn->cn_rsts = rwsize / 2;
191: conn->cn_time = Chclock;
192: pkt->pk_op = RFCOP;
193: pkt->pk_fc = pkt->pk_ackn = 0;
194: debug(DCONN,printf("Conn #%x: RFCS state\n", conn->cn_lidx.ci_idx));
195: /*
196: * By writing the RFC packet like a data packet, it will be kept
197: * around for automatic retransmission until freed by the normal
198: * receipting mechanism; xmitdone() and chrcv() facilitate this.
199: * Since new_conn() clears the connection (including cn_tlast),
200: * the packet number of the RFC will be 1 (pkn = ++cn_tlast).
201: */
202: chld_write(conn, pkt);
203: }
204:
205:
206: chld_listen(conn, rwsize, pkt)
207: register struct connection *conn;
208: register struct packet *pkt;
209: {
210: register struct packet *opkt, *pktl;
211: int ps;
212:
213: conn->cn_state = CSLISTEN;
214: conn->cn_flags |= CHSERVER;
215: conn->cn_rwsize = rwsize;
216: pkt->pk_op = LSNOP;
217: setconn(conn, pkt);
218:
219: if (flatten(pkt)) {
220: free_packet(pkt);
221: return;
222: }
223:
224: ps = spl6();
225: opkt = NOPKT;
226: for (pktl = Chrfclist; pktl != NOPKT; pktl = (opkt = pktl)->next)
227: if (concmp(pktl, pkt->data->rptr, (int)pkt->pk_len)) {
228: if (opkt == NOPKT)
229: Chrfclist = pktl->next;
230: else
231: opkt->next = pktl->next;
232: if (pktl == Chrfctail)
233: Chrfctail = opkt;
234: free_packet(pkt);
235: lsnmatch(pktl, conn);
236: chd_newstate(conn);
237: splx(ps);
238: return;
239: }
240:
241: pkt->next = Chlsnlist;
242: Chlsnlist = pkt;
243: splx(ps);
244:
245: debug(DCONN,printf("Conn #%x: LISTEN state\n", conn->cn_lidx.ci_idx));
246: }
247:
248:
249: chld_close(conn, pkt)
250: register struct connection *conn;
251: register struct packet *pkt;
252: {
253: int ps = spl6();
254:
255: ch_busy++;
256: switch (conn->cn_state) {
257: case CSOPEN:
258: case CSRFCRCVD:
259: if (pkt != NOPKT) {
260: setconn(conn, pkt);
261: pkt->pk_ackn = pkt->pk_pkn = 0;
262: sendctl(pkt);
263: pkt = NOPKT;
264: }
265: /* Fall into ... */
266: case CSRFCSENT:
267: close_conn(conn, CSCLOSED, NOPKT);
268: break;
269: case CSLISTEN:
270: rmlisten(conn);
271: break;
272: }
273: --ch_busy;
274: splx(ps);
275:
276: if (pkt != NOPKT)
277: free_packet(pkt);
278: }
279:
280: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.