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 */ 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 6425202Skarels /* 6525202Skarels * notes to above mostly apply 6625202Skarels * 6725202Skarels * icmp_addr() sort of assumes the packet was addressed to us. But when we 6825202Skarels * act as a getway, S sends to A1, and we use A2 to get to D. We want to 6925202Skarels * reply with the A1 address, not the A2 address. 7025202Skarels */ 7125202Skarels struct in_addr redir_addr (ip) 7225202Skarels struct ip *ip; 7325202Skarels { 7425202Skarels register struct in_ifaddr *ia; 7525202Skarels 7625202Skarels #ifdef bsd42 7725202Skarels /* note we use ip_src, not ip_dst here */ 7825202Skarels if ((ia = in_iawithnet(ip->ip_src)) == NULL) 7925202Skarels { 8025202Skarels struct in_addr l; 8125202Skarels 8225202Skarels l.s_addr = INADDR_ANY; 8325202Skarels return (l); 8425202Skarels } 8525202Skarels #endif 8625202Skarels ia = in_iafromif(inetifp); 8725202Skarels return (IA_INADDR(ia)); 8825202Skarels } 8925202Skarels 9025202Skarels /* 9125202Skarels * There are a few icmp output routines since the header has some variable 9225202Skarels * types in it ... 9325202Skarels */ 9425202Skarels send_redirect (redirip, use, code, icmplen) 9525202Skarels struct ip *redirip; 9625202Skarels struct in_addr use; 9725202Skarels unsigned icmplen; 9825202Skarels { 9925202Skarels register struct mbuf *m; 10025202Skarels int error; 10125202Skarels 10225202Skarels if (m = m_get(M_DONTWAIT, MT_HEADER)) 10325202Skarels { 10425202Skarels m->m_len = ICMPSIZE + icmplen; 10525202Skarels m->m_off = MMAXOFF - m->m_len; 10625202Skarels { 10725202Skarels register struct icmp *ic; 10825202Skarels 10925202Skarels ic = mtod(m, struct icmp *); 11025202Skarels ic->ic_type = ICMP_REDIR; 11125202Skarels ic->ic_code = code; 11225202Skarels ic->ic_sum = 0; 11325202Skarels ic->ic_gaddr = use; 11425202Skarels if (icmplen > 0) 11525202Skarels bcopy ((caddr_t)redirip, ic->ic_data, icmplen); 11625202Skarels 11725202Skarels /* used to use an inline cksum here */ 11825202Skarels ic->ic_sum = in_cksum (m, m->m_len); 11925202Skarels } 12025202Skarels 12125202Skarels m->m_off -= sizeof(struct ip); 12225202Skarels m->m_len += sizeof(struct ip); 12325202Skarels { 12425202Skarels register struct ip *ip; 12525202Skarels 12625202Skarels ip = mtod(m, struct ip *); 12725202Skarels ip->ip_p = IPPROTO_ICMP; 12825202Skarels ip->ip_tos = 0; 12925202Skarels ip->ip_dst = redirip->ip_src; 13025202Skarels ip->ip_src = redir_addr(redirip); 13125202Skarels } 13225202Skarels NOPCB_IPSEND (m, (int)icmplen, FALSE, error); 13325202Skarels 13425202Skarels #ifdef lint 13525202Skarels error = error ; 13625202Skarels #endif 13725202Skarels } 13825202Skarels } 13925202Skarels 14025202Skarels /* 14125202Skarels * Send an ICMP error message. Note that data must not exceed single mbuf. 14225202Skarels */ 14325202Skarels ic_errmsg (src, dst, type, code, off, dlen, dp) 14425202Skarels struct in_addr src; 14525202Skarels struct in_addr dst; 14625202Skarels unsigned dlen; 14725202Skarels caddr_t dp; /* assumed to be contiguous */ 14825202Skarels { 14925202Skarels register struct mbuf *m; 15025202Skarels register unsigned len; 15125202Skarels int error; 15225202Skarels 15325202Skarels if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 15425202Skarels return /*ENOBUFS*/; 15525202Skarels 15625202Skarels /* 15725202Skarels * Build ICMP header 15825202Skarels */ 15925202Skarels len = ICMPSIZE + dlen; 16025202Skarels m->m_off = MMAXOFF - len; 16125202Skarels if (m->m_off < (MMINOFF + sizeof(struct ip))) 16225202Skarels { 163*25205Skarels log (LOG_INFO, "ic_errmsg len %d", len); 16425202Skarels m_free (m); 16525202Skarels return; 16625202Skarels } 16725202Skarels m->m_len = len; 16825202Skarels 16925202Skarels /* ICMP header */ 17025202Skarels { 17125202Skarels register struct icmp *ic; 17225202Skarels 17325202Skarels ic = mtod(m, struct icmp *); 17425202Skarels ic->ic_type = type; 17525202Skarels ic->ic_code = code; 17625202Skarels ic->ic_off = off; 17725202Skarels if (dlen > 0) 17825202Skarels bcopy(dp, ic->ic_data, dlen); 17925202Skarels ic->ic_sum = 0; 18025202Skarels ic->ic_sum = in_cksum(m, len); 18125202Skarels } 18225202Skarels 18325202Skarels /* IP header */ 18425202Skarels { 18525202Skarels register struct ip *ip; 18625202Skarels 18725202Skarels m->m_off -= sizeof(struct ip); 18825202Skarels m->m_len += sizeof(struct ip); 18925202Skarels ip = mtod(m, struct ip *); 19025202Skarels ip->ip_p = IPPROTO_ICMP; 19125202Skarels ip->ip_tos = 0; 19225202Skarels ip->ip_src = src; 19325202Skarels ip->ip_dst = dst; 19425202Skarels } 19525202Skarels 19625202Skarels NOPCB_IPSEND (m, (int)len, FALSE, error); 19725202Skarels 19825202Skarels #ifdef lint 19925202Skarels error = error; 20025202Skarels #endif 20125202Skarels } 20225202Skarels 20325202Skarels #ifdef BBNPING 20425202Skarels ping(gwaddr) 20525202Skarels struct in_addr gwaddr; 20625202Skarels { 20725202Skarels register struct mbuf *m; 20825202Skarels 20925202Skarels if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 21025202Skarels return; 21125202Skarels m->m_off = MMAXOFF - ICMPSIZE; 21225202Skarels m->m_len = ICMPSIZE; 21325202Skarels { 21425202Skarels register struct icmp *ic; 21525202Skarels 21625202Skarels ic = mtod (m, struct icmp *); 21725202Skarels ic->ic_type = ICMP_ECHO; 21825202Skarels ic->ic_code = 0; 21925202Skarels ic->ic_id = MY_ECHO_ID; 22025202Skarels ic->ic_sum = 0; 22125202Skarels ic->ic_sum = in_cksum(m, ICMPSIZE); 22225202Skarels } 22325202Skarels 22425202Skarels m->m_off -= sizeof(struct ip); 22525202Skarels m->m_len += sizeof(struct ip); 22625202Skarels { 22725202Skarels register struct ip *ip; 22825202Skarels 22925202Skarels ip = mtod(m, struct ip *); 23025202Skarels ip->ip_p = IPPROTO_ICMP; 23125202Skarels ip->ip_tos = 0; 23225202Skarels ip->ip_dst = gwaddr; 23325202Skarels ip->ip_src = icmp_addr (ip); 23425202Skarels } 23525202Skarels 23625202Skarels { 23725202Skarels register int error; 23825202Skarels 23925202Skarels NOPCB_IPSEND (m, ICMPSIZE, FALSE, error); 24025202Skarels #ifdef lint 24125202Skarels error = error; 24225202Skarels #endif 24325202Skarels } 24425202Skarels } 24525202Skarels #endif 246