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: /var/src/sys/netiso/RCS/clnp_er.c,v 5.1 89/02/09 16:20:18 hagens Exp $ */ 28 /* $Source: /var/src/sys/netiso/RCS/clnp_er.c,v $ */ 29 30 #ifndef lint 31 static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_er.c,v 5.1 89/02/09 16:20:18 hagens Exp $"; 32 #endif lint 33 34 #ifdef ISO 35 36 #include "types.h" 37 #include "param.h" 38 #include "mbuf.h" 39 #include "domain.h" 40 #include "protosw.h" 41 #include "socket.h" 42 #include "socketvar.h" 43 #include "errno.h" 44 45 #include "../net/if.h" 46 #include "../net/route.h" 47 48 #include "iso.h" 49 #include "iso_var.h" 50 #include "iso_pcb.h" 51 #include "clnp.h" 52 #include "clnp_stat.h" 53 #include "argo_debug.h" 54 55 static struct clnp_fixed er_template = { 56 ISO8473_CLNP, /* network identifier */ 57 0, /* length */ 58 ISO8473_V1, /* version */ 59 CLNP_TTL, /* ttl */ 60 CLNP_ER, /* type */ 61 0, /* segment length */ 62 0 /* checksum */ 63 }; 64 65 /* 66 * FUNCTION: clnp_er_input 67 * 68 * PURPOSE: Process an ER pdu. 69 * 70 * RETURNS: 71 * 72 * SIDE EFFECTS: 73 * 74 * NOTES: 75 */ 76 clnp_er_input(m, src, reason) 77 struct mbuf *m; /* ptr to packet itself */ 78 struct iso_addr *src; /* ptr to src of er */ 79 u_char reason; /* reason code of er */ 80 { 81 int cmd = -1; 82 extern u_char clnp_protox[]; 83 84 IFDEBUG(D_CTLINPUT) 85 printf("clnp_er_input: m x%x, src %s, reason x%x\n", m, 86 clnp_iso_addrp(src), reason); 87 ENDDEBUG 88 89 INCSTAT(cns_errcvd); 90 91 switch (reason) { 92 case GEN_NOREAS: 93 case GEN_PROTOERR: 94 INCSTAT(er_protoerr); 95 break; 96 case GEN_BADCSUM: 97 cmd = PRC_PARAMPROB; 98 INCSTAT(er_badcsum); 99 break; 100 case GEN_CONGEST: 101 cmd = PRC_QUENCH; 102 INCSTAT(er_congest); 103 break; 104 case GEN_HDRSYNTAX: 105 cmd = PRC_PARAMPROB; 106 INCSTAT(er_protoerr); 107 break; 108 case GEN_SEGNEEDED: 109 cmd = PRC_UNREACH_NEEDFRAG; 110 INCSTAT(er_segneeded); 111 break; 112 case GEN_INCOMPLETE: 113 cmd = PRC_PARAMPROB; 114 INCSTAT(er_reassfail); 115 break; 116 case GEN_DUPOPT: 117 cmd = PRC_PARAMPROB; 118 INCSTAT(er_protoerr); 119 break; 120 case ADDR_DESTUNREACH: 121 cmd = PRC_UNREACH_HOST; 122 INCSTAT(er_dstunreach); 123 break; 124 case ADDR_DESTUNKNOWN: 125 cmd = PRC_UNREACH_PROTOCOL; 126 INCSTAT(er_dstunreach); 127 break; 128 case SRCRT_UNSPECERR: 129 case SRCRT_SYNTAX: 130 case SRCRT_UNKNOWNADDR: 131 case SRCRT_BADPATH: 132 cmd = PRC_UNREACH_SRCFAIL; 133 INCSTAT(er_srcrterr); 134 break; 135 case TTL_EXPTRANSIT: 136 cmd = PRC_TIMXCEED_INTRANS; 137 INCSTAT(er_ttlexpired); 138 break; 139 case TTL_EXPREASS: 140 cmd = PRC_TIMXCEED_REASS; 141 INCSTAT(er_ttlexpired); 142 break; 143 case DISC_UNSUPPOPT: 144 case DISC_UNSUPPVERS: 145 case DISC_UNSUPPSECURE: 146 case DISC_UNSUPPSRCRT: 147 case DISC_UNSUPPRECRT: 148 cmd = PRC_PARAMPROB; 149 INCSTAT(er_unsupported); 150 break; 151 case REASS_INTERFERE: 152 cmd = PRC_TIMXCEED_REASS; 153 INCSTAT(er_reassfail); 154 break; 155 } 156 157 /* 158 * tpclnp_ctlinput1 is called directly so that we don't 159 * have to build an iso_sockaddr out of src. 160 */ 161 if (cmd >= 0) 162 tpclnp_ctlinput1(cmd, src); 163 164 m_freem(m); 165 } 166 167 /* 168 * FUNCTION: clnp_discard 169 * 170 * PURPOSE: Discard a clnp datagram 171 * 172 * RETURNS: nothing 173 * 174 * SIDE EFFECTS: Will emit an ER pdu if possible 175 * 176 * NOTES: This code assumes that we have previously tried to pull 177 * up the header of the datagram into one mbuf. 178 */ 179 clnp_discard(m, reason) 180 struct mbuf *m; /* header of packet to discard */ 181 char reason; /* reason for discard */ 182 { 183 IFDEBUG(D_DISCARD) 184 printf("clnp_discard: m x%x, reason x%x\n", m, reason); 185 ENDDEBUG 186 187 if (m != NULL) { 188 if (m->m_len >= sizeof(struct clnp_fixed)) { 189 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *); 190 191 if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && 192 (clnp->cnf_type & CNF_ERR_OK)) { 193 clnp_emit_er(m, reason); 194 return; 195 } 196 } 197 m_freem(m); 198 } 199 } 200 201 /* 202 * FUNCTION: clnp_emit_er 203 * 204 * PURPOSE: Send an ER pdu. 205 * The src of the of the ER pdu is the host that is sending 206 * the ER (ie. us), *not* the original destination of the 207 * packet. 208 * 209 * RETURNS: nothing 210 * 211 * SIDE EFFECTS: 212 * 213 * NOTES: Takes responsibility for freeing mbuf passed 214 * This function may be called with a packet that 215 * was created by us; in this case, do not send 216 * an ER. 217 */ 218 clnp_emit_er(m, reason) 219 struct mbuf *m; /* header of packet to discard */ 220 char reason; /* reason for discard */ 221 { 222 register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *); 223 register struct clnp_fixed *er; 224 struct route_iso route; 225 struct ifnet *ifp; 226 struct sockaddr *first_hop; 227 struct iso_addr src, dst, *our_addr; 228 caddr_t hoff, hend; 229 int total_len; /* total len of dg */ 230 struct mbuf *m0; /* contains er pdu hdr */ 231 struct iso_ifaddr *ia = 0; 232 233 IFDEBUG(D_DISCARD) 234 printf("clnp_emit_er: m x%x, hdr len %d\n", m, clnp->cnf_hdr_len); 235 ENDDEBUG 236 237 bzero((caddr_t)&route, sizeof(route)); 238 239 /* 240 * If header length is incorrect, or entire header is not contained 241 * in this mbuf, we punt 242 */ 243 if ((clnp->cnf_hdr_len < CLNP_HDR_MIN) || 244 (clnp->cnf_hdr_len > CLNP_HDR_MAX) || 245 (clnp->cnf_hdr_len > m->m_len)) 246 goto bad; 247 248 /* extract src, dest address */ 249 hend = (caddr_t)clnp + clnp->cnf_hdr_len; 250 hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); 251 CLNP_EXTRACT_ADDR(dst, hoff, hend); 252 if (hoff == (caddr_t)0) { 253 goto bad; 254 } 255 CLNP_EXTRACT_ADDR(src, hoff, hend); 256 if (hoff == (caddr_t)0) { 257 goto bad; 258 } 259 260 /* 261 * Do not send ER if we generated the packet. 262 */ 263 if (clnp_ours(&src)) 264 goto bad; 265 266 /* 267 * Trim mbuf to hold only the header. 268 * This mbuf will be the 'data' of the er pdu 269 */ 270 if (m->m_next != NULL) { 271 m_freem(m->m_next); 272 m->m_next = NULL; 273 } 274 275 if (m->m_len > clnp->cnf_hdr_len) 276 m_adj(m, (int)-(m->m_len - (int)clnp->cnf_hdr_len)); 277 278 /* route er pdu: note we send pkt to src of original packet */ 279 if (clnp_route(&src, &route, /* flags */0, &first_hop, &ia) != 0) 280 goto bad; 281 282 /* compute our address based upon firsthop/ifp */ 283 if (ia) 284 our_addr = &ia->ia_addr.siso_addr; 285 else 286 goto bad; 287 ifp = ia->ia_ifp; 288 289 IFDEBUG(D_DISCARD) 290 printf("clnp_emit_er: to %s", clnp_iso_addrp(&src)); 291 printf(" from %s\n", clnp_iso_addrp(our_addr)); 292 ENDDEBUG 293 294 IFDEBUG(D_DISCARD) 295 printf("clnp_emit_er: packet routed to %s\n", 296 clnp_iso_addrp(&((struct sockaddr_iso *)first_hop)->siso_addr)); 297 ENDDEBUG 298 299 /* allocate mbuf for er pdu header: punt on no space */ 300 MGET(m0, M_DONTWAIT, MT_HEADER); 301 if (m0 == 0) 302 goto bad; 303 304 m0->m_next = m; 305 er = mtod(m0, struct clnp_fixed *); 306 *er = er_template; 307 308 /* setup src/dst on er pdu */ 309 /* NOTE REVERSAL OF SRC/DST */ 310 hoff = (caddr_t)er + sizeof(struct clnp_fixed); 311 CLNP_INSERT_ADDR(hoff, src); 312 CLNP_INSERT_ADDR(hoff, *our_addr); 313 314 /* 315 * TODO: if complete src rt was specified, then reverse path, and 316 * copy into er as option. 317 */ 318 319 /* add er option */ 320 *hoff++ = CLNPOVAL_ERREAS; /* code */ 321 *hoff++ = 2; /* length */ 322 *hoff++ = reason; /* discard reason */ 323 *hoff++ = 0; /* error localization = not specified */ 324 325 /* set length */ 326 er->cnf_hdr_len = m0->m_len = (u_char)(hoff - (caddr_t)er); 327 total_len = m0->m_len + m->m_len; 328 HTOC(er->cnf_seglen_msb, er->cnf_seglen_lsb, total_len); 329 330 /* compute checksum (on header only) */ 331 iso_gen_csum(m0, CLNP_CKSUM_OFF, (int)er->cnf_hdr_len); 332 333 /* trim packet if too large for interface */ 334 if (total_len > ifp->if_mtu) 335 m_adj(m0, -(total_len - ifp->if_mtu)); 336 337 /* send packet */ 338 (void) (*ifp->if_output)(ifp, m0, first_hop); 339 goto done; 340 341 bad: 342 m_freem(m); 343 344 done: 345 /* free route if it is a temp */ 346 if (route.ro_rt != NULL) 347 RTFREE(route.ro_rt); 348 } 349 #endif ISO 350