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 #ifdef bsd42 42 /* don't want broadcasts to match */ 43 if (! (ia = in_iawithaddr(ip->ip_dst, FALSE))) 44 { 45 /* hmm, try for the net... */ 46 if ((ia = in_iawithnet(ip->ip_dst)) == NULL) 47 { 48 struct in_addr l; 49 50 /* 51 * The message will be sent by ip_send() who will 52 * route the message and discover that a local address 53 * should be set on the basis of the route used. 54 */ 55 l.s_addr = INADDR_ANY; 56 return (l); 57 } 58 } 59 #endif 60 ia = in_iafromif(inetifp); 61 return (IA_INADDR(ia)); 62 } 63 64 65 66 67 struct in_addr ping_addr (ip) 68 struct ip *ip; 69 { 70 struct in_ifaddr *ia; 71 72 /* don't want broadcasts to match */ 73 if (! (ia = in_iawithaddr(ip->ip_dst, FALSE))) 74 { 75 /* hmm, try for the net... */ 76 if ((ia = in_iawithnet(ip->ip_dst)) == NULL) 77 { 78 struct in_addr l; 79 80 /* 81 * The message will be sent by ip_send() who will 82 * route the message and discover that a local address 83 * should be set on the basis of the route used. 84 */ 85 l.s_addr = INADDR_ANY; 86 return (l); 87 } 88 } 89 return (IA_INADDR(ia)); 90 } 91 92 /* 93 * notes to above mostly apply 94 * 95 * icmp_addr() sort of assumes the packet was addressed to us. But when we 96 * act as a getway, S sends to A1, and we use A2 to get to D. We want to 97 * reply with the A1 address, not the A2 address. 98 */ 99 struct in_addr redir_addr (ip) 100 struct ip *ip; 101 { 102 register struct in_ifaddr *ia; 103 104 #ifdef bsd42 105 /* note we use ip_src, not ip_dst here */ 106 if ((ia = in_iawithnet(ip->ip_src)) == NULL) 107 { 108 struct in_addr l; 109 110 l.s_addr = INADDR_ANY; 111 return (l); 112 } 113 #endif 114 ia = in_iafromif(inetifp); 115 return (IA_INADDR(ia)); 116 } 117 118 /* 119 * There are a few icmp output routines since the header has some variable 120 * types in it ... 121 */ 122 send_redirect (redirip, use, code, icmplen) 123 struct ip *redirip; 124 struct in_addr use; 125 unsigned icmplen; 126 { 127 register struct mbuf *m; 128 int error; 129 130 if (m = m_get(M_DONTWAIT, MT_HEADER)) 131 { 132 m->m_len = ICMPSIZE + icmplen; 133 m->m_off = MMAXOFF - m->m_len; 134 { 135 register struct icmp *ic; 136 137 ic = mtod(m, struct icmp *); 138 ic->ic_type = ICMP_REDIR; 139 ic->ic_code = code; 140 ic->ic_sum = 0; 141 ic->ic_gaddr = use; 142 if (icmplen > 0) 143 bcopy ((caddr_t)redirip, ic->ic_data, icmplen); 144 145 /* used to use an inline cksum here */ 146 ic->ic_sum = in_cksum (m, m->m_len); 147 } 148 149 m->m_off -= sizeof(struct ip); 150 m->m_len += sizeof(struct ip); 151 { 152 register struct ip *ip; 153 154 ip = mtod(m, struct ip *); 155 ip->ip_p = IPPROTO_ICMP; 156 ip->ip_tos = 0; 157 ip->ip_dst = redirip->ip_src; 158 ip->ip_src = redir_addr(redirip); 159 } 160 NOPCB_IPSEND (m, (int)icmplen, FALSE, error); 161 162 #ifdef lint 163 error = error ; 164 #endif 165 } 166 } 167 168 /* 169 * Send an ICMP error message. Note that data must not exceed single mbuf. 170 */ 171 ic_errmsg (src, dst, type, code, off, dlen, dp) 172 struct in_addr src; 173 struct in_addr dst; 174 unsigned dlen; 175 caddr_t dp; /* assumed to be contiguous */ 176 { 177 register struct mbuf *m; 178 register unsigned len; 179 int error; 180 181 if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 182 return /*ENOBUFS*/; 183 184 /* 185 * Build ICMP header 186 */ 187 len = ICMPSIZE + dlen; 188 m->m_off = MMAXOFF - len; 189 if (m->m_off < (MMINOFF + sizeof(struct ip))) 190 { 191 log (LOG_INFO, "ic_errmsg len %d", len); 192 m_free (m); 193 return; 194 } 195 m->m_len = len; 196 197 /* ICMP header */ 198 { 199 register struct icmp *ic; 200 201 ic = mtod(m, struct icmp *); 202 ic->ic_type = type; 203 ic->ic_code = code; 204 ic->ic_off = off; 205 if (dlen > 0) 206 bcopy(dp, ic->ic_data, dlen); 207 ic->ic_sum = 0; 208 ic->ic_sum = in_cksum(m, len); 209 } 210 211 /* IP header */ 212 { 213 register struct ip *ip; 214 215 m->m_off -= sizeof(struct ip); 216 m->m_len += sizeof(struct ip); 217 ip = mtod(m, struct ip *); 218 ip->ip_p = IPPROTO_ICMP; 219 ip->ip_tos = 0; 220 ip->ip_src = src; 221 ip->ip_dst = dst; 222 } 223 224 NOPCB_IPSEND (m, (int)len, FALSE, error); 225 226 #ifdef lint 227 error = error; 228 #endif 229 } 230 231 #ifdef BBNPING 232 ping(gwaddr) 233 struct in_addr gwaddr; 234 { 235 register struct mbuf *m; 236 237 if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 238 return; 239 m->m_off = MMAXOFF - ICMPSIZE; 240 m->m_len = ICMPSIZE; 241 { 242 register struct icmp *ic; 243 244 ic = mtod (m, struct icmp *); 245 ic->ic_type = ICMP_ECHO; 246 ic->ic_code = 0; 247 ic->ic_id = MY_ECHO_ID; 248 ic->ic_sum = 0; 249 ic->ic_sum = in_cksum(m, ICMPSIZE); 250 } 251 252 m->m_off -= sizeof(struct ip); 253 m->m_len += sizeof(struct ip); 254 { 255 register struct ip *ip; 256 257 ip = mtod(m, struct ip *); 258 ip->ip_p = IPPROTO_ICMP; 259 ip->ip_tos = 0; 260 ip->ip_dst = gwaddr; 261 ip->ip_src = ping_addr (ip); 262 } 263 264 { 265 register int error; 266 267 NOPCB_IPSEND (m, ICMPSIZE, FALSE, error); 268 #ifdef lint 269 error = error; 270 #endif 271 } 272 } 273 #endif 274