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