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