123206Smckusick /* 233411Ssklower * Copyright (c) 1984, 1988 Regents of the University of California. 333371Ssklower * All rights reserved. 423206Smckusick * 544502Sbostic * %sccs.include.redist.c% 633371Ssklower * 7*56534Sbostic * @(#)ns_error.c 7.9 (Berkeley) 10/11/92 823206Smckusick */ 921483Ssklower 10*56534Sbostic #include <sys/param.h> 11*56534Sbostic #include <sys/systm.h> 12*56534Sbostic #include <sys/malloc.h> 13*56534Sbostic #include <sys/mbuf.h> 14*56534Sbostic #include <sys/protosw.h> 15*56534Sbostic #include <sys/socket.h> 16*56534Sbostic #include <sys/time.h> 17*56534Sbostic #include <sys/kernel.h> 1821483Ssklower 19*56534Sbostic #include <net/route.h> 2021483Ssklower 21*56534Sbostic #include <netns/ns.h> 22*56534Sbostic #include <netns/ns_pcb.h> 23*56534Sbostic #include <netns/idp.h> 24*56534Sbostic #include <netns/ns_error.h> 2521483Ssklower 2624226Ssklower #ifdef lint 2724226Ssklower #define NS_ERRPRINTFS 1 2824226Ssklower #endif 2924226Ssklower 3021483Ssklower #ifdef NS_ERRPRINTFS 3121483Ssklower /* 3221483Ssklower * NS_ERR routines: error generation, receive packet processing, and 3321746Ssklower * routines to turnaround packets back to the originator. 3421483Ssklower */ 3521483Ssklower int ns_errprintfs = 0; 3621483Ssklower #endif 3721483Ssklower 3833429Smckusick ns_err_x(c) 3933411Ssklower { 4033411Ssklower register u_short *w, *lim, *base = ns_errstat.ns_es_codes; 4133411Ssklower u_short x = c; 4233411Ssklower 4333411Ssklower /* 4433411Ssklower * zero is a legit error code, handle specially 4533411Ssklower */ 4633411Ssklower if (x == 0) 4733411Ssklower return (0); 4833411Ssklower lim = base + NS_ERR_MAX - 1; 4933411Ssklower for (w = base + 1; w < lim; w++) { 5033411Ssklower if (*w == 0) 5133411Ssklower *w = x; 5233411Ssklower if (*w == x) 5333411Ssklower break; 5433411Ssklower } 5533411Ssklower return (w - base); 5633411Ssklower } 5733411Ssklower 5821483Ssklower /* 5921483Ssklower * Generate an error packet of type error 6021483Ssklower * in response to bad packet. 6121483Ssklower */ 6221483Ssklower 6321483Ssklower ns_error(om, type, param) 6421483Ssklower struct mbuf *om; 6521483Ssklower int type; 6621483Ssklower { 6721483Ssklower register struct ns_epidp *ep; 6821483Ssklower struct mbuf *m; 6921483Ssklower struct idp *nip; 7021483Ssklower register struct idp *oip = mtod(om, struct idp *); 7121483Ssklower extern int idpcksum; 7221483Ssklower 7321746Ssklower /* 7421746Ssklower * If this packet was sent to the echo port, 7521746Ssklower * and nobody was there, just echo it. 7621746Ssklower * (Yes, this is a wart!) 7721746Ssklower */ 7837473Ssklower if (type == NS_ERR_NOSOCK && 7937473Ssklower oip->idp_dna.x_port == htons(2) && 8037473Ssklower (type = ns_echo(om))==0) 8121746Ssklower return; 8221746Ssklower 8321483Ssklower #ifdef NS_ERRPRINTFS 8421483Ssklower if (ns_errprintfs) 8521483Ssklower printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 8621483Ssklower #endif 8723980Ssklower /* 8823980Ssklower * Don't Generate error packets in response to multicasts. 8923980Ssklower */ 9023980Ssklower if (oip->idp_dna.x_host.c_host[0] & 1) 9137473Ssklower goto freeit; 9223980Ssklower 9321483Ssklower ns_errstat.ns_es_error++; 9421483Ssklower /* 9521483Ssklower * Make sure that the old IDP packet had 30 bytes of data to return; 9621483Ssklower * if not, don't bother. Also don't EVER error if the old 9721483Ssklower * packet protocol was NS_ERR. 9821483Ssklower */ 9921483Ssklower if (oip->idp_len < sizeof(struct idp)) { 10021483Ssklower ns_errstat.ns_es_oldshort++; 10137473Ssklower goto freeit; 10221483Ssklower } 10321483Ssklower if (oip->idp_pt == NSPROTO_ERROR) { 10421483Ssklower ns_errstat.ns_es_oldns_err++; 10537473Ssklower goto freeit; 10621483Ssklower } 10721483Ssklower 10821483Ssklower /* 10921483Ssklower * First, formulate ns_err message 11021483Ssklower */ 11137473Ssklower m = m_gethdr(M_DONTWAIT, MT_HEADER); 11221483Ssklower if (m == NULL) 11337473Ssklower goto freeit; 11421483Ssklower m->m_len = sizeof(*ep); 11537473Ssklower MH_ALIGN(m, m->m_len); 11621483Ssklower ep = mtod(m, struct ns_epidp *); 11721483Ssklower if ((u_int)type > NS_ERR_TOO_BIG) 11821483Ssklower panic("ns_err_error"); 11921483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 12024226Ssklower ep->ns_ep_errp.ns_err_num = htons((u_short)type); 12124226Ssklower ep->ns_ep_errp.ns_err_param = htons((u_short)param); 12221483Ssklower bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 12321483Ssklower nip = &ep->ns_ep_idp; 12421483Ssklower nip->idp_len = sizeof(*ep); 12521483Ssklower nip->idp_len = htons((u_short)nip->idp_len); 12621483Ssklower nip->idp_pt = NSPROTO_ERROR; 12721483Ssklower nip->idp_tc = 0; 12821483Ssklower nip->idp_dna = oip->idp_sna; 12921483Ssklower nip->idp_sna = oip->idp_dna; 13021483Ssklower if (idpcksum) { 13121483Ssklower nip->idp_sum = 0; 13237473Ssklower nip->idp_sum = ns_cksum(m, sizeof(*ep)); 13321483Ssklower } else 13421483Ssklower nip->idp_sum = 0xffff; 13537473Ssklower (void) ns_output(m, (struct route *)0, 0); 13621483Ssklower 13737473Ssklower freeit: 13837473Ssklower m_freem(om); 13921483Ssklower } 14021483Ssklower 14121483Ssklower ns_printhost(p) 14221483Ssklower register struct ns_addr *p; 14321483Ssklower { 14421483Ssklower 14521483Ssklower printf("<net:%x%x,host:%x%x%x,port:%x>", 14621483Ssklower p->x_net.s_net[0], 14721483Ssklower p->x_net.s_net[1], 14821483Ssklower p->x_host.s_host[0], 14921483Ssklower p->x_host.s_host[1], 15021483Ssklower p->x_host.s_host[2], 15121483Ssklower p->x_port); 15221483Ssklower 15321483Ssklower } 15421483Ssklower 15521483Ssklower /* 15621483Ssklower * Process a received NS_ERR message. 15721483Ssklower */ 15821483Ssklower ns_err_input(m) 15921483Ssklower struct mbuf *m; 16021483Ssklower { 16121483Ssklower register struct ns_errp *ep; 16221483Ssklower register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 16321483Ssklower register int i; 16421483Ssklower int type, code, param; 16521483Ssklower 16621483Ssklower /* 16721483Ssklower * Locate ns_err structure in mbuf, and check 16821483Ssklower * that not corrupted and of at least minimum length. 16921483Ssklower */ 17021483Ssklower #ifdef NS_ERRPRINTFS 17121483Ssklower if (ns_errprintfs) { 17221483Ssklower printf("ns_err_input from "); 17321483Ssklower ns_printhost(&epidp->ns_ep_idp.idp_sna); 17421483Ssklower printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 17521483Ssklower } 17621483Ssklower #endif 17721483Ssklower i = sizeof (struct ns_epidp); 17837473Ssklower if (((m->m_flags & M_EXT) || m->m_len < i) && 17921483Ssklower (m = m_pullup(m, i)) == 0) { 18021483Ssklower ns_errstat.ns_es_tooshort++; 18121483Ssklower return; 18221483Ssklower } 18321483Ssklower ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 18421483Ssklower type = ntohs(ep->ns_err_num); 18521483Ssklower param = ntohs(ep->ns_err_param); 18623980Ssklower ns_errstat.ns_es_inhist[ns_err_x(type)]++; 18721483Ssklower 18821483Ssklower #ifdef NS_ERRPRINTFS 18921483Ssklower /* 19021483Ssklower * Message type specific processing. 19121483Ssklower */ 19221483Ssklower if (ns_errprintfs) 19321483Ssklower printf("ns_err_input, type %d param %d\n", type, param); 19421483Ssklower #endif 19521483Ssklower if (type >= NS_ERR_TOO_BIG) { 19621483Ssklower goto badcode; 19721483Ssklower } 19821483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 19921483Ssklower switch (type) { 20021483Ssklower 20121483Ssklower case NS_ERR_UNREACH_HOST: 20221483Ssklower code = PRC_UNREACH_NET; 20321483Ssklower goto deliver; 20421483Ssklower 20521483Ssklower case NS_ERR_TOO_OLD: 20621483Ssklower code = PRC_TIMXCEED_INTRANS; 20721483Ssklower goto deliver; 20821483Ssklower 20921483Ssklower case NS_ERR_TOO_BIG: 21021483Ssklower code = PRC_MSGSIZE; 21121483Ssklower goto deliver; 21221483Ssklower 21321483Ssklower case NS_ERR_FULLUP: 21421483Ssklower code = PRC_QUENCH; 21521483Ssklower goto deliver; 21621483Ssklower 21721483Ssklower case NS_ERR_NOSOCK: 21821483Ssklower code = PRC_UNREACH_PORT; 21921483Ssklower goto deliver; 22021483Ssklower 22121483Ssklower case NS_ERR_UNSPEC_T: 22221483Ssklower case NS_ERR_BADSUM_T: 22321483Ssklower case NS_ERR_BADSUM: 22421483Ssklower case NS_ERR_UNSPEC: 22521483Ssklower code = PRC_PARAMPROB; 22621483Ssklower goto deliver; 22721483Ssklower 22821483Ssklower deliver: 22921483Ssklower /* 23021483Ssklower * Problem with datagram; advise higher level routines. 23121483Ssklower */ 23221483Ssklower #ifdef NS_ERRPRINTFS 23321483Ssklower if (ns_errprintfs) 23421483Ssklower printf("deliver to protocol %d\n", 23521483Ssklower ep->ns_err_idp.idp_pt); 23621483Ssklower #endif 23721483Ssklower switch(ep->ns_err_idp.idp_pt) { 23821483Ssklower case NSPROTO_SPP: 23921483Ssklower spp_ctlinput(code, (caddr_t)ep); 24021483Ssklower break; 24121483Ssklower 24221483Ssklower default: 24321483Ssklower idp_ctlinput(code, (caddr_t)ep); 24421483Ssklower } 24521483Ssklower 24637473Ssklower goto freeit; 24721483Ssklower 24821483Ssklower default: 24921483Ssklower badcode: 25021483Ssklower ns_errstat.ns_es_badcode++; 25137473Ssklower goto freeit; 25221483Ssklower 25321483Ssklower } 25437473Ssklower freeit: 25521483Ssklower m_freem(m); 25621483Ssklower } 25721746Ssklower 25828956Skarels #ifdef notdef 25921483Ssklower u_long 26021483Ssklower nstime() 26121483Ssklower { 26229924Skarels int s = splclock(); 26321483Ssklower u_long t; 26421483Ssklower 26521483Ssklower t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 26621483Ssklower splx(s); 26721483Ssklower return (htonl(t)); 26821483Ssklower } 26928956Skarels #endif 27021746Ssklower 27137473Ssklower ns_echo(m) 27237473Ssklower struct mbuf *m; 27321746Ssklower { 27437473Ssklower register struct idp *idp = mtod(m, struct idp *); 27521746Ssklower register struct echo { 27621746Ssklower struct idp ec_idp; 27721746Ssklower u_short ec_op; /* Operation, 1 = request, 2 = reply */ 27821746Ssklower } *ec = (struct echo *)idp; 27921746Ssklower struct ns_addr temp; 28021746Ssklower 28121746Ssklower if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 28221746Ssklower if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 28321746Ssklower 28421746Ssklower ec->ec_op = htons(2); 28521746Ssklower 28621746Ssklower temp = idp->idp_dna; 28721746Ssklower idp->idp_dna = idp->idp_sna; 28821746Ssklower idp->idp_sna = temp; 28921746Ssklower 29021746Ssklower if (idp->idp_sum != 0xffff) { 29121746Ssklower idp->idp_sum = 0; 29228956Skarels idp->idp_sum = ns_cksum(m, 29328956Skarels (int)(((ntohs(idp->idp_len) - 1)|1)+1)); 29421746Ssklower } 29526389Skarels (void) ns_output(m, (struct route *)0, NS_FORWARDING); 29621746Ssklower return(0); 29721746Ssklower } 298