123206Smckusick /* 233411Ssklower * 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 6*34856Sbostic * provided that the above copyright notice and this paragraph are 7*34856Sbostic * duplicated in all such forms and that any documentation, 8*34856Sbostic * advertising materials, and other materials related to such 9*34856Sbostic * distribution and use acknowledge that the software was developed 10*34856Sbostic * by the University of California, Berkeley. The name of the 11*34856Sbostic * University may not be used to endorse or promote products derived 12*34856Sbostic * from this software without specific prior written permission. 13*34856Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34856Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34856Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633371Ssklower * 17*34856Sbostic * @(#)ns_error.c 7.6 (Berkeley) 06/29/88 1823206Smckusick */ 1921483Ssklower 2021483Ssklower #include "param.h" 2121483Ssklower #include "systm.h" 2221483Ssklower #include "mbuf.h" 2321483Ssklower #include "protosw.h" 2421483Ssklower #include "socket.h" 2521483Ssklower #include "time.h" 2621483Ssklower #include "kernel.h" 2721483Ssklower 2821483Ssklower #include "../net/route.h" 2921483Ssklower 3021483Ssklower #include "ns.h" 3121483Ssklower #include "ns_pcb.h" 3221483Ssklower #include "idp.h" 3321483Ssklower #include "ns_error.h" 3421483Ssklower 3524226Ssklower #ifdef lint 3624226Ssklower #define NS_ERRPRINTFS 1 3724226Ssklower #endif 3824226Ssklower 3921483Ssklower #ifdef NS_ERRPRINTFS 4021483Ssklower /* 4121483Ssklower * NS_ERR routines: error generation, receive packet processing, and 4221746Ssklower * routines to turnaround packets back to the originator. 4321483Ssklower */ 4421483Ssklower int ns_errprintfs = 0; 4521483Ssklower #endif 4621483Ssklower 4733429Smckusick ns_err_x(c) 4833411Ssklower { 4933411Ssklower register u_short *w, *lim, *base = ns_errstat.ns_es_codes; 5033411Ssklower u_short x = c; 5133411Ssklower 5233411Ssklower /* 5333411Ssklower * zero is a legit error code, handle specially 5433411Ssklower */ 5533411Ssklower if (x == 0) 5633411Ssklower return (0); 5733411Ssklower lim = base + NS_ERR_MAX - 1; 5833411Ssklower for (w = base + 1; w < lim; w++) { 5933411Ssklower if (*w == 0) 6033411Ssklower *w = x; 6133411Ssklower if (*w == x) 6233411Ssklower break; 6333411Ssklower } 6433411Ssklower return (w - base); 6533411Ssklower } 6633411Ssklower 6721483Ssklower /* 6821483Ssklower * Generate an error packet of type error 6921483Ssklower * in response to bad packet. 7021483Ssklower */ 7121483Ssklower 7221483Ssklower ns_error(om, type, param) 7321483Ssklower struct mbuf *om; 7421483Ssklower int type; 7521483Ssklower { 7621483Ssklower register struct ns_epidp *ep; 7721483Ssklower struct mbuf *m; 7821483Ssklower struct idp *nip; 7921483Ssklower register struct idp *oip = mtod(om, struct idp *); 8021483Ssklower extern int idpcksum; 8121483Ssklower 8221746Ssklower /* 8321746Ssklower * If this packet was sent to the echo port, 8421746Ssklower * and nobody was there, just echo it. 8521746Ssklower * (Yes, this is a wart!) 8621746Ssklower */ 8721746Ssklower if (type==NS_ERR_NOSOCK && 8821746Ssklower oip->idp_dna.x_port==htons(2) && 8921746Ssklower (type = ns_echo(oip)==0)) 9021746Ssklower return; 9121746Ssklower 9221483Ssklower #ifdef NS_ERRPRINTFS 9321483Ssklower if (ns_errprintfs) 9421483Ssklower printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 9521483Ssklower #endif 9623980Ssklower /* 9723980Ssklower * Don't Generate error packets in response to multicasts. 9823980Ssklower */ 9923980Ssklower if (oip->idp_dna.x_host.c_host[0] & 1) 10023980Ssklower goto free; 10123980Ssklower 10221483Ssklower ns_errstat.ns_es_error++; 10321483Ssklower /* 10421483Ssklower * Make sure that the old IDP packet had 30 bytes of data to return; 10521483Ssklower * if not, don't bother. Also don't EVER error if the old 10621483Ssklower * packet protocol was NS_ERR. 10721483Ssklower */ 10821483Ssklower if (oip->idp_len < sizeof(struct idp)) { 10921483Ssklower ns_errstat.ns_es_oldshort++; 11021483Ssklower goto free; 11121483Ssklower } 11221483Ssklower if (oip->idp_pt == NSPROTO_ERROR) { 11321483Ssklower ns_errstat.ns_es_oldns_err++; 11421483Ssklower goto free; 11521483Ssklower } 11621483Ssklower 11721483Ssklower /* 11821483Ssklower * First, formulate ns_err message 11921483Ssklower */ 12021483Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 12121483Ssklower if (m == NULL) 12221483Ssklower goto free; 12321483Ssklower m->m_len = sizeof(*ep); 12421483Ssklower m->m_off = MMAXOFF - m->m_len; 12521483Ssklower ep = mtod(m, struct ns_epidp *); 12621483Ssklower if ((u_int)type > NS_ERR_TOO_BIG) 12721483Ssklower panic("ns_err_error"); 12821483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 12924226Ssklower ep->ns_ep_errp.ns_err_num = htons((u_short)type); 13024226Ssklower ep->ns_ep_errp.ns_err_param = htons((u_short)param); 13121483Ssklower bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 13221483Ssklower nip = &ep->ns_ep_idp; 13321483Ssklower nip->idp_len = sizeof(*ep); 13421483Ssklower nip->idp_len = htons((u_short)nip->idp_len); 13521483Ssklower nip->idp_pt = NSPROTO_ERROR; 13621483Ssklower nip->idp_tc = 0; 13721483Ssklower nip->idp_dna = oip->idp_sna; 13821483Ssklower nip->idp_sna = oip->idp_dna; 13921483Ssklower if (idpcksum) { 14021483Ssklower nip->idp_sum = 0; 14121483Ssklower nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 14221483Ssklower } else 14321483Ssklower nip->idp_sum = 0xffff; 14424226Ssklower (void) ns_output(dtom(nip), (struct route *)0, 0); 14521483Ssklower 14621483Ssklower free: 14721483Ssklower m_freem(dtom(oip)); 14821483Ssklower } 14921483Ssklower 15021483Ssklower ns_printhost(p) 15121483Ssklower register struct ns_addr *p; 15221483Ssklower { 15321483Ssklower 15421483Ssklower printf("<net:%x%x,host:%x%x%x,port:%x>", 15521483Ssklower p->x_net.s_net[0], 15621483Ssklower p->x_net.s_net[1], 15721483Ssklower p->x_host.s_host[0], 15821483Ssklower p->x_host.s_host[1], 15921483Ssklower p->x_host.s_host[2], 16021483Ssklower p->x_port); 16121483Ssklower 16221483Ssklower } 16321483Ssklower 16421483Ssklower /* 16521483Ssklower * Process a received NS_ERR message. 16621483Ssklower */ 16721483Ssklower ns_err_input(m) 16821483Ssklower struct mbuf *m; 16921483Ssklower { 17021483Ssklower register struct ns_errp *ep; 17121483Ssklower register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 17221483Ssklower register int i; 17321483Ssklower int type, code, param; 17421483Ssklower 17521483Ssklower /* 17621483Ssklower * Locate ns_err structure in mbuf, and check 17721483Ssklower * that not corrupted and of at least minimum length. 17821483Ssklower */ 17921483Ssklower #ifdef NS_ERRPRINTFS 18021483Ssklower if (ns_errprintfs) { 18121483Ssklower printf("ns_err_input from "); 18221483Ssklower ns_printhost(&epidp->ns_ep_idp.idp_sna); 18321483Ssklower printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 18421483Ssklower } 18521483Ssklower #endif 18621483Ssklower i = sizeof (struct ns_epidp); 18721483Ssklower if ((m->m_off > MMAXOFF || m->m_len < i) && 18821483Ssklower (m = m_pullup(m, i)) == 0) { 18921483Ssklower ns_errstat.ns_es_tooshort++; 19021483Ssklower return; 19121483Ssklower } 19221483Ssklower ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 19321483Ssklower type = ntohs(ep->ns_err_num); 19421483Ssklower param = ntohs(ep->ns_err_param); 19523980Ssklower ns_errstat.ns_es_inhist[ns_err_x(type)]++; 19621483Ssklower 19721483Ssklower #ifdef NS_ERRPRINTFS 19821483Ssklower /* 19921483Ssklower * Message type specific processing. 20021483Ssklower */ 20121483Ssklower if (ns_errprintfs) 20221483Ssklower printf("ns_err_input, type %d param %d\n", type, param); 20321483Ssklower #endif 20421483Ssklower if (type >= NS_ERR_TOO_BIG) { 20521483Ssklower goto badcode; 20621483Ssklower } 20721483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 20821483Ssklower switch (type) { 20921483Ssklower 21021483Ssklower case NS_ERR_UNREACH_HOST: 21121483Ssklower code = PRC_UNREACH_NET; 21221483Ssklower goto deliver; 21321483Ssklower 21421483Ssklower case NS_ERR_TOO_OLD: 21521483Ssklower code = PRC_TIMXCEED_INTRANS; 21621483Ssklower goto deliver; 21721483Ssklower 21821483Ssklower case NS_ERR_TOO_BIG: 21921483Ssklower code = PRC_MSGSIZE; 22021483Ssklower goto deliver; 22121483Ssklower 22221483Ssklower case NS_ERR_FULLUP: 22321483Ssklower code = PRC_QUENCH; 22421483Ssklower goto deliver; 22521483Ssklower 22621483Ssklower case NS_ERR_NOSOCK: 22721483Ssklower code = PRC_UNREACH_PORT; 22821483Ssklower goto deliver; 22921483Ssklower 23021483Ssklower case NS_ERR_UNSPEC_T: 23121483Ssklower case NS_ERR_BADSUM_T: 23221483Ssklower case NS_ERR_BADSUM: 23321483Ssklower case NS_ERR_UNSPEC: 23421483Ssklower code = PRC_PARAMPROB; 23521483Ssklower goto deliver; 23621483Ssklower 23721483Ssklower deliver: 23821483Ssklower /* 23921483Ssklower * Problem with datagram; advise higher level routines. 24021483Ssklower */ 24121483Ssklower #ifdef NS_ERRPRINTFS 24221483Ssklower if (ns_errprintfs) 24321483Ssklower printf("deliver to protocol %d\n", 24421483Ssklower ep->ns_err_idp.idp_pt); 24521483Ssklower #endif 24621483Ssklower switch(ep->ns_err_idp.idp_pt) { 24721483Ssklower case NSPROTO_SPP: 24821483Ssklower spp_ctlinput(code, (caddr_t)ep); 24921483Ssklower break; 25021483Ssklower 25121483Ssklower default: 25221483Ssklower idp_ctlinput(code, (caddr_t)ep); 25321483Ssklower } 25421483Ssklower 25521483Ssklower goto free; 25621483Ssklower 25721483Ssklower default: 25821483Ssklower badcode: 25921483Ssklower ns_errstat.ns_es_badcode++; 26021483Ssklower goto free; 26121483Ssklower 26221483Ssklower } 26321483Ssklower free: 26421483Ssklower m_freem(m); 26521483Ssklower } 26621746Ssklower 26728956Skarels #ifdef notdef 26821483Ssklower u_long 26921483Ssklower nstime() 27021483Ssklower { 27129924Skarels int s = splclock(); 27221483Ssklower u_long t; 27321483Ssklower 27421483Ssklower t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 27521483Ssklower splx(s); 27621483Ssklower return (htonl(t)); 27721483Ssklower } 27828956Skarels #endif 27921746Ssklower 28021746Ssklower ns_echo(idp) 28121746Ssklower register struct idp *idp; 28221746Ssklower { 28321746Ssklower struct mbuf *m = dtom(idp); 28421746Ssklower register struct echo { 28521746Ssklower struct idp ec_idp; 28621746Ssklower u_short ec_op; /* Operation, 1 = request, 2 = reply */ 28721746Ssklower } *ec = (struct echo *)idp; 28821746Ssklower struct ns_addr temp; 28921746Ssklower 29021746Ssklower if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 29121746Ssklower if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 29221746Ssklower 29321746Ssklower ec->ec_op = htons(2); 29421746Ssklower 29521746Ssklower temp = idp->idp_dna; 29621746Ssklower idp->idp_dna = idp->idp_sna; 29721746Ssklower idp->idp_sna = temp; 29821746Ssklower 29921746Ssklower if (idp->idp_sum != 0xffff) { 30021746Ssklower idp->idp_sum = 0; 30128956Skarels idp->idp_sum = ns_cksum(m, 30228956Skarels (int)(((ntohs(idp->idp_len) - 1)|1)+1)); 30321746Ssklower } 30426389Skarels (void) ns_output(m, (struct route *)0, NS_FORWARDING); 30521746Ssklower return(0); 30621746Ssklower } 307