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 */
icmp_addr(ip)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
ping_addr(ip)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 */
redir_addr(ip)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