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.5 (Berkeley) 09/22/89 */ 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 sockaddr_iso rclnp_src = { sizeof(rclnp_src), AF_ISO }; 56 struct sockaddr_iso rclnp_dst = { sizeof(rclnp_src), AF_ISO }; 57 struct 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 */ 72 rclnp_input(m, src, dst, hdrlen) 73 struct mbuf *m; /* ptr to packet */ 74 struct iso_addr *src; /* ptr to src address */ 75 struct iso_addr *dst; /* ptr to dest address */ 76 int 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; 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 } 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 */ 108 rclnp_output(m0, so) 109 struct mbuf *m0; /* packet to send */ 110 struct 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 */ 114 struct rawisopcb *rp = sotorawisopcb(so); /* ptr to raw cb */ 115 int error; /* return value of function */ 116 int flags; /* flags for clnp_output */ 117 118 if (0 == m0->m_flags & M_PKTHDR) 119 return (EINVAL); 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 */ 124 if (rp->risop_rcb.rcb_laddr) { 125 if (rp->risop_isop.isop_sladdr.siso_family != AF_ISO) { 126 bad: 127 m_freem(m0); 128 return(EAFNOSUPPORT); 129 } 130 } 131 /* set up dest address */ 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; 137 138 /* get flags and ship it off */ 139 flags = rp->risop_flags & CLNP_VFLAGS; 140 141 error = clnp_output(m0, &rp->risop_isop, m0->m_pkthdr.len, 142 flags|CLNP_NOCACHE); 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 */ 161 rclnp_ctloutput(op, so, level, optname, m) 162 int op; /* type of operation */ 163 struct socket *so; /* ptr to socket */ 164 int level; /* level of option */ 165 int optname; /* name of option */ 166 struct mbuf **m; /* ptr to ptr to option data */ 167 { 168 int error = 0; 169 register struct rawisopcb *rp = sotorawisopcb(so);/* raw cb ptr */ 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 207 rp->risop_flags |= usr_flags; 208 209 } break; 210 211 case CLNPOPT_OPTS: 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 *)); 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*/ 248 clnp_usrreq(so, req, m, nam, rights, control) 249 register struct socket *so; 250 int req; 251 struct mbuf *m, *nam, *rights, *control; 252 { 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); 329 } 330