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