123206Smckusick /* 2*33411Ssklower * Copyright (c) 1984, 1988 Regents of the University of California. 333371Ssklower * All rights reserved. 423206Smckusick * 533371Ssklower * Redistribution and use in source and binary forms are permitted 633371Ssklower * provided that this notice is preserved and that due credit is given 733371Ssklower * to the University of California at Berkeley. The name of the University 833371Ssklower * may not be used to endorse or promote products derived from this 933371Ssklower * software without specific prior written permission. This software 1033371Ssklower * is provided ``as is'' without express or implied warranty. 1133371Ssklower * 12*33411Ssklower * @(#)ns_error.c 7.4 (Berkeley) 01/28/88 1323206Smckusick */ 1421483Ssklower 1521483Ssklower #include "param.h" 1621483Ssklower #include "systm.h" 1721483Ssklower #include "mbuf.h" 1821483Ssklower #include "protosw.h" 1921483Ssklower #include "socket.h" 2021483Ssklower #include "time.h" 2121483Ssklower #include "kernel.h" 2221483Ssklower 2321483Ssklower #include "../net/route.h" 2421483Ssklower 2521483Ssklower #include "ns.h" 2621483Ssklower #include "ns_pcb.h" 2721483Ssklower #include "idp.h" 2821483Ssklower #include "ns_error.h" 2921483Ssklower 3024226Ssklower #ifdef lint 3124226Ssklower #define NS_ERRPRINTFS 1 3224226Ssklower #endif 3324226Ssklower 3421483Ssklower #ifdef NS_ERRPRINTFS 3521483Ssklower /* 3621483Ssklower * NS_ERR routines: error generation, receive packet processing, and 3721746Ssklower * routines to turnaround packets back to the originator. 3821483Ssklower */ 3921483Ssklower int ns_errprintfs = 0; 4021483Ssklower #endif 4121483Ssklower 42*33411Ssklower ns_error_x(c) 43*33411Ssklower { 44*33411Ssklower register u_short *w, *lim, *base = ns_errstat.ns_es_codes; 45*33411Ssklower u_short x = c; 46*33411Ssklower 47*33411Ssklower /* 48*33411Ssklower * zero is a legit error code, handle specially 49*33411Ssklower */ 50*33411Ssklower if (x == 0) 51*33411Ssklower return (0); 52*33411Ssklower lim = base + NS_ERR_MAX - 1; 53*33411Ssklower for (w = base + 1; w < lim; w++) { 54*33411Ssklower if (*w == 0) 55*33411Ssklower *w = x; 56*33411Ssklower if (*w == x) 57*33411Ssklower break; 58*33411Ssklower } 59*33411Ssklower return (w - base); 60*33411Ssklower } 61*33411Ssklower 6221483Ssklower /* 6321483Ssklower * Generate an error packet of type error 6421483Ssklower * in response to bad packet. 6521483Ssklower */ 6621483Ssklower 6721483Ssklower ns_error(om, type, param) 6821483Ssklower struct mbuf *om; 6921483Ssklower int type; 7021483Ssklower { 7121483Ssklower register struct ns_epidp *ep; 7221483Ssklower struct mbuf *m; 7321483Ssklower struct idp *nip; 7421483Ssklower register struct idp *oip = mtod(om, struct idp *); 7521483Ssklower extern int idpcksum; 7621483Ssklower 7721746Ssklower /* 7821746Ssklower * If this packet was sent to the echo port, 7921746Ssklower * and nobody was there, just echo it. 8021746Ssklower * (Yes, this is a wart!) 8121746Ssklower */ 8221746Ssklower if (type==NS_ERR_NOSOCK && 8321746Ssklower oip->idp_dna.x_port==htons(2) && 8421746Ssklower (type = ns_echo(oip)==0)) 8521746Ssklower return; 8621746Ssklower 8721483Ssklower #ifdef NS_ERRPRINTFS 8821483Ssklower if (ns_errprintfs) 8921483Ssklower printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 9021483Ssklower #endif 9123980Ssklower /* 9223980Ssklower * Don't Generate error packets in response to multicasts. 9323980Ssklower */ 9423980Ssklower if (oip->idp_dna.x_host.c_host[0] & 1) 9523980Ssklower goto free; 9623980Ssklower 9721483Ssklower ns_errstat.ns_es_error++; 9821483Ssklower /* 9921483Ssklower * Make sure that the old IDP packet had 30 bytes of data to return; 10021483Ssklower * if not, don't bother. Also don't EVER error if the old 10121483Ssklower * packet protocol was NS_ERR. 10221483Ssklower */ 10321483Ssklower if (oip->idp_len < sizeof(struct idp)) { 10421483Ssklower ns_errstat.ns_es_oldshort++; 10521483Ssklower goto free; 10621483Ssklower } 10721483Ssklower if (oip->idp_pt == NSPROTO_ERROR) { 10821483Ssklower ns_errstat.ns_es_oldns_err++; 10921483Ssklower goto free; 11021483Ssklower } 11121483Ssklower 11221483Ssklower /* 11321483Ssklower * First, formulate ns_err message 11421483Ssklower */ 11521483Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 11621483Ssklower if (m == NULL) 11721483Ssklower goto free; 11821483Ssklower m->m_len = sizeof(*ep); 11921483Ssklower m->m_off = MMAXOFF - m->m_len; 12021483Ssklower ep = mtod(m, struct ns_epidp *); 12121483Ssklower if ((u_int)type > NS_ERR_TOO_BIG) 12221483Ssklower panic("ns_err_error"); 12321483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 12424226Ssklower ep->ns_ep_errp.ns_err_num = htons((u_short)type); 12524226Ssklower ep->ns_ep_errp.ns_err_param = htons((u_short)param); 12621483Ssklower bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 12721483Ssklower nip = &ep->ns_ep_idp; 12821483Ssklower nip->idp_len = sizeof(*ep); 12921483Ssklower nip->idp_len = htons((u_short)nip->idp_len); 13021483Ssklower nip->idp_pt = NSPROTO_ERROR; 13121483Ssklower nip->idp_tc = 0; 13221483Ssklower nip->idp_dna = oip->idp_sna; 13321483Ssklower nip->idp_sna = oip->idp_dna; 13421483Ssklower if (idpcksum) { 13521483Ssklower nip->idp_sum = 0; 13621483Ssklower nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 13721483Ssklower } else 13821483Ssklower nip->idp_sum = 0xffff; 13924226Ssklower (void) ns_output(dtom(nip), (struct route *)0, 0); 14021483Ssklower 14121483Ssklower free: 14221483Ssklower m_freem(dtom(oip)); 14321483Ssklower } 14421483Ssklower 14521483Ssklower ns_printhost(p) 14621483Ssklower register struct ns_addr *p; 14721483Ssklower { 14821483Ssklower 14921483Ssklower printf("<net:%x%x,host:%x%x%x,port:%x>", 15021483Ssklower p->x_net.s_net[0], 15121483Ssklower p->x_net.s_net[1], 15221483Ssklower p->x_host.s_host[0], 15321483Ssklower p->x_host.s_host[1], 15421483Ssklower p->x_host.s_host[2], 15521483Ssklower p->x_port); 15621483Ssklower 15721483Ssklower } 15821483Ssklower 15921483Ssklower /* 16021483Ssklower * Process a received NS_ERR message. 16121483Ssklower */ 16221483Ssklower ns_err_input(m) 16321483Ssklower struct mbuf *m; 16421483Ssklower { 16521483Ssklower register struct ns_errp *ep; 16621483Ssklower register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 16721483Ssklower register int i; 16821483Ssklower int type, code, param; 16921483Ssklower 17021483Ssklower /* 17121483Ssklower * Locate ns_err structure in mbuf, and check 17221483Ssklower * that not corrupted and of at least minimum length. 17321483Ssklower */ 17421483Ssklower #ifdef NS_ERRPRINTFS 17521483Ssklower if (ns_errprintfs) { 17621483Ssklower printf("ns_err_input from "); 17721483Ssklower ns_printhost(&epidp->ns_ep_idp.idp_sna); 17821483Ssklower printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 17921483Ssklower } 18021483Ssklower #endif 18121483Ssklower i = sizeof (struct ns_epidp); 18221483Ssklower if ((m->m_off > MMAXOFF || m->m_len < i) && 18321483Ssklower (m = m_pullup(m, i)) == 0) { 18421483Ssklower ns_errstat.ns_es_tooshort++; 18521483Ssklower return; 18621483Ssklower } 18721483Ssklower ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 18821483Ssklower type = ntohs(ep->ns_err_num); 18921483Ssklower param = ntohs(ep->ns_err_param); 19023980Ssklower ns_errstat.ns_es_inhist[ns_err_x(type)]++; 19121483Ssklower 19221483Ssklower #ifdef NS_ERRPRINTFS 19321483Ssklower /* 19421483Ssklower * Message type specific processing. 19521483Ssklower */ 19621483Ssklower if (ns_errprintfs) 19721483Ssklower printf("ns_err_input, type %d param %d\n", type, param); 19821483Ssklower #endif 19921483Ssklower if (type >= NS_ERR_TOO_BIG) { 20021483Ssklower goto badcode; 20121483Ssklower } 20221483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 20321483Ssklower switch (type) { 20421483Ssklower 20521483Ssklower case NS_ERR_UNREACH_HOST: 20621483Ssklower code = PRC_UNREACH_NET; 20721483Ssklower goto deliver; 20821483Ssklower 20921483Ssklower case NS_ERR_TOO_OLD: 21021483Ssklower code = PRC_TIMXCEED_INTRANS; 21121483Ssklower goto deliver; 21221483Ssklower 21321483Ssklower case NS_ERR_TOO_BIG: 21421483Ssklower code = PRC_MSGSIZE; 21521483Ssklower goto deliver; 21621483Ssklower 21721483Ssklower case NS_ERR_FULLUP: 21821483Ssklower code = PRC_QUENCH; 21921483Ssklower goto deliver; 22021483Ssklower 22121483Ssklower case NS_ERR_NOSOCK: 22221483Ssklower code = PRC_UNREACH_PORT; 22321483Ssklower goto deliver; 22421483Ssklower 22521483Ssklower case NS_ERR_UNSPEC_T: 22621483Ssklower case NS_ERR_BADSUM_T: 22721483Ssklower case NS_ERR_BADSUM: 22821483Ssklower case NS_ERR_UNSPEC: 22921483Ssklower code = PRC_PARAMPROB; 23021483Ssklower goto deliver; 23121483Ssklower 23221483Ssklower deliver: 23321483Ssklower /* 23421483Ssklower * Problem with datagram; advise higher level routines. 23521483Ssklower */ 23621483Ssklower #ifdef NS_ERRPRINTFS 23721483Ssklower if (ns_errprintfs) 23821483Ssklower printf("deliver to protocol %d\n", 23921483Ssklower ep->ns_err_idp.idp_pt); 24021483Ssklower #endif 24121483Ssklower switch(ep->ns_err_idp.idp_pt) { 24221483Ssklower case NSPROTO_SPP: 24321483Ssklower spp_ctlinput(code, (caddr_t)ep); 24421483Ssklower break; 24521483Ssklower 24621483Ssklower default: 24721483Ssklower idp_ctlinput(code, (caddr_t)ep); 24821483Ssklower } 24921483Ssklower 25021483Ssklower goto free; 25121483Ssklower 25221483Ssklower default: 25321483Ssklower badcode: 25421483Ssklower ns_errstat.ns_es_badcode++; 25521483Ssklower goto free; 25621483Ssklower 25721483Ssklower } 25821483Ssklower free: 25921483Ssklower m_freem(m); 26021483Ssklower } 26121746Ssklower 26228956Skarels #ifdef notdef 26321483Ssklower u_long 26421483Ssklower nstime() 26521483Ssklower { 26629924Skarels int s = splclock(); 26721483Ssklower u_long t; 26821483Ssklower 26921483Ssklower t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 27021483Ssklower splx(s); 27121483Ssklower return (htonl(t)); 27221483Ssklower } 27328956Skarels #endif 27421746Ssklower 27521746Ssklower ns_echo(idp) 27621746Ssklower register struct idp *idp; 27721746Ssklower { 27821746Ssklower struct mbuf *m = dtom(idp); 27921746Ssklower register struct echo { 28021746Ssklower struct idp ec_idp; 28121746Ssklower u_short ec_op; /* Operation, 1 = request, 2 = reply */ 28221746Ssklower } *ec = (struct echo *)idp; 28321746Ssklower struct ns_addr temp; 28421746Ssklower 28521746Ssklower if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 28621746Ssklower if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 28721746Ssklower 28821746Ssklower ec->ec_op = htons(2); 28921746Ssklower 29021746Ssklower temp = idp->idp_dna; 29121746Ssklower idp->idp_dna = idp->idp_sna; 29221746Ssklower idp->idp_sna = temp; 29321746Ssklower 29421746Ssklower if (idp->idp_sum != 0xffff) { 29521746Ssklower idp->idp_sum = 0; 29628956Skarels idp->idp_sum = ns_cksum(m, 29728956Skarels (int)(((ntohs(idp->idp_len) - 1)|1)+1)); 29821746Ssklower } 29926389Skarels (void) ns_output(m, (struct route *)0, NS_FORWARDING); 30021746Ssklower return(0); 30121746Ssklower } 302