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