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