|
|
1.1 root 1: /*
2: * Copyright (c) 1980, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)raw_usrreq.c 7.1 (Berkeley) 6/4/86
7: */
8:
9: #include "param.h"
10: #include "mbuf.h"
11: #include "domain.h"
12: #include "protosw.h"
13: #include "socket.h"
14: #include "socketvar.h"
15: #include "errno.h"
16:
17: #include "if.h"
18: #include "route.h"
19: #include "netisr.h"
20: #include "raw_cb.h"
21:
22: #include "../vax/mtpr.h"
23:
24: /*
25: * Initialize raw connection block q.
26: */
27: raw_init()
28: {
29:
30: rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
31: rawintrq.ifq_maxlen = IFQ_MAXLEN;
32: }
33:
34: /*
35: * Raw protocol interface.
36: */
37: raw_input(m0, proto, src, dst)
38: struct mbuf *m0;
39: struct sockproto *proto;
40: struct sockaddr *src, *dst;
41: {
42: register struct mbuf *m;
43: struct raw_header *rh;
44: int s;
45:
46: /*
47: * Rip off an mbuf for a generic header.
48: */
49: m = m_get(M_DONTWAIT, MT_HEADER);
50: if (m == 0) {
51: m_freem(m0);
52: return;
53: }
54: m->m_next = m0;
55: m->m_len = sizeof(struct raw_header);
56: rh = mtod(m, struct raw_header *);
57: rh->raw_dst = *dst;
58: rh->raw_src = *src;
59: rh->raw_proto = *proto;
60:
61: /*
62: * Header now contains enough info to decide
63: * which socket to place packet in (if any).
64: * Queue it up for the raw protocol process
65: * running at software interrupt level.
66: */
67: s = splimp();
68: if (IF_QFULL(&rawintrq))
69: m_freem(m);
70: else
71: IF_ENQUEUE(&rawintrq, m);
72: splx(s);
73: schednetisr(NETISR_RAW);
74: }
75:
76: /*
77: * Raw protocol input routine. Process packets entered
78: * into the queue at interrupt time. Find the socket
79: * associated with the packet(s) and move them over. If
80: * nothing exists for this packet, drop it.
81: */
82: rawintr()
83: {
84: int s;
85: struct mbuf *m;
86: register struct rawcb *rp;
87: register struct raw_header *rh;
88: struct socket *last;
89:
90: next:
91: s = splimp();
92: IF_DEQUEUE(&rawintrq, m);
93: splx(s);
94: if (m == 0)
95: return;
96: rh = mtod(m, struct raw_header *);
97: last = 0;
98: for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
99: if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family)
100: continue;
101: if (rp->rcb_proto.sp_protocol &&
102: rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol)
103: continue;
104: /*
105: * We assume the lower level routines have
106: * placed the address in a canonical format
107: * suitable for a structure comparison.
108: */
109: #define equal(a1, a2) \
110: (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
111: if ((rp->rcb_flags & RAW_LADDR) &&
112: !equal(rp->rcb_laddr, rh->raw_dst))
113: continue;
114: if ((rp->rcb_flags & RAW_FADDR) &&
115: !equal(rp->rcb_faddr, rh->raw_src))
116: continue;
117: if (last) {
118: struct mbuf *n;
119: if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) {
120: if (sbappendaddr(&last->so_rcv, &rh->raw_src,
121: n, (struct mbuf *)0) == 0)
122: /* should notify about lost packet */
123: m_freem(n);
124: else
125: sorwakeup(last);
126: }
127: }
128: last = rp->rcb_socket;
129: }
130: if (last) {
131: if (sbappendaddr(&last->so_rcv, &rh->raw_src,
132: m->m_next, (struct mbuf *)0) == 0)
133: m_freem(m->m_next);
134: else
135: sorwakeup(last);
136: (void) m_free(m); /* header */
137: } else
138: m_freem(m);
139: goto next;
140: }
141:
142: /*ARGSUSED*/
143: raw_ctlinput(cmd, arg)
144: int cmd;
145: struct sockaddr *arg;
146: {
147:
148: if (cmd < 0 || cmd > PRC_NCMDS)
149: return;
150: /* INCOMPLETE */
151: }
152:
153: /*ARGSUSED*/
154: raw_usrreq(so, req, m, nam, rights)
155: struct socket *so;
156: int req;
157: struct mbuf *m, *nam, *rights;
158: {
159: register struct rawcb *rp = sotorawcb(so);
160: register int error = 0;
161:
162: if (req == PRU_CONTROL)
163: return (EOPNOTSUPP);
164: if (rights && rights->m_len) {
165: error = EOPNOTSUPP;
166: goto release;
167: }
168: if (rp == 0 && req != PRU_ATTACH) {
169: error = EINVAL;
170: goto release;
171: }
172: switch (req) {
173:
174: /*
175: * Allocate a raw control block and fill in the
176: * necessary info to allow packets to be routed to
177: * the appropriate raw interface routine.
178: */
179: case PRU_ATTACH:
180: if ((so->so_state & SS_PRIV) == 0) {
181: error = EACCES;
182: break;
183: }
184: if (rp) {
185: error = EINVAL;
186: break;
187: }
188: error = raw_attach(so, (int)nam);
189: break;
190:
191: /*
192: * Destroy state just before socket deallocation.
193: * Flush data or not depending on the options.
194: */
195: case PRU_DETACH:
196: if (rp == 0) {
197: error = ENOTCONN;
198: break;
199: }
200: raw_detach(rp);
201: break;
202:
203: /*
204: * If a socket isn't bound to a single address,
205: * the raw input routine will hand it anything
206: * within that protocol family (assuming there's
207: * nothing else around it should go to).
208: */
209: case PRU_CONNECT:
210: if (rp->rcb_flags & RAW_FADDR) {
211: error = EISCONN;
212: break;
213: }
214: raw_connaddr(rp, nam);
215: soisconnected(so);
216: break;
217:
218: case PRU_CONNECT2:
219: error = EOPNOTSUPP;
220: goto release;
221:
222: case PRU_BIND:
223: if (rp->rcb_flags & RAW_LADDR) {
224: error = EINVAL; /* XXX */
225: break;
226: }
227: error = raw_bind(so, nam);
228: break;
229:
230: case PRU_DISCONNECT:
231: if ((rp->rcb_flags & RAW_FADDR) == 0) {
232: error = ENOTCONN;
233: break;
234: }
235: raw_disconnect(rp);
236: soisdisconnected(so);
237: break;
238:
239: /*
240: * Mark the connection as being incapable of further input.
241: */
242: case PRU_SHUTDOWN:
243: socantsendmore(so);
244: break;
245:
246: /*
247: * Ship a packet out. The appropriate raw output
248: * routine handles any massaging necessary.
249: */
250: case PRU_SEND:
251: if (nam) {
252: if (rp->rcb_flags & RAW_FADDR) {
253: error = EISCONN;
254: break;
255: }
256: raw_connaddr(rp, nam);
257: } else if ((rp->rcb_flags & RAW_FADDR) == 0) {
258: error = ENOTCONN;
259: break;
260: }
261: error = (*so->so_proto->pr_output)(m, so);
262: m = NULL;
263: if (nam)
264: rp->rcb_flags &= ~RAW_FADDR;
265: break;
266:
267: case PRU_ABORT:
268: raw_disconnect(rp);
269: sofree(so);
270: soisdisconnected(so);
271: break;
272:
273: case PRU_SENSE:
274: /*
275: * stat: don't bother with a blocksize.
276: */
277: return (0);
278:
279: /*
280: * Not supported.
281: */
282: case PRU_RCVOOB:
283: case PRU_RCVD:
284: return(EOPNOTSUPP);
285:
286: case PRU_LISTEN:
287: case PRU_ACCEPT:
288: case PRU_SENDOOB:
289: error = EOPNOTSUPP;
290: break;
291:
292: case PRU_SOCKADDR:
293: bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t),
294: sizeof (struct sockaddr));
295: nam->m_len = sizeof (struct sockaddr);
296: break;
297:
298: case PRU_PEERADDR:
299: bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t),
300: sizeof (struct sockaddr));
301: nam->m_len = sizeof (struct sockaddr);
302: break;
303:
304: default:
305: panic("raw_usrreq");
306: }
307: release:
308: if (m != NULL)
309: m_freem(m);
310: return (error);
311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.