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