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