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 #ifdef bsd42 81 /* note we use ip_src, not ip_dst here */ 82 if ((ia = in_iawithnet(ip->ip_src)) == NULL) 83 { 84 struct in_addr l; 85 86 l.s_addr = INADDR_ANY; 87 return (l); 88 } 89 ia = in_iafromif(inetifp); 90 return (IA_INADDR(ia)); 91 } 92 93 /* 94 * There are a few icmp output routines since the header has some variable 95 * types in it ... 96 */ 97 send_redirect (redirip, use, code, icmplen) 98 struct ip *redirip; 99 struct in_addr use; 100 unsigned icmplen; 101 { 102 register struct mbuf *m; 103 int error; 104 105 if (m = m_get(M_DONTWAIT, MT_HEADER)) 106 { 107 m->m_len = ICMPSIZE + icmplen; 108 m->m_off = MMAXOFF - m->m_len; 109 { 110 register struct icmp *ic; 111 112 ic = mtod(m, struct icmp *); 113 ic->ic_type = ICMP_REDIR; 114 ic->ic_code = code; 115 ic->ic_sum = 0; 116 ic->ic_gaddr = use; 117 if (icmplen > 0) 118 bcopy ((caddr_t)redirip, ic->ic_data, icmplen); 119 120 /* used to use an inline cksum here */ 121 ic->ic_sum = in_cksum (m, m->m_len); 122 } 123 124 m->m_off -= sizeof(struct ip); 125 m->m_len += sizeof(struct ip); 126 { 127 register struct ip *ip; 128 129 ip = mtod(m, struct ip *); 130 ip->ip_p = IPPROTO_ICMP; 131 ip->ip_tos = 0; 132 ip->ip_dst = redirip->ip_src; 133 ip->ip_src = redir_addr(redirip); 134 } 135 NOPCB_IPSEND (m, (int)icmplen, FALSE, error); 136 137 #ifdef lint 138 error = error ; 139 #endif 140 } 141 } 142 143 /* 144 * Send an ICMP error message. Note that data must not exceed single mbuf. 145 */ 146 ic_errmsg (src, dst, type, code, off, dlen, dp) 147 struct in_addr src; 148 struct in_addr dst; 149 unsigned dlen; 150 caddr_t dp; /* assumed to be contiguous */ 151 { 152 register struct mbuf *m; 153 register unsigned len; 154 int error; 155 156 if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 157 return /*ENOBUFS*/; 158 159 /* 160 * Build ICMP header 161 */ 162 len = ICMPSIZE + dlen; 163 m->m_off = MMAXOFF - len; 164 if (m->m_off < (MMINOFF + sizeof(struct ip))) 165 { 166 log (LOG_INFO, "ic_errmsg len %d", len); 167 m_free (m); 168 return; 169 } 170 m->m_len = len; 171 172 /* ICMP header */ 173 { 174 register struct icmp *ic; 175 176 ic = mtod(m, struct icmp *); 177 ic->ic_type = type; 178 ic->ic_code = code; 179 ic->ic_off = off; 180 if (dlen > 0) 181 bcopy(dp, ic->ic_data, dlen); 182 ic->ic_sum = 0; 183 ic->ic_sum = in_cksum(m, len); 184 } 185 186 /* IP header */ 187 { 188 register struct ip *ip; 189 190 m->m_off -= sizeof(struct ip); 191 m->m_len += sizeof(struct ip); 192 ip = mtod(m, struct ip *); 193 ip->ip_p = IPPROTO_ICMP; 194 ip->ip_tos = 0; 195 ip->ip_src = src; 196 ip->ip_dst = dst; 197 } 198 199 NOPCB_IPSEND (m, (int)len, FALSE, error); 200 201 #ifdef lint 202 error = error; 203 #endif 204 } 205 206 #ifdef BBNPING 207 ping(gwaddr) 208 struct in_addr gwaddr; 209 { 210 register struct mbuf *m; 211 212 if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 213 return; 214 m->m_off = MMAXOFF - ICMPSIZE; 215 m->m_len = ICMPSIZE; 216 { 217 register struct icmp *ic; 218 219 ic = mtod (m, struct icmp *); 220 ic->ic_type = ICMP_ECHO; 221 ic->ic_code = 0; 222 ic->ic_id = MY_ECHO_ID; 223 ic->ic_sum = 0; 224 ic->ic_sum = in_cksum(m, ICMPSIZE); 225 } 226 227 m->m_off -= sizeof(struct ip); 228 m->m_len += sizeof(struct ip); 229 { 230 register struct ip *ip; 231 232 ip = mtod(m, struct ip *); 233 ip->ip_p = IPPROTO_ICMP; 234 ip->ip_tos = 0; 235 ip->ip_dst = gwaddr; 236 ip->ip_src = icmp_addr (ip); 237 } 238 239 { 240 register int error; 241 242 NOPCB_IPSEND (m, ICMPSIZE, FALSE, error); 243 #ifdef lint 244 error = error; 245 #endif 246 } 247 } 248 #endif 249