mitre decbit 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 $ */
4f565be6 29/* @(#)clnp_raw.c 7.5 (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
55struct sockaddr_iso rclnp_src = { sizeof(rclnp_src), AF_ISO };
56struct sockaddr_iso rclnp_dst = { sizeof(rclnp_src), AF_ISO };
986fd057
KS
57struct sockproto rclnp_proto = { PF_ISO, 0 };
58/*
59 * FUNCTION: rclnp_input
60 *
61 * PURPOSE: Setup generic address an protocol structures for
62 * raw input routine, then pass them along with the
63 * mbuf chain.
64 *
65 * RETURNS: none
66 *
67 * SIDE EFFECTS:
68 *
69 * NOTES: The protocol field of rclnp_proto is set to zero indicating
70 * no protocol.
71 */
72rclnp_input(m, src, dst, hdrlen)
73struct mbuf *m; /* ptr to packet */
74struct iso_addr *src; /* ptr to src address */
75struct iso_addr *dst; /* ptr to dest address */
76int hdrlen; /* length (in bytes) of clnp header */
77{
78#ifdef TROLL
79 if (trollctl.tr_ops & TR_CHUCK) {
80 m_freem(m);
81 return;
82 }
83#endif TROLL
84
85 rclnp_src.siso_addr = *src;
86 rclnp_dst.siso_addr = *dst;
4f565be6
KS
87 if (raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src,
88 (struct sockaddr *)&rclnp_dst) == 0) {
89 clnp_stat.cns_delivered--;
90 clnp_stat.cns_noproto++;
91 }
986fd057
KS
92}
93
94/*
95 * FUNCTION: rclnp_output
96 *
97 * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest
98 * addresses, count the number of bytes to send, and
99 * call clnp_output.
100 *
101 * RETURNS: success - 0
102 * failure - an appropriate error code
103 *
104 * SIDE EFFECTS:
105 *
106 * NOTES:
107 */
108rclnp_output(m0, so)
109struct mbuf *m0; /* packet to send */
110struct socket *so; /* socket to send from */
111{
112 register struct mbuf *m; /* used to scan a chain */
113 int len = 0; /* store length of chain here */
a50e2bc0 114 struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */
986fd057 115 int error; /* return value of function */
a50e2bc0 116 int flags; /* flags for clnp_output */
986fd057 117
44f52ea5
KS
118 if (0 == m0->m_flags & M_PKTHDR)
119 return (EINVAL);
986fd057
KS
120 /*
121 * Set up src address. If user has bound socket to an address, use it.
122 * Otherwise, do not specify src (clnp_output will fill it in).
123 */
a50e2bc0
KS
124 if (rp->risop_rcb.rcb_laddr) {
125 if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) {
126bad:
986fd057
KS
127 m_freem(m0);
128 return(EAFNOSUPPORT);
129 }
986fd057 130 }
986fd057 131 /* set up dest address */
a50e2bc0
KS
132 if (rp->risop_rcb.rcb_faddr == 0)
133 goto bad;
134 rp->risop_isop.isop_sfaddr =
135 *(struct sockaddr_iso *)rp->risop_rcb.rcb_faddr;
136 rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr;
986fd057
KS
137
138 /* get flags and ship it off */
a50e2bc0 139 flags = rp->risop_flags & CLNP_VFLAGS;
986fd057 140
44f52ea5
KS
141 error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len,
142 flags|CLNP_NOCACHE);
986fd057
KS
143
144 return (error);
145}
146
147/*
148 * FUNCTION: rclnp_ctloutput
149 *
150 * PURPOSE: Raw clnp socket option processing
151 * All options are stored inside an mbuf.
152 *
153 * RETURNS: success - 0
154 * failure - unix error code
155 *
156 * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed
157 * is used.
158 *
159 * NOTES:
160 */
161rclnp_ctloutput(op, so, level, optname, m)
162int op; /* type of operation */
163struct socket *so; /* ptr to socket */
164int level; /* level of option */
165int optname; /* name of option */
166struct mbuf **m; /* ptr to ptr to option data */
167{
168 int error = 0;
a50e2bc0 169 register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */
986fd057
KS
170
171 IFDEBUG(D_CTLOUTPUT)
172 printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n",
173 op, level, optname);
174 if (*m != NULL) {
175 printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len);
176 dump_buf(mtod((*m), caddr_t), (*m)->m_len);
177 }
178 ENDDEBUG
179
180#ifdef SOL_NETWORK
181 if (level != SOL_NETWORK)
182 error = EINVAL;
183 else switch (op) {
184#else
185 switch (op) {
186#endif SOL_NETWORK
187 case PRCO_SETOPT:
188 switch (optname) {
189 case CLNPOPT_FLAGS: {
190 u_short usr_flags;
191 /*
192 * Insure that the data passed has exactly one short in it
193 */
194 if ((*m == NULL) || ((*m)->m_len != sizeof(short))) {
195 error = EINVAL;
196 break;
197 }
198
199 /*
200 * Don't allow invalid flags to be set
201 */
202 usr_flags = (*mtod((*m), short *));
203
204 if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) {
205 error = EINVAL;
206 } else
a50e2bc0 207 rp->risop_flags |= usr_flags;
986fd057
KS
208
209 } break;
210
211 case CLNPOPT_OPTS:
a50e2bc0
KS
212 if (error = clnp_set_opts(&rp->risop_isop.isop_options, m))
213 break;
214 rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS);
215 (void) clnp_opt_sanity(rp->risop_isop.isop_options,
216 mtod(rp->risop_isop.isop_options, caddr_t),
217 rp->risop_isop.isop_options->m_len,
218 mtod(rp->risop_isop.isop_optindex,
219 struct clnp_optidx *));
986fd057
KS
220 break;
221 }
222 break;
223
224 case PRCO_GETOPT:
225#ifdef notdef
226 /* commented out to keep hi C quiet */
227 switch (optname) {
228 default:
229 error = EINVAL;
230 break;
231 }
232#endif notdef
233 break;
234 default:
235 error = EINVAL;
236 break;
237 }
238 if (op == PRCO_SETOPT) {
239 /* note: m_freem does not barf is *m is NULL */
240 m_freem(*m);
241 *m = NULL;
242 }
243
244 return error;
245}
246
247/*ARGSUSED*/
a50e2bc0
KS
248clnp_usrreq(so, req, m, nam, rights, control)
249 register struct socket *so;
986fd057 250 int req;
a50e2bc0 251 struct mbuf *m, *nam, *rights, *control;
986fd057 252{
a50e2bc0
KS
253 register int error = 0;
254 register struct rawisopcb *rp = sotorawisopcb(so);
255
256 rp = sotorawisopcb(so);
257 switch (req) {
258
259 case PRU_ATTACH:
260 if (rp)
261 panic("rip_attach");
262 MALLOC(rp, struct rawisopcb *, sizeof *rp, M_PCB, M_WAITOK);
263 if (rp == 0)
264 return (ENOBUFS);
265 bzero((caddr_t)rp, sizeof *rp);
266 so->so_pcb = (caddr_t)rp;
267 break;
268
269 case PRU_DETACH:
270 if (rp == 0)
271 panic("rip_detach");
272 if (rp->risop_isop.isop_options)
273 m_freem(rp->risop_isop.isop_options);
274 if (rp->risop_isop.isop_route.ro_rt)
275 RTFREE(rp->risop_isop.isop_route.ro_rt);
276 if (rp->risop_rcb.rcb_laddr)
277 rp->risop_rcb.rcb_laddr = 0;
278 /* free clnp cached hdr if necessary */
279 if (rp->risop_isop.isop_clnpcache != NULL) {
280 struct clnp_cache *clcp =
281 mtod(rp->risop_isop.isop_clnpcache, struct clnp_cache *);
282 if (clcp->clc_hdr != NULL) {
283 m_free(clcp->clc_hdr);
284 }
285 m_free(rp->risop_isop.isop_clnpcache);
286 }
287 if (rp->risop_isop.isop_optindex != NULL)
288 m_free(rp->risop_isop.isop_optindex);
289
290 break;
291
292 case PRU_BIND:
293 {
294 struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
295
296 if (nam->m_len != sizeof(*addr))
297 return (EINVAL);
298 if ((ifnet == 0) ||
299 (addr->siso_family != AF_ISO) ||
300 (addr->siso_addr.isoa_len &&
301 ifa_ifwithaddr((struct sockaddr *)addr) == 0))
302 return (EADDRNOTAVAIL);
303 rp->risop_isop.isop_sladdr = *addr;
304 rp->risop_rcb.rcb_laddr = (struct sockaddr *)
305 (rp->risop_isop.isop_laddr = &rp->risop_isop.isop_sladdr);
306 return (0);
307 }
308 case PRU_CONNECT:
309 {
310 struct sockaddr_iso *addr = mtod(nam, struct sockaddr_iso *);
311
312 if ((nam->m_len > sizeof(*addr)) || (addr->siso_len > sizeof(*addr)))
313 return (EINVAL);
314 if (ifnet == 0)
315 return (EADDRNOTAVAIL);
316 if (addr->siso_family != AF_ISO)
317 rp->risop_isop.isop_sfaddr = *addr;
318 rp->risop_rcb.rcb_faddr = (struct sockaddr *)
319 (rp->risop_isop.isop_faddr = &rp->risop_isop.isop_sfaddr);
320 soisconnected(so);
321 return (0);
322 }
323 }
324 error = raw_usrreq(so, req, m, nam, rights, control);
325
326 if (error && req == PRU_ATTACH && so->so_pcb)
327 free((caddr_t)rp, M_PCB);
328 return (error);
986fd057 329}