1 /*********************************************************** 2 Copyright IBM Corporation 1987 3 4 All Rights Reserved 5 6 Permission to use, copy, modify, and distribute this software and its 7 documentation for any purpose and without fee is hereby granted, 8 provided that the above copyright notice appear in all copies and that 9 both that copyright notice and this permission notice appear in 10 supporting documentation, and that the name of IBM not be 11 used in advertising or publicity pertaining to distribution of the 12 software without specific, written prior permission. 13 14 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20 SOFTWARE. 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 $ */ 29 /* @(#)clnp_raw.c 7.7 (Berkeley) 04/05/90 */ 30 #ifndef lint 31 static char *rcsid = "$Header: clnp_raw.c,v 4.2 88/06/29 14:58:56 hagens Exp $"; 32 #endif lint 33 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" 42 43 #include "../net/if.h" 44 #include "../net/route.h" 45 #include "../net/raw_cb.h" 46 47 #include "iso.h" 48 #include "iso_pcb.h" 49 #include "clnp.h" 50 #include "clnp_stat.h" 51 #include "argo_debug.h" 52 53 #include "tp_user.h"/* XXX -- defines SOL_NETWORK */ 54 55 struct 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 */ 70 rclnp_input(m, src, dst, hdrlen) 71 struct mbuf *m; /* ptr to packet */ 72 struct sockaddr_iso *src; /* ptr to src address */ 73 struct sockaddr_iso *dst; /* ptr to dest address */ 74 int 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 83 if (raw_input(m, &rclnp_proto, (struct sockaddr *)src, 84 (struct sockaddr *)dst) == 0) { 85 clnp_stat.cns_delivered--; 86 clnp_stat.cns_noproto++; 87 } 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 */ 104 rclnp_output(m0, so) 105 struct mbuf *m0; /* packet to send */ 106 struct 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 */ 110 struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */ 111 int error; /* return value of function */ 112 int flags; /* flags for clnp_output */ 113 114 if (0 == m0->m_flags & M_PKTHDR) 115 return (EINVAL); 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 */ 120 if (rp->risop_rcb.rcb_laddr) { 121 if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) { 122 bad: 123 m_freem(m0); 124 return(EAFNOSUPPORT); 125 } 126 } 127 /* set up dest address */ 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; 133 134 /* get flags and ship it off */ 135 flags = rp->risop_flags & CLNP_VFLAGS; 136 137 error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len, 138 flags|CLNP_NOCACHE); 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 */ 157 rclnp_ctloutput(op, so, level, optname, m) 158 int op; /* type of operation */ 159 struct socket *so; /* ptr to socket */ 160 int level; /* level of option */ 161 int optname; /* name of option */ 162 struct mbuf **m; /* ptr to ptr to option data */ 163 { 164 int error = 0; 165 register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */ 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 203 rp->risop_flags |= usr_flags; 204 205 } break; 206 207 case CLNPOPT_OPTS: 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 *)); 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*/ 244 clnp_usrreq(so, req, m, nam, control) 245 register struct socket *so; 246 int req; 247 struct mbuf *m, *nam, *control; 248 { 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 } 320 error = raw_usrreq(so, req, m, nam, control); 321 322 if (error && req == PRU_ATTACH && so->so_pcb) 323 free((caddr_t)rp, M_PCB); 324 return (error); 325 } 326