Commit | Line | Data |
---|---|---|
7bcd1bb8 KB |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | * | |
9f4ad8e6 | 7 | * @(#)clnp_raw.c 7.12 (Berkeley) %G% |
7bcd1bb8 KB |
8 | */ |
9 | ||
4f565be6 KS |
10 | /*********************************************************** |
11 | Copyright IBM Corporation 1987 | |
986fd057 KS |
12 | |
13 | All Rights Reserved | |
14 | ||
15 | Permission to use, copy, modify, and distribute this software and its | |
16 | documentation for any purpose and without fee is hereby granted, | |
17 | provided that the above copyright notice appear in all copies and that | |
18 | both that copyright notice and this permission notice appear in | |
19 | supporting documentation, and that the name of IBM not be | |
20 | used in advertising or publicity pertaining to distribution of the | |
21 | software without specific, written prior permission. | |
22 | ||
23 | IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
25 | IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
26 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
27 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
28 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
29 | SOFTWARE. | |
30 | ||
31 | ******************************************************************/ | |
32 | ||
33 | /* | |
34 | * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison | |
35 | */ | |
36 | /* $Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $ */ | |
37 | /* $Source: /usr/argo/sys/netiso/RCS/clnp_raw.c,v $ */ | |
986fd057 | 38 | |
5548a02f KB |
39 | #include <sys/param.h> |
40 | #include <sys/mbuf.h> | |
41 | #include <sys/domain.h> | |
42 | #include <sys/protosw.h> | |
43 | #include <sys/socket.h> | |
44 | #include <sys/socketvar.h> | |
45 | #include <sys/errno.h> | |
46 | #include <sys/time.h> | |
986fd057 | 47 | |
5548a02f KB |
48 | #include <net/if.h> |
49 | #include <net/route.h> | |
50 | #include <net/raw_cb.h> | |
986fd057 | 51 | |
5548a02f KB |
52 | #include <netiso/iso.h> |
53 | #include <netiso/iso_pcb.h> | |
54 | #include <netiso/clnp.h> | |
55 | #include <netiso/clnp_stat.h> | |
56 | #include <netiso/argo_debug.h> | |
986fd057 | 57 | |
5548a02f | 58 | #include <netiso/tp_user.h> /* XXX -- defines SOL_NETWORK */ |
a50e2bc0 | 59 | |
986fd057 KS |
60 | struct sockproto rclnp_proto = { PF_ISO, 0 }; |
61 | /* | |
62 | * FUNCTION: rclnp_input | |
63 | * | |
64 | * PURPOSE: Setup generic address an protocol structures for | |
65 | * raw input routine, then pass them along with the | |
66 | * mbuf chain. | |
67 | * | |
68 | * RETURNS: none | |
69 | * | |
70 | * SIDE EFFECTS: | |
71 | * | |
72 | * NOTES: The protocol field of rclnp_proto is set to zero indicating | |
73 | * no protocol. | |
74 | */ | |
75 | rclnp_input(m, src, dst, hdrlen) | |
76 | struct mbuf *m; /* ptr to packet */ | |
dea3dc96 KS |
77 | struct sockaddr_iso *src; /* ptr to src address */ |
78 | struct sockaddr_iso *dst; /* ptr to dest address */ | |
986fd057 KS |
79 | int hdrlen; /* length (in bytes) of clnp header */ |
80 | { | |
81 | #ifdef TROLL | |
82 | if (trollctl.tr_ops & TR_CHUCK) { | |
83 | m_freem(m); | |
84 | return; | |
85 | } | |
4d8170e5 | 86 | #endif /* TROLL */ |
986fd057 | 87 | |
9f4ad8e6 | 88 | raw_input(m, &rclnp_proto, (struct sockaddr *)src, (struct sockaddr *)dst); |
986fd057 KS |
89 | } |
90 | ||
91 | /* | |
92 | * FUNCTION: rclnp_output | |
93 | * | |
94 | * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest | |
95 | * addresses, count the number of bytes to send, and | |
96 | * call clnp_output. | |
97 | * | |
98 | * RETURNS: success - 0 | |
99 | * failure - an appropriate error code | |
100 | * | |
101 | * SIDE EFFECTS: | |
102 | * | |
103 | * NOTES: | |
104 | */ | |
105 | rclnp_output(m0, so) | |
106 | struct mbuf *m0; /* packet to send */ | |
107 | struct socket *so; /* socket to send from */ | |
108 | { | |
109 | register struct mbuf *m; /* used to scan a chain */ | |
110 | int len = 0; /* store length of chain here */ | |
a50e2bc0 | 111 | struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */ |
986fd057 | 112 | int error; /* return value of function */ |
a50e2bc0 | 113 | int flags; /* flags for clnp_output */ |
986fd057 | 114 | |
97f0cba7 | 115 | if (0 == (m0->m_flags & M_PKTHDR)) |
44f52ea5 | 116 | return (EINVAL); |
986fd057 KS |
117 | /* |
118 | * Set up src address. If user has bound socket to an address, use it. | |
119 | * Otherwise, do not specify src (clnp_output will fill it in). | |
120 | */ | |
a50e2bc0 KS |
121 | if (rp->risop_rcb.rcb_laddr) { |
122 | if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) { | |
123 | bad: | |
986fd057 KS |
124 | m_freem(m0); |
125 | return(EAFNOSUPPORT); | |
126 | } | |
986fd057 | 127 | } |
986fd057 | 128 | /* set up dest address */ |
a50e2bc0 KS |
129 | if (rp->risop_rcb.rcb_faddr == 0) |
130 | goto bad; | |
131 | rp->risop_isop.isop_sfaddr = | |
132 | *(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr; | |
133 | rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr; | |
986fd057 KS |
134 | |
135 | /* get flags and ship it off */ | |
a50e2bc0 | 136 | flags = rp->risop_flags & CLNP_VFLAGS; |
986fd057 | 137 | |
44f52ea5 KS |
138 | error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len, |
139 | flags|CLNP_NOCACHE); | |
986fd057 KS |
140 | |
141 | return (error); | |
142 | } | |
143 | ||
144 | /* | |
145 | * FUNCTION: rclnp_ctloutput | |
146 | * | |
147 | * PURPOSE: Raw clnp socket option processing | |
148 | * All options are stored inside an mbuf. | |
149 | * | |
150 | * RETURNS: success - 0 | |
151 | * failure - unix error code | |
152 | * | |
153 | * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed | |
154 | * is used. | |
155 | * | |
156 | * NOTES: | |
157 | */ | |
158 | rclnp_ctloutput(op, so, level, optname, m) | |
159 | int op; /* type of operation */ | |
160 | struct socket *so; /* ptr to socket */ | |
161 | int level; /* level of option */ | |
162 | int optname; /* name of option */ | |
163 | struct mbuf **m; /* ptr to ptr to option data */ | |
164 | { | |
165 | int error = 0; | |
a50e2bc0 | 166 | register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */ |
986fd057 KS |
167 | |
168 | IFDEBUG(D_CTLOUTPUT) | |
169 | printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n", | |
170 | op, level, optname); | |
171 | if (*m != NULL) { | |
172 | printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len); | |
173 | dump_buf(mtod((*m), caddr_t), (*m)->m_len); | |
174 | } | |
175 | ENDDEBUG | |
176 | ||
177 | #ifdef SOL_NETWORK | |
178 | if (level != SOL_NETWORK) | |
179 | error = EINVAL; | |
180 | else switch (op) { | |
181 | #else | |
182 | switch (op) { | |
4d8170e5 | 183 | #endif /* SOL_NETWORK */ |
986fd057 KS |
184 | case PRCO_SETOPT: |
185 | switch (optname) { | |
186 | case CLNPOPT_FLAGS: { | |
187 | u_short usr_flags; | |
188 | /* | |
189 | * Insure that the data passed has exactly one short in it | |
190 | */ | |
191 | if ((*m == NULL) || ((*m)->m_len != sizeof(short))) { | |
192 | error = EINVAL; | |
193 | break; | |
194 | } | |
195 | ||
196 | /* | |
197 | * Don't allow invalid flags to be set | |
198 | */ | |
199 | usr_flags = (*mtod((*m), short *)); | |
200 | ||
201 | if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { | |
202 | error = EINVAL; | |
203 | } else | |
a50e2bc0 | 204 | rp->risop_flags |= usr_flags; |
986fd057 KS |
205 | |
206 | } break; | |
207 | ||
208 | case CLNPOPT_OPTS: | |
a50e2bc0 KS |
209 | if (error = clnp_set_opts(&rp->risop_isop.isop_options, m)) |
210 | break; | |
211 | rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS); | |
212 | (void) clnp_opt_sanity(rp->risop_isop.isop_options, | |
213 | mtod(rp->risop_isop.isop_options, caddr_t), | |
214 | rp->risop_isop.isop_options->m_len, | |
215 | mtod(rp->risop_isop.isop_optindex, | |
216 | struct clnp_optidx *)); | |
986fd057 KS |
217 | break; |
218 | } | |
219 | break; | |
220 | ||
221 | case PRCO_GETOPT: | |
222 | #ifdef notdef | |
223 | /* commented out to keep hi C quiet */ | |
224 | switch (optname) { | |
225 | default: | |
226 | error = EINVAL; | |
227 | break; | |
228 | } | |
4d8170e5 | 229 | #endif /* notdef */ |
986fd057 KS |
230 | break; |
231 | default: | |
232 | error = EINVAL; | |
233 | break; | |
234 | } | |
235 | if (op == PRCO_SETOPT) { | |
236 | /* note: m_freem does not barf is *m is NULL */ | |
237 | m_freem(*m); | |
238 | *m = NULL; | |
239 | } | |
240 | ||
241 | return error; | |
242 | } | |
243 | ||
244 | /*ARGSUSED*/ | |
118a1fb8 | 245 | clnp_usrreq(so, req, m, nam, control) |
a50e2bc0 | 246 | register struct socket *so; |
986fd057 | 247 | int req; |
118a1fb8 | 248 | struct mbuf *m, *nam, *control; |
986fd057 | 249 | { |
a50e2bc0 KS |
250 | register int error = 0; |
251 | register struct rawisopcb *rp = sotorawisopcb(so); | |
252 | ||
253 | rp = sotorawisopcb(so); | |
254 | switch (req) { | |
255 | ||
256 | case PRU_ATTACH: | |
257 | if (rp) | |
258 | panic("rip_attach"); | |
259 | MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK); | |
260 | if (rp == 0) | |
261 | return (ENOBUFS); | |
262 | bzero((caddr_t)rp, sizeof *rp); | |
263 | so->so_pcb = (caddr_t)rp; | |
264 | break; | |
265 | ||
266 | case PRU_DETACH: | |
267 | if (rp == 0) | |
268 | panic("rip_detach"); | |
269 | if (rp->risop_isop.isop_options) | |
270 | m_freem(rp->risop_isop.isop_options); | |
271 | if (rp->risop_isop.isop_route.ro_rt) | |
272 | RTFREE(rp->risop_isop.isop_route.ro_rt); | |
273 | if (rp->risop_rcb.rcb_laddr) | |
274 | rp->risop_rcb.rcb_laddr = 0; | |
275 | /* free clnp cached hdr if necessary */ | |
276 | if (rp->risop_isop.isop_clnpcache != NULL) { | |
277 | struct clnp_cache *clcp = | |
278 | mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *); | |
279 | if (clcp->clc_hdr != NULL) { | |
280 | m_free(clcp->clc_hdr); | |
281 | } | |
282 | m_free(rp->risop_isop.isop_clnpcache); | |
283 | } | |
284 | if (rp->risop_isop.isop_optindex != NULL) | |
285 | m_free(rp->risop_isop.isop_optindex); | |
286 | ||
287 | break; | |
288 | ||
289 | case PRU_BIND: | |
290 | { | |
291 | struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); | |
292 | ||
293 | if (nam->m_len != sizeof(*addr)) | |
294 | return (EINVAL); | |
295 | if ((ifnet == 0) || | |
296 | (addr->siso_family != AF_ISO) || | |
297 | (addr->siso_addr.isoa_len && | |
298 | ifa_ifwithaddr((struct sockaddr *)addr) == 0)) | |
299 | return (EADDRNOTAVAIL); | |
300 | rp->risop_isop.isop_sladdr = *addr; | |
301 | rp->risop_rcb.rcb_laddr = (struct sockaddr *) | |
302 | (rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr); | |
303 | return (0); | |
304 | } | |
305 | case PRU_CONNECT: | |
306 | { | |
307 | struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *); | |
308 | ||
309 | if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr))) | |
310 | return (EINVAL); | |
311 | if (ifnet == 0) | |
312 | return (EADDRNOTAVAIL); | |
313 | if (addr->siso_family != AF_ISO) | |
314 | rp->risop_isop.isop_sfaddr = *addr; | |
315 | rp->risop_rcb.rcb_faddr = (struct sockaddr *) | |
316 | (rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr); | |
317 | soisconnected(so); | |
318 | return (0); | |
319 | } | |
320 | } | |
118a1fb8 | 321 | error = raw_usrreq(so, req, m, nam, control); |
a50e2bc0 KS |
322 | |
323 | if (error && req == PRU_ATTACH && so->so_pcb) | |
324 | free((caddr_t)rp, M_PCB); | |
325 | return (error); | |
986fd057 | 326 | } |