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