1 #include "../h/param.h" 2 #include "../h/systm.h" 3 #include "../h/mbuf.h" 4 #include "../h/socket.h" 5 #include "../h/socketvar.h" 6 #include "../h/protosw.h" 7 #include "../h/syslog.h" 8 9 #include "../net/if.h" 10 #include "../net/route.h" 11 12 #include "../bbnnet/in.h" 13 #include "../bbnnet/net.h" 14 #include "../bbnnet/in_pcb.h" 15 #include "../bbnnet/in_var.h" 16 #include "../bbnnet/ip.h" 17 #include "../bbnnet/icmp.h" 18 #include "../bbnnet/nopcb.h" 19 20 extern struct ifnet *inetifp; 21 22 /* 23 * We are generating an ICMP error message in response to this packet sent 24 * to us. Too bad the device driver doesn't pair a pointer to its ifnet with 25 * the incoming packet. That would save us a search, and we could use that 26 * for our source address in the ICMP error message. 27 * 28 * Pick a source address for that ICMP error message we send. We can't 29 * always use ip_dst of the original for the ip_src of the ICMP error 30 * message since the packet may have been broadcast. 31 * 32 * We try to establish a proper interface to respond by in case we're 33 * multi-homed. Try to respond by interface received on rather than 34 * interface that represents most direct route back. 35 */ 36 struct in_addr icmp_addr (ip) 37 struct ip *ip; 38 { 39 struct in_ifaddr *ia; 40 41 /* 42 #ifdef bsd42 43 */ 44 /* don't want broadcasts to match */ 45 if (! (ia = in_iawithaddr(ip->ip_dst, FALSE))) 46 { 47 /* hmm, try for the net... */ 48 if ((ia = in_iawithnet(ip->ip_dst)) == NULL) 49 { 50 struct in_addr l; 51 52 /* 53 * The message will be sent by ip_send() who will 54 * route the message and discover that a local address 55 * should be set on the basis of the route used. 56 */ 57 l.s_addr = INADDR_ANY; 58 return (l); 59 } 60 } 61 /* 62 #endif 63 ia = in_iafromif(inetifp); 64 */ 65 return (IA_INADDR(ia)); 66 } 67 68 /* 69 * notes to above mostly apply 70 * 71 * icmp_addr() sort of assumes the packet was addressed to us. But when we 72 * act as a getway, S sends to A1, and we use A2 to get to D. We want to 73 * reply with the A1 address, not the A2 address. 74 */ 75 struct in_addr redir_addr (ip) 76 struct ip *ip; 77 { 78 register struct in_ifaddr *ia; 79 80 /* 81 #ifdef bsd42 82 */ 83 /* note we use ip_src, not ip_dst here */ 84 if ((ia = in_iawithnet(ip->ip_src)) == NULL) 85 { 86 struct in_addr l; 87 88 l.s_addr = INADDR_ANY; 89 return (l); 90 } 91 /* 92 #endif 93 ia = in_iafromif(inetifp); 94 */ 95 return (IA_INADDR(ia)); 96 } 97 98 /* 99 * There are a few icmp output routines since the header has some variable 100 * types in it ... 101 */ 102 send_redirect (redirip, use, code, icmplen) 103 struct ip *redirip; 104 struct in_addr use; 105 unsigned icmplen; 106 { 107 register struct mbuf *m; 108 int error; 109 110 if (m = m_get(M_DONTWAIT, MT_HEADER)) 111 { 112 m->m_len = ICMPSIZE + icmplen; 113 m->m_off = MMAXOFF - m->m_len; 114 { 115 register struct icmp *ic; 116 117 ic = mtod(m, struct icmp *); 118 ic->ic_type = ICMP_REDIR; 119 ic->ic_code = code; 120 ic->ic_sum = 0; 121 ic->ic_gaddr = use; 122 if (icmplen > 0) 123 bcopy ((caddr_t)redirip, ic->ic_data, icmplen); 124 125 /* used to use an inline cksum here */ 126 ic->ic_sum = in_cksum (m, m->m_len); 127 } 128 129 m->m_off -= sizeof(struct ip); 130 m->m_len += sizeof(struct ip); 131 { 132 register struct ip *ip; 133 134 ip = mtod(m, struct ip *); 135 ip->ip_p = IPPROTO_ICMP; 136 ip->ip_tos = 0; 137 ip->ip_dst = redirip->ip_src; 138 ip->ip_src = redir_addr(redirip); 139 } 140 NOPCB_IPSEND (m, (int)icmplen, FALSE, error); 141 142 #ifdef lint 143 error = error ; 144 #endif 145 } 146 } 147 148 /* 149 * Send an ICMP error message. Note that data must not exceed single mbuf. 150 */ 151 ic_errmsg (src, dst, type, code, off, dlen, dp) 152 struct in_addr src; 153 struct in_addr dst; 154 unsigned dlen; 155 caddr_t dp; /* assumed to be contiguous */ 156 { 157 register struct mbuf *m; 158 register unsigned len; 159 int error; 160 161 if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 162 return /*ENOBUFS*/; 163 164 /* 165 * Build ICMP header 166 */ 167 len = ICMPSIZE + dlen; 168 m->m_off = MMAXOFF - len; 169 if (m->m_off < (MMINOFF + sizeof(struct ip))) 170 { 171 log (LOG_INFO, "ic_errmsg len %d", len); 172 m_free (m); 173 return; 174 } 175 m->m_len = len; 176 177 /* ICMP header */ 178 { 179 register struct icmp *ic; 180 181 ic = mtod(m, struct icmp *); 182 ic->ic_type = type; 183 ic->ic_code = code; 184 ic->ic_off = off; 185 if (dlen > 0) 186 bcopy(dp, ic->ic_data, dlen); 187 ic->ic_sum = 0; 188 ic->ic_sum = in_cksum(m, len); 189 } 190 191 /* IP header */ 192 { 193 register struct ip *ip; 194 195 m->m_off -= sizeof(struct ip); 196 m->m_len += sizeof(struct ip); 197 ip = mtod(m, struct ip *); 198 ip->ip_p = IPPROTO_ICMP; 199 ip->ip_tos = 0; 200 ip->ip_src = src; 201 ip->ip_dst = dst; 202 } 203 204 NOPCB_IPSEND (m, (int)len, FALSE, error); 205 206 #ifdef lint 207 error = error; 208 #endif 209 } 210 211 #ifdef BBNPING 212 ping(gwaddr) 213 struct in_addr gwaddr; 214 { 215 register struct mbuf *m; 216 217 if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 218 return; 219 m->m_off = MMAXOFF - ICMPSIZE; 220 m->m_len = ICMPSIZE; 221 { 222 register struct icmp *ic; 223 224 ic = mtod (m, struct icmp *); 225 ic->ic_type = ICMP_ECHO; 226 ic->ic_code = 0; 227 ic->ic_id = MY_ECHO_ID; 228 ic->ic_sum = 0; 229 ic->ic_sum = in_cksum(m, ICMPSIZE); 230 } 231 232 m->m_off -= sizeof(struct ip); 233 m->m_len += sizeof(struct ip); 234 { 235 register struct ip *ip; 236 237 ip = mtod(m, struct ip *); 238 ip->ip_p = IPPROTO_ICMP; 239 ip->ip_tos = 0; 240 ip->ip_dst = gwaddr; 241 ip->ip_src = icmp_addr (ip); 242 } 243 244 { 245 register int error; 246 247 NOPCB_IPSEND (m, ICMPSIZE, FALSE, error); 248 #ifdef lint 249 error = error; 250 #endif 251 } 252 } 253 #endif 254