125202Skarels #include "../h/param.h"
225202Skarels #include "../h/systm.h"
325202Skarels #include "../h/mbuf.h"
425202Skarels #include "../h/socket.h"
525202Skarels #include "../h/socketvar.h"
625202Skarels #include "../h/protosw.h"
725202Skarels #include "../h/syslog.h"
825202Skarels
925202Skarels #include "../net/if.h"
1025202Skarels #include "../net/route.h"
1125202Skarels
1225202Skarels #include "../bbnnet/in.h"
1325202Skarels #include "../bbnnet/net.h"
1425202Skarels #include "../bbnnet/in_pcb.h"
1525202Skarels #include "../bbnnet/in_var.h"
1625202Skarels #include "../bbnnet/ip.h"
1725202Skarels #include "../bbnnet/icmp.h"
1825202Skarels #include "../bbnnet/nopcb.h"
1925202Skarels
2025202Skarels extern struct ifnet *inetifp;
2125202Skarels
2225202Skarels /*
2325202Skarels * We are generating an ICMP error message in response to this packet sent
2425202Skarels * to us. Too bad the device driver doesn't pair a pointer to its ifnet with
2525202Skarels * the incoming packet. That would save us a search, and we could use that
2625202Skarels * for our source address in the ICMP error message.
2725202Skarels *
2825202Skarels * Pick a source address for that ICMP error message we send. We can't
2925202Skarels * always use ip_dst of the original for the ip_src of the ICMP error
3025202Skarels * message since the packet may have been broadcast.
3125202Skarels *
3225202Skarels * We try to establish a proper interface to respond by in case we're
3325202Skarels * multi-homed. Try to respond by interface received on rather than
3425202Skarels * interface that represents most direct route back.
3525202Skarels */
icmp_addr(ip)3625202Skarels struct in_addr icmp_addr (ip)
3725202Skarels struct ip *ip;
3825202Skarels {
3925202Skarels struct in_ifaddr *ia;
4025202Skarels
4125202Skarels #ifdef bsd42
4225202Skarels /* don't want broadcasts to match */
4325202Skarels if (! (ia = in_iawithaddr(ip->ip_dst, FALSE)))
4425202Skarels {
4525202Skarels /* hmm, try for the net... */
4625202Skarels if ((ia = in_iawithnet(ip->ip_dst)) == NULL)
4725202Skarels {
4825202Skarels struct in_addr l;
4925202Skarels
5025202Skarels /*
5125202Skarels * The message will be sent by ip_send() who will
5225202Skarels * route the message and discover that a local address
5325202Skarels * should be set on the basis of the route used.
5425202Skarels */
5525202Skarels l.s_addr = INADDR_ANY;
5625202Skarels return (l);
5725202Skarels }
5825202Skarels }
5925202Skarels #endif
6025202Skarels ia = in_iafromif(inetifp);
6125202Skarels return (IA_INADDR(ia));
6225202Skarels }
6325202Skarels
64*25660Slam
65*25660Slam
66*25660Slam
ping_addr(ip)67*25660Slam struct in_addr ping_addr (ip)
68*25660Slam struct ip *ip;
69*25660Slam {
70*25660Slam struct in_ifaddr *ia;
71*25660Slam
72*25660Slam /* don't want broadcasts to match */
73*25660Slam if (! (ia = in_iawithaddr(ip->ip_dst, FALSE)))
74*25660Slam {
75*25660Slam /* hmm, try for the net... */
76*25660Slam if ((ia = in_iawithnet(ip->ip_dst)) == NULL)
77*25660Slam {
78*25660Slam struct in_addr l;
79*25660Slam
80*25660Slam /*
81*25660Slam * The message will be sent by ip_send() who will
82*25660Slam * route the message and discover that a local address
83*25660Slam * should be set on the basis of the route used.
84*25660Slam */
85*25660Slam l.s_addr = INADDR_ANY;
86*25660Slam return (l);
87*25660Slam }
88*25660Slam }
89*25660Slam return (IA_INADDR(ia));
90*25660Slam }
91*25660Slam
9225202Skarels /*
9325202Skarels * notes to above mostly apply
9425202Skarels *
9525202Skarels * icmp_addr() sort of assumes the packet was addressed to us. But when we
9625202Skarels * act as a getway, S sends to A1, and we use A2 to get to D. We want to
9725202Skarels * reply with the A1 address, not the A2 address.
9825202Skarels */
redir_addr(ip)9925202Skarels struct in_addr redir_addr (ip)
10025202Skarels struct ip *ip;
10125202Skarels {
10225202Skarels register struct in_ifaddr *ia;
10325202Skarels
10425202Skarels #ifdef bsd42
10525202Skarels /* note we use ip_src, not ip_dst here */
10625202Skarels if ((ia = in_iawithnet(ip->ip_src)) == NULL)
10725202Skarels {
10825202Skarels struct in_addr l;
10925202Skarels
11025202Skarels l.s_addr = INADDR_ANY;
11125202Skarels return (l);
11225202Skarels }
113*25660Slam #endif
11425202Skarels ia = in_iafromif(inetifp);
11525202Skarels return (IA_INADDR(ia));
11625202Skarels }
11725202Skarels
11825202Skarels /*
11925202Skarels * There are a few icmp output routines since the header has some variable
12025202Skarels * types in it ...
12125202Skarels */
12225202Skarels send_redirect (redirip, use, code, icmplen)
12325202Skarels struct ip *redirip;
12425202Skarels struct in_addr use;
12525202Skarels unsigned icmplen;
12625202Skarels {
12725202Skarels register struct mbuf *m;
12825202Skarels int error;
12925202Skarels
13025202Skarels if (m = m_get(M_DONTWAIT, MT_HEADER))
13125202Skarels {
13225202Skarels m->m_len = ICMPSIZE + icmplen;
13325202Skarels m->m_off = MMAXOFF - m->m_len;
13425202Skarels {
13525202Skarels register struct icmp *ic;
13625202Skarels
13725202Skarels ic = mtod(m, struct icmp *);
13825202Skarels ic->ic_type = ICMP_REDIR;
13925202Skarels ic->ic_code = code;
14025202Skarels ic->ic_sum = 0;
14125202Skarels ic->ic_gaddr = use;
14225202Skarels if (icmplen > 0)
14325202Skarels bcopy ((caddr_t)redirip, ic->ic_data, icmplen);
14425202Skarels
14525202Skarels /* used to use an inline cksum here */
14625202Skarels ic->ic_sum = in_cksum (m, m->m_len);
14725202Skarels }
14825202Skarels
14925202Skarels m->m_off -= sizeof(struct ip);
15025202Skarels m->m_len += sizeof(struct ip);
15125202Skarels {
15225202Skarels register struct ip *ip;
15325202Skarels
15425202Skarels ip = mtod(m, struct ip *);
15525202Skarels ip->ip_p = IPPROTO_ICMP;
15625202Skarels ip->ip_tos = 0;
15725202Skarels ip->ip_dst = redirip->ip_src;
15825202Skarels ip->ip_src = redir_addr(redirip);
15925202Skarels }
16025202Skarels NOPCB_IPSEND (m, (int)icmplen, FALSE, error);
16125202Skarels
16225202Skarels #ifdef lint
16325202Skarels error = error ;
16425202Skarels #endif
16525202Skarels }
16625202Skarels }
16725202Skarels
16825202Skarels /*
16925202Skarels * Send an ICMP error message. Note that data must not exceed single mbuf.
17025202Skarels */
17125202Skarels ic_errmsg (src, dst, type, code, off, dlen, dp)
17225202Skarels struct in_addr src;
17325202Skarels struct in_addr dst;
17425202Skarels unsigned dlen;
17525202Skarels caddr_t dp; /* assumed to be contiguous */
17625202Skarels {
17725202Skarels register struct mbuf *m;
17825202Skarels register unsigned len;
17925202Skarels int error;
18025202Skarels
18125202Skarels if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL)
18225202Skarels return /*ENOBUFS*/;
18325202Skarels
18425202Skarels /*
18525202Skarels * Build ICMP header
18625202Skarels */
18725202Skarels len = ICMPSIZE + dlen;
18825202Skarels m->m_off = MMAXOFF - len;
18925202Skarels if (m->m_off < (MMINOFF + sizeof(struct ip)))
19025202Skarels {
19125205Skarels log (LOG_INFO, "ic_errmsg len %d", len);
19225202Skarels m_free (m);
19325202Skarels return;
19425202Skarels }
19525202Skarels m->m_len = len;
19625202Skarels
19725202Skarels /* ICMP header */
19825202Skarels {
19925202Skarels register struct icmp *ic;
20025202Skarels
20125202Skarels ic = mtod(m, struct icmp *);
20225202Skarels ic->ic_type = type;
20325202Skarels ic->ic_code = code;
20425202Skarels ic->ic_off = off;
20525202Skarels if (dlen > 0)
20625202Skarels bcopy(dp, ic->ic_data, dlen);
20725202Skarels ic->ic_sum = 0;
20825202Skarels ic->ic_sum = in_cksum(m, len);
20925202Skarels }
21025202Skarels
21125202Skarels /* IP header */
21225202Skarels {
21325202Skarels register struct ip *ip;
21425202Skarels
21525202Skarels m->m_off -= sizeof(struct ip);
21625202Skarels m->m_len += sizeof(struct ip);
21725202Skarels ip = mtod(m, struct ip *);
21825202Skarels ip->ip_p = IPPROTO_ICMP;
21925202Skarels ip->ip_tos = 0;
22025202Skarels ip->ip_src = src;
22125202Skarels ip->ip_dst = dst;
22225202Skarels }
22325202Skarels
22425202Skarels NOPCB_IPSEND (m, (int)len, FALSE, error);
22525202Skarels
22625202Skarels #ifdef lint
22725202Skarels error = error;
22825202Skarels #endif
22925202Skarels }
23025202Skarels
23125202Skarels #ifdef BBNPING
23225202Skarels ping(gwaddr)
23325202Skarels struct in_addr gwaddr;
23425202Skarels {
23525202Skarels register struct mbuf *m;
23625202Skarels
23725202Skarels if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL)
23825202Skarels return;
23925202Skarels m->m_off = MMAXOFF - ICMPSIZE;
24025202Skarels m->m_len = ICMPSIZE;
24125202Skarels {
24225202Skarels register struct icmp *ic;
24325202Skarels
24425202Skarels ic = mtod (m, struct icmp *);
24525202Skarels ic->ic_type = ICMP_ECHO;
24625202Skarels ic->ic_code = 0;
24725202Skarels ic->ic_id = MY_ECHO_ID;
24825202Skarels ic->ic_sum = 0;
24925202Skarels ic->ic_sum = in_cksum(m, ICMPSIZE);
25025202Skarels }
25125202Skarels
25225202Skarels m->m_off -= sizeof(struct ip);
25325202Skarels m->m_len += sizeof(struct ip);
25425202Skarels {
25525202Skarels register struct ip *ip;
25625202Skarels
25725202Skarels ip = mtod(m, struct ip *);
25825202Skarels ip->ip_p = IPPROTO_ICMP;
25925202Skarels ip->ip_tos = 0;
26025202Skarels ip->ip_dst = gwaddr;
261*25660Slam ip->ip_src = ping_addr (ip);
26225202Skarels }
26325202Skarels
26425202Skarels {
26525202Skarels register int error;
26625202Skarels
26725202Skarels NOPCB_IPSEND (m, ICMPSIZE, FALSE, error);
26825202Skarels #ifdef lint
26925202Skarels error = error;
27025202Skarels #endif
27125202Skarels }
27225202Skarels }
27325202Skarels #endif
274