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