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