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