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