1: /* 2: * Copyright (c) 1984, 1988 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: * 12: * @(#)ns_error.c 7.5 (Berkeley) 2/4/88 13: */ 14: 15: #include "param.h" 16: #ifdef NS 17: #include "systm.h" 18: #include "mbuf.h" 19: #include "protosw.h" 20: #include "socket.h" 21: #include "time.h" 22: #include "kernel.h" 23: 24: #include "../net/route.h" 25: 26: #include "ns.h" 27: #include "ns_pcb.h" 28: #include "idp.h" 29: #include "ns_error.h" 30: 31: #ifdef lint 32: #define NS_ERRPRINTFS 1 33: #endif 34: 35: #ifdef NS_ERRPRINTFS 36: /* 37: * NS_ERR routines: error generation, receive packet processing, and 38: * routines to turnaround packets back to the originator. 39: */ 40: int ns_errprintfs = 0; 41: #endif 42: 43: ns_err_x(c) 44: { 45: register u_short *w, *lim, *base = ns_errstat.ns_es_codes; 46: u_short x = c; 47: 48: /* 49: * zero is a legit error code, handle specially 50: */ 51: if (x == 0) 52: return (0); 53: lim = base + NS_ERR_MAX - 1; 54: for (w = base + 1; w < lim; w++) { 55: if (*w == 0) 56: *w = x; 57: if (*w == x) 58: break; 59: } 60: return (w - base); 61: } 62: 63: /* 64: * Generate an error packet of type error 65: * in response to bad packet. 66: */ 67: 68: ns_error(om, type, param) 69: struct mbuf *om; 70: int type; 71: { 72: register struct ns_epidp *ep; 73: struct mbuf *m; 74: struct idp *nip; 75: register struct idp *oip = mtod(om, struct idp *); 76: extern int idpcksum; 77: 78: /* 79: * If this packet was sent to the echo port, 80: * and nobody was there, just echo it. 81: * (Yes, this is a wart!) 82: */ 83: if (type==NS_ERR_NOSOCK && 84: oip->idp_dna.x_port==htons(2) && 85: (type = ns_echo(oip)==0)) 86: return; 87: 88: #ifdef NS_ERRPRINTFS 89: if (ns_errprintfs) 90: printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 91: #endif 92: /* 93: * Don't Generate error packets in response to multicasts. 94: */ 95: if (oip->idp_dna.x_host.c_host[0] & 1) 96: goto free; 97: 98: ns_errstat.ns_es_error++; 99: /* 100: * Make sure that the old IDP packet had 30 bytes of data to return; 101: * if not, don't bother. Also don't EVER error if the old 102: * packet protocol was NS_ERR. 103: */ 104: if (oip->idp_len < sizeof(struct idp)) { 105: ns_errstat.ns_es_oldshort++; 106: goto free; 107: } 108: if (oip->idp_pt == NSPROTO_ERROR) { 109: ns_errstat.ns_es_oldns_err++; 110: goto free; 111: } 112: 113: /* 114: * First, formulate ns_err message 115: */ 116: m = m_get(M_DONTWAIT, MT_HEADER); 117: if (m == NULL) 118: goto free; 119: m->m_len = sizeof(*ep); 120: m->m_off = MMAXOFF - m->m_len; 121: ep = mtod(m, struct ns_epidp *); 122: if ((u_int)type > NS_ERR_TOO_BIG) 123: panic("ns_err_error"); 124: ns_errstat.ns_es_outhist[ns_err_x(type)]++; 125: ep->ns_ep_errp.ns_err_num = htons((u_short)type); 126: ep->ns_ep_errp.ns_err_param = htons((u_short)param); 127: bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 128: nip = &ep->ns_ep_idp; 129: nip->idp_len = sizeof(*ep); 130: nip->idp_len = htons((u_short)nip->idp_len); 131: nip->idp_pt = NSPROTO_ERROR; 132: nip->idp_tc = 0; 133: nip->idp_dna = oip->idp_sna; 134: nip->idp_sna = oip->idp_dna; 135: if (idpcksum) { 136: nip->idp_sum = 0; 137: nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 138: } else 139: nip->idp_sum = 0xffff; 140: (void) ns_output(dtom(nip), (struct route *)0, 0); 141: 142: free: 143: m_freem(dtom(oip)); 144: } 145: 146: ns_printhost(p) 147: register struct ns_addr *p; 148: { 149: 150: printf("<net:%x%x,host:%x%x%x,port:%x>", 151: p->x_net.s_net[0], 152: p->x_net.s_net[1], 153: p->x_host.s_host[0], 154: p->x_host.s_host[1], 155: p->x_host.s_host[2], 156: p->x_port); 157: 158: } 159: 160: /* 161: * Process a received NS_ERR message. 162: */ 163: ns_err_input(m) 164: struct mbuf *m; 165: { 166: register struct ns_errp *ep; 167: register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 168: register int i; 169: int type, code, param; 170: 171: /* 172: * Locate ns_err structure in mbuf, and check 173: * that not corrupted and of at least minimum length. 174: */ 175: #ifdef NS_ERRPRINTFS 176: if (ns_errprintfs) { 177: printf("ns_err_input from "); 178: ns_printhost(&epidp->ns_ep_idp.idp_sna); 179: printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 180: } 181: #endif 182: i = sizeof (struct ns_epidp); 183: if ((m->m_off > MMAXOFF || m->m_len < i) && 184: (m = m_pullup(m, i)) == 0) { 185: ns_errstat.ns_es_tooshort++; 186: return; 187: } 188: ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 189: type = ntohs(ep->ns_err_num); 190: param = ntohs(ep->ns_err_param); 191: ns_errstat.ns_es_inhist[ns_err_x(type)]++; 192: 193: #ifdef NS_ERRPRINTFS 194: /* 195: * Message type specific processing. 196: */ 197: if (ns_errprintfs) 198: printf("ns_err_input, type %d param %d\n", type, param); 199: #endif 200: if (type >= NS_ERR_TOO_BIG) { 201: goto badcode; 202: } 203: ns_errstat.ns_es_outhist[ns_err_x(type)]++; 204: switch (type) { 205: 206: case NS_ERR_UNREACH_HOST: 207: code = PRC_UNREACH_NET; 208: goto deliver; 209: 210: case NS_ERR_TOO_OLD: 211: code = PRC_TIMXCEED_INTRANS; 212: goto deliver; 213: 214: case NS_ERR_TOO_BIG: 215: code = PRC_MSGSIZE; 216: goto deliver; 217: 218: case NS_ERR_FULLUP: 219: code = PRC_QUENCH; 220: goto deliver; 221: 222: case NS_ERR_NOSOCK: 223: code = PRC_UNREACH_PORT; 224: goto deliver; 225: 226: case NS_ERR_UNSPEC_T: 227: case NS_ERR_BADSUM_T: 228: case NS_ERR_BADSUM: 229: case NS_ERR_UNSPEC: 230: code = PRC_PARAMPROB; 231: goto deliver; 232: 233: deliver: 234: /* 235: * Problem with datagram; advise higher level routines. 236: */ 237: #ifdef NS_ERRPRINTFS 238: if (ns_errprintfs) 239: printf("deliver to protocol %d\n", 240: ep->ns_err_idp.idp_pt); 241: #endif 242: switch(ep->ns_err_idp.idp_pt) { 243: case NSPROTO_SPP: 244: spp_ctlinput(code, (caddr_t)ep); 245: break; 246: 247: default: 248: idp_ctlinput(code, (caddr_t)ep); 249: } 250: 251: goto free; 252: 253: default: 254: badcode: 255: ns_errstat.ns_es_badcode++; 256: goto free; 257: 258: } 259: free: 260: m_freem(m); 261: } 262: 263: #ifdef notdef 264: u_long 265: nstime() 266: { 267: int s = splclock(); 268: u_long t; 269: 270: t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 271: splx(s); 272: return (htonl(t)); 273: } 274: #endif 275: 276: ns_echo(idp) 277: register struct idp *idp; 278: { 279: struct mbuf *m = dtom(idp); 280: register struct echo { 281: struct idp ec_idp; 282: u_short ec_op; /* Operation, 1 = request, 2 = reply */ 283: } *ec = (struct echo *)idp; 284: struct ns_addr temp; 285: 286: if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 287: if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 288: 289: ec->ec_op = htons(2); 290: 291: temp = idp->idp_dna; 292: idp->idp_dna = idp->idp_sna; 293: idp->idp_sna = temp; 294: 295: if (idp->idp_sum != 0xffff) { 296: idp->idp_sum = 0; 297: idp->idp_sum = ns_cksum(m, 298: (int)(((ntohs(idp->idp_len) - 1)|1)+1)); 299: } 300: (void) ns_output(m, (struct route *)0, NS_FORWARDING); 301: return(0); 302: } 303: #endif