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