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