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