1 /* $NetBSD: idrp_usrreq.c,v 1.17 2006/08/30 15:32:23 christos Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)idrp_usrreq.c 8.1 (Berkeley) 6/10/93
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: idrp_usrreq.c,v 1.17 2006/08/30 15:32:23 christos Exp $");
36
37 #include <sys/param.h>
38 #include <sys/proc.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/protosw.h>
45 #include <sys/errno.h>
46
47 #include <net/raw_cb.h>
48 #include <net/route.h>
49 #include <net/if.h>
50
51 #include <netiso/argo_debug.h>
52 #include <netiso/iso.h>
53 #include <netiso/clnp.h>
54 #include <netiso/clnl.h>
55 #include <netiso/iso_pcb.h>
56 #include <netiso/iso_var.h>
57 #include <netiso/idrp_var.h>
58
59 #include <machine/stdarg.h>
60
61 LIST_HEAD(, rawcb) idrp_pcb;
62 struct isopcb idrp_isop;
63 static struct sockaddr_iso idrp_addrs[2] =
64 {
65 {
66 .siso_len = sizeof(idrp_addrs[0]),
67 .siso_family = AF_ISO,
68 },
69 {
70 .siso_len = sizeof(idrp_addrs[1]),
71 .siso_family = AF_ISO,
72 },
73 };
74
75 /*
76 * IDRP initialization
77 */
78 void
79 idrp_init(void)
80 {
81 extern struct clnl_protosw clnl_protox[256];
82
83 LIST_INIT(&idrp_pcb);
84
85 idrp_isop.isop_next = idrp_isop.isop_prev = &idrp_isop;
86 idrp_isop.isop_faddr = &idrp_isop.isop_sfaddr;
87 idrp_isop.isop_laddr = &idrp_isop.isop_sladdr;
88 idrp_isop.isop_sladdr = idrp_addrs[1];
89 idrp_isop.isop_sfaddr = idrp_addrs[1];
90 clnl_protox[ISO10747_IDRP].clnl_input = idrp_input;
91 }
92
93 /*
94 * CALLED FROM:
95 * tpclnp_input().
96 * FUNCTION and ARGUMENTS:
97 * Take a packet (m) from clnp, strip off the clnp header
98 * and mke suitable for the idrp socket.
99 * No return value.
100 */
101 void
102 idrp_input(struct mbuf *m, ...)
103 {
104 struct sockaddr_iso *src, *dst;
105 va_list ap;
106
107 va_start(ap, m);
108 src = va_arg(ap, struct sockaddr_iso *);
109 dst = va_arg(ap, struct sockaddr_iso *);
110 va_end(ap);
111
112 if (idrp_isop.isop_socket == 0) {
113 bad: m_freem(m);
114 return;
115 }
116 bzero(idrp_addrs[0].siso_data, sizeof(idrp_addrs[0].siso_data));
117 bcopy((caddr_t) & (src->siso_addr), (caddr_t) & idrp_addrs[0].siso_addr,
118 1 + src->siso_nlen);
119 bzero(idrp_addrs[1].siso_data, sizeof(idrp_addrs[1].siso_data));
120 bcopy((caddr_t) & (dst->siso_addr), (caddr_t) & idrp_addrs[1].siso_addr,
121 1 + dst->siso_nlen);
122 if (sbappendaddr(&idrp_isop.isop_socket->so_rcv,
123 sisotosa(idrp_addrs), m, (struct mbuf *) 0) == 0)
124 goto bad;
125 sorwakeup(idrp_isop.isop_socket);
126 }
127
128 int
129 idrp_output(struct mbuf *m, ...)
130 {
131 struct sockaddr_iso *siso;
132 int s = splsoftnet(), i;
133 va_list ap;
134
135 va_start(ap, m);
136 siso = va_arg(ap, struct sockaddr_iso *);
137 va_end(ap);
138
139 bcopy((caddr_t) & (siso->siso_addr),
140 (caddr_t) & idrp_isop.isop_sfaddr.siso_addr, 1 + siso->siso_nlen);
141 siso++;
142 bcopy((caddr_t) & (siso->siso_addr),
143 (caddr_t) & idrp_isop.isop_sladdr.siso_addr, 1 + siso->siso_nlen);
144 i = clnp_output(m, idrp_isop, m->m_pkthdr.len, 0);
145 splx(s);
146 return (i);
147 }
148
149 u_long idrp_sendspace = 3072; /* really max datagram size */
150 u_long idrp_recvspace = 40 * 1024; /* 40 1K datagrams */
151
152 /* ARGSUSED */
153 int
154 idrp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
155 struct mbuf *control, struct lwp *l)
156 {
157 struct rawcb *rp;
158 struct proc *p;
159 int error = 0;
160
161 if (req == PRU_CONTROL)
162 return (EOPNOTSUPP);
163
164 p = l ? l->l_proc : NULL;
165 rp = sotorawcb(so);
166 #ifdef DIAGNOSTIC
167 if (req != PRU_SEND && req != PRU_SENDOOB && control)
168 panic("idrp_usrreq: unexpected control mbuf");
169 #endif
170 if (rp == 0 && req != PRU_ATTACH) {
171 error = EINVAL;
172 goto release;
173 }
174
175 /*
176 * Note: need to block idrp_input while changing the udp pcb queue
177 * and/or pcb addresses.
178 */
179 switch (req) {
180
181 case PRU_ATTACH:
182 if (rp != 0) {
183 error = EISCONN;
184 break;
185 }
186 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
187 error = soreserve(so, idrp_sendspace, idrp_recvspace);
188 if (error)
189 break;
190 }
191 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK|M_ZERO);
192 if (rp == 0) {
193 error = ENOBUFS;
194 break;
195 }
196 rp->rcb_socket = so;
197 LIST_INSERT_HEAD(&idrp_pcb, rp, rcb_list);
198 so->so_pcb = rp;
199 break;
200
201 case PRU_SEND:
202 if (control && control->m_len) {
203 m_freem(control);
204 m_freem(m);
205 error = EINVAL;
206 break;
207 }
208 if (nam == NULL) {
209 m_freem(m);
210 error = EINVAL;
211 break;
212 }
213 /* error checking here */
214 error = idrp_output(m, mtod(nam, struct sockaddr_iso *));
215 break;
216
217 case PRU_SENDOOB:
218 m_freem(control);
219 m_freem(m);
220 error = EOPNOTSUPP;
221 break;
222
223 case PRU_DETACH:
224 raw_detach(rp);
225 break;
226
227 case PRU_SHUTDOWN:
228 socantsendmore(so);
229 break;
230
231 case PRU_SENSE:
232 /*
233 * stat: don't bother with a blocksize.
234 */
235 return (0);
236
237 default:
238 error = EOPNOTSUPP;
239 break;
240 }
241
242 release:
243 return (error);
244 }
Cache object: 572d80f23737ec74446c09cda217c2ee
|