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 #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 "../h/types.h" 36 #include "../h/param.h" 37 #include "../h/mbuf.h" 38 #include "../h/domain.h" 39 #include "../h/protosw.h" 40 #include "../h/socket.h" 41 #include "../h/socketvar.h" 42 #include "../h/errno.h" 43 #include "../h/time.h" 44 45 #include "../net/if.h" 46 #include "../net/route.h" 47 #include "../net/raw_cb.h" 48 49 #include "../netiso/iso.h" 50 #include "../netiso/iso_pcb.h" 51 #include "../netiso/clnp.h" 52 #include "../netiso/clnp_stat.h" 53 #include "../netiso/argo_debug.h" 54 55 struct sockaddr_iso rclnp_src = { AF_ISO }; 56 struct sockaddr_iso rclnp_dst = { 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 raw_input(m, &rclnp_proto, (struct sockaddr *)&rclnp_src, 88 (struct sockaddr *)&rclnp_dst); 89 } 90 91 /* 92 * FUNCTION: rclnp_output 93 * 94 * PURPOSE: Prepare to send a raw clnp packet. Setup src and dest 95 * addresses, count the number of bytes to send, and 96 * call clnp_output. 97 * 98 * RETURNS: success - 0 99 * failure - an appropriate error code 100 * 101 * SIDE EFFECTS: 102 * 103 * NOTES: 104 */ 105 rclnp_output(m0, so) 106 struct mbuf *m0; /* packet to send */ 107 struct socket *so; /* socket to send from */ 108 { 109 register struct mbuf *m; /* used to scan a chain */ 110 int len = 0; /* store length of chain here */ 111 struct rawcb *rp = sotorawcb(so); /* ptr to raw cb */ 112 int error; /* return value of function */ 113 u_int flags; /* flags for clnp_output */ 114 struct isopcb isopcb; /* isopcb used to interface w/clnp */ 115 116 /* Calculate length of data */ 117 for (m = m0; m; m = m->m_next) 118 len += m->m_len; 119 120 bzero((caddr_t)&isopcb, sizeof(isopcb)); 121 122 /* 123 * Set up src address. If user has bound socket to an address, use it. 124 * Otherwise, do not specify src (clnp_output will fill it in). 125 */ 126 if (rp->rcb_flags & RAW_LADDR) { 127 if (rp->rcb_laddr.sa_family != AF_ISO) { 128 m_freem(m0); 129 return(EAFNOSUPPORT); 130 } 131 bcopy((caddr_t)&rp->rcb_laddr, &isopcb.isop_laddr, 132 sizeof(struct sockaddr_iso)); 133 } 134 135 /* set up route structure, if route is present */ 136 if (rp->rcb_route.ro_rt != NULL) 137 bcopy((caddr_t)&rp->rcb_route, (caddr_t)&isopcb.isop_route, 138 sizeof(struct route)); 139 140 /* set up dest address */ 141 bcopy((caddr_t)&rp->rcb_faddr, &isopcb.isop_faddr, 142 sizeof(struct sockaddr_iso)); 143 144 /* 145 * setup option index - this was done when option was set, but raw 146 * cb has no place to put it. 147 */ 148 if (rp->rcb_options != NULL) { 149 isopcb.isop_options = rp->rcb_options; 150 isopcb.isop_optindex = m_get(M_WAIT, MT_SOOPTS); 151 (void) clnp_opt_sanity(isopcb.isop_options, 152 mtod(isopcb.isop_options, caddr_t), isopcb.isop_options->m_len, 153 mtod(isopcb.isop_optindex, struct clnp_optidx *)); 154 } 155 156 /* get flags and ship it off */ 157 flags = rp->rcb_flags & CLNP_VFLAGS; 158 159 #ifdef TROLL 160 if (trollctl.tr_ops & TR_BLAST) { 161 register int i; 162 struct timeval start, stop; 163 extern struct timeval time; 164 struct mbuf *mbuf_orig; 165 166 mbuf_orig = m0; 167 start = time; 168 for (i=0; i<trollctl.tr_blast_cnt; i++) { 169 m0 = m_copy(mbuf_orig, 0, M_COPYALL); 170 if (m0 == NULL) { 171 error = ENOBUFS; 172 } else { 173 error = clnp_output(m0, &isopcb, len, flags); 174 } 175 if (error) 176 break; 177 } 178 stop = time; 179 printf("rclnp_output: %d pkts in %d sec\n", i, 180 stop.tv_sec - start.tv_sec); 181 m_freem(mbuf_orig); 182 } else { 183 /* 184 * Don't bother creating the cache since this is raw; probably 185 * a one shot send 186 */ 187 error = clnp_output(m0, &isopcb, len, flags|CLNP_NOCACHE); 188 } 189 #else 190 error = clnp_output(m0, &isopcb, len, flags|CLNP_NOCACHE); 191 #endif TROLL 192 193 if (isopcb.isop_route.ro_rt) 194 RTFREE(isopcb.isop_route.ro_rt); 195 196 /* free clnp cached hdr if necessary */ 197 if (isopcb.isop_clnpcache != NULL) { 198 struct clnp_cache *clcp = 199 mtod(isopcb.isop_clnpcache, struct clnp_cache *); 200 if (clcp->clc_hdr != NULL) { 201 m_free(clcp->clc_hdr); 202 } 203 m_free(isopcb.isop_clnpcache); 204 } 205 206 if (isopcb.isop_optindex != NULL) 207 m_free(isopcb.isop_optindex); 208 209 return (error); 210 } 211 212 /* 213 * FUNCTION: rclnp_ctloutput 214 * 215 * PURPOSE: Raw clnp socket option processing 216 * All options are stored inside an mbuf. 217 * 218 * RETURNS: success - 0 219 * failure - unix error code 220 * 221 * SIDE EFFECTS: If the options mbuf does not exist, it the mbuf passed 222 * is used. 223 * 224 * NOTES: 225 */ 226 rclnp_ctloutput(op, so, level, optname, m) 227 int op; /* type of operation */ 228 struct socket *so; /* ptr to socket */ 229 int level; /* level of option */ 230 int optname; /* name of option */ 231 struct mbuf **m; /* ptr to ptr to option data */ 232 { 233 int error = 0; 234 register struct rawcb *rp = sotorawcb(so);/* raw cb ptr */ 235 236 IFDEBUG(D_CTLOUTPUT) 237 printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n", 238 op, level, optname); 239 if (*m != NULL) { 240 printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len); 241 dump_buf(mtod((*m), caddr_t), (*m)->m_len); 242 } 243 ENDDEBUG 244 245 #ifdef SOL_NETWORK 246 if (level != SOL_NETWORK) 247 error = EINVAL; 248 else switch (op) { 249 #else 250 switch (op) { 251 #endif SOL_NETWORK 252 case PRCO_SETOPT: 253 switch (optname) { 254 case CLNPOPT_FLAGS: { 255 u_short usr_flags; 256 /* 257 * Insure that the data passed has exactly one short in it 258 */ 259 if ((*m == NULL) || ((*m)->m_len != sizeof(short))) { 260 error = EINVAL; 261 break; 262 } 263 264 /* 265 * Don't allow invalid flags to be set 266 */ 267 usr_flags = (*mtod((*m), short *)); 268 269 if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { 270 error = EINVAL; 271 } else 272 rp->rcb_flags |= usr_flags; 273 274 } break; 275 276 case CLNPOPT_OPTS: 277 error = clnp_set_opts(&rp->rcb_options, m); 278 break; 279 } 280 break; 281 282 case PRCO_GETOPT: 283 #ifdef notdef 284 /* commented out to keep hi C quiet */ 285 switch (optname) { 286 default: 287 error = EINVAL; 288 break; 289 } 290 #endif notdef 291 break; 292 default: 293 error = EINVAL; 294 break; 295 } 296 if (op == PRCO_SETOPT) { 297 /* note: m_freem does not barf is *m is NULL */ 298 m_freem(*m); 299 *m = NULL; 300 } 301 302 return error; 303 } 304 305 /*ARGSUSED*/ 306 clnp_usrreq(so, req, m, nam, rights) 307 struct socket *so; 308 int req; 309 struct mbuf *m, *nam, *rights; 310 { 311 return EPROTOTYPE; 312 } 313 #endif ISO 314