1*25202Skarels #include "../h/param.h" 2*25202Skarels #include "../h/systm.h" 3*25202Skarels #include "../h/mbuf.h" 4*25202Skarels #include "../h/socket.h" 5*25202Skarels #include "../h/socketvar.h" 6*25202Skarels #include "../h/protosw.h" 7*25202Skarels #include "../h/syslog.h" 8*25202Skarels 9*25202Skarels #include "../net/if.h" 10*25202Skarels #include "../net/route.h" 11*25202Skarels 12*25202Skarels #include "../bbnnet/in.h" 13*25202Skarels #include "../bbnnet/net.h" 14*25202Skarels #include "../bbnnet/in_pcb.h" 15*25202Skarels #include "../bbnnet/in_var.h" 16*25202Skarels #include "../bbnnet/ip.h" 17*25202Skarels #include "../bbnnet/icmp.h" 18*25202Skarels #include "../bbnnet/nopcb.h" 19*25202Skarels 20*25202Skarels extern struct ifnet *inetifp; 21*25202Skarels 22*25202Skarels /* 23*25202Skarels * We are generating an ICMP error message in response to this packet sent 24*25202Skarels * to us. Too bad the device driver doesn't pair a pointer to its ifnet with 25*25202Skarels * the incoming packet. That would save us a search, and we could use that 26*25202Skarels * for our source address in the ICMP error message. 27*25202Skarels * 28*25202Skarels * Pick a source address for that ICMP error message we send. We can't 29*25202Skarels * always use ip_dst of the original for the ip_src of the ICMP error 30*25202Skarels * message since the packet may have been broadcast. 31*25202Skarels * 32*25202Skarels * We try to establish a proper interface to respond by in case we're 33*25202Skarels * multi-homed. Try to respond by interface received on rather than 34*25202Skarels * interface that represents most direct route back. 35*25202Skarels */ 36*25202Skarels struct in_addr icmp_addr (ip) 37*25202Skarels struct ip *ip; 38*25202Skarels { 39*25202Skarels struct in_ifaddr *ia; 40*25202Skarels 41*25202Skarels #ifdef bsd42 42*25202Skarels /* don't want broadcasts to match */ 43*25202Skarels if (! (ia = in_iawithaddr(ip->ip_dst, FALSE))) 44*25202Skarels { 45*25202Skarels /* hmm, try for the net... */ 46*25202Skarels if ((ia = in_iawithnet(ip->ip_dst)) == NULL) 47*25202Skarels { 48*25202Skarels struct in_addr l; 49*25202Skarels 50*25202Skarels /* 51*25202Skarels * The message will be sent by ip_send() who will 52*25202Skarels * route the message and discover that a local address 53*25202Skarels * should be set on the basis of the route used. 54*25202Skarels */ 55*25202Skarels l.s_addr = INADDR_ANY; 56*25202Skarels return (l); 57*25202Skarels } 58*25202Skarels } 59*25202Skarels #endif 60*25202Skarels ia = in_iafromif(inetifp); 61*25202Skarels return (IA_INADDR(ia)); 62*25202Skarels } 63*25202Skarels 64*25202Skarels /* 65*25202Skarels * notes to above mostly apply 66*25202Skarels * 67*25202Skarels * icmp_addr() sort of assumes the packet was addressed to us. But when we 68*25202Skarels * act as a getway, S sends to A1, and we use A2 to get to D. We want to 69*25202Skarels * reply with the A1 address, not the A2 address. 70*25202Skarels */ 71*25202Skarels struct in_addr redir_addr (ip) 72*25202Skarels struct ip *ip; 73*25202Skarels { 74*25202Skarels register struct in_ifaddr *ia; 75*25202Skarels 76*25202Skarels #ifdef bsd42 77*25202Skarels /* note we use ip_src, not ip_dst here */ 78*25202Skarels if ((ia = in_iawithnet(ip->ip_src)) == NULL) 79*25202Skarels { 80*25202Skarels struct in_addr l; 81*25202Skarels 82*25202Skarels l.s_addr = INADDR_ANY; 83*25202Skarels return (l); 84*25202Skarels } 85*25202Skarels #endif 86*25202Skarels ia = in_iafromif(inetifp); 87*25202Skarels return (IA_INADDR(ia)); 88*25202Skarels } 89*25202Skarels 90*25202Skarels /* 91*25202Skarels * There are a few icmp output routines since the header has some variable 92*25202Skarels * types in it ... 93*25202Skarels */ 94*25202Skarels send_redirect (redirip, use, code, icmplen) 95*25202Skarels struct ip *redirip; 96*25202Skarels struct in_addr use; 97*25202Skarels unsigned icmplen; 98*25202Skarels { 99*25202Skarels register struct mbuf *m; 100*25202Skarels int error; 101*25202Skarels 102*25202Skarels if (m = m_get(M_DONTWAIT, MT_HEADER)) 103*25202Skarels { 104*25202Skarels m->m_len = ICMPSIZE + icmplen; 105*25202Skarels m->m_off = MMAXOFF - m->m_len; 106*25202Skarels { 107*25202Skarels register struct icmp *ic; 108*25202Skarels 109*25202Skarels ic = mtod(m, struct icmp *); 110*25202Skarels ic->ic_type = ICMP_REDIR; 111*25202Skarels ic->ic_code = code; 112*25202Skarels ic->ic_sum = 0; 113*25202Skarels ic->ic_gaddr = use; 114*25202Skarels if (icmplen > 0) 115*25202Skarels bcopy ((caddr_t)redirip, ic->ic_data, icmplen); 116*25202Skarels 117*25202Skarels /* used to use an inline cksum here */ 118*25202Skarels ic->ic_sum = in_cksum (m, m->m_len); 119*25202Skarels } 120*25202Skarels 121*25202Skarels m->m_off -= sizeof(struct ip); 122*25202Skarels m->m_len += sizeof(struct ip); 123*25202Skarels { 124*25202Skarels register struct ip *ip; 125*25202Skarels 126*25202Skarels ip = mtod(m, struct ip *); 127*25202Skarels ip->ip_p = IPPROTO_ICMP; 128*25202Skarels ip->ip_tos = 0; 129*25202Skarels ip->ip_dst = redirip->ip_src; 130*25202Skarels ip->ip_src = redir_addr(redirip); 131*25202Skarels } 132*25202Skarels NOPCB_IPSEND (m, (int)icmplen, FALSE, error); 133*25202Skarels 134*25202Skarels #ifdef lint 135*25202Skarels error = error ; 136*25202Skarels #endif 137*25202Skarels } 138*25202Skarels } 139*25202Skarels 140*25202Skarels /* 141*25202Skarels * Send an ICMP error message. Note that data must not exceed single mbuf. 142*25202Skarels */ 143*25202Skarels ic_errmsg (src, dst, type, code, off, dlen, dp) 144*25202Skarels struct in_addr src; 145*25202Skarels struct in_addr dst; 146*25202Skarels unsigned dlen; 147*25202Skarels caddr_t dp; /* assumed to be contiguous */ 148*25202Skarels { 149*25202Skarels register struct mbuf *m; 150*25202Skarels register unsigned len; 151*25202Skarels int error; 152*25202Skarels 153*25202Skarels if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 154*25202Skarels return /*ENOBUFS*/; 155*25202Skarels 156*25202Skarels /* 157*25202Skarels * Build ICMP header 158*25202Skarels */ 159*25202Skarels len = ICMPSIZE + dlen; 160*25202Skarels m->m_off = MMAXOFF - len; 161*25202Skarels if (m->m_off < (MMINOFF + sizeof(struct ip))) 162*25202Skarels { 163*25202Skarels log (KERN_RECOV, "ic_errmsg len %d", len); 164*25202Skarels m_free (m); 165*25202Skarels return; 166*25202Skarels } 167*25202Skarels m->m_len = len; 168*25202Skarels 169*25202Skarels /* ICMP header */ 170*25202Skarels { 171*25202Skarels register struct icmp *ic; 172*25202Skarels 173*25202Skarels ic = mtod(m, struct icmp *); 174*25202Skarels ic->ic_type = type; 175*25202Skarels ic->ic_code = code; 176*25202Skarels ic->ic_off = off; 177*25202Skarels if (dlen > 0) 178*25202Skarels bcopy(dp, ic->ic_data, dlen); 179*25202Skarels ic->ic_sum = 0; 180*25202Skarels ic->ic_sum = in_cksum(m, len); 181*25202Skarels } 182*25202Skarels 183*25202Skarels /* IP header */ 184*25202Skarels { 185*25202Skarels register struct ip *ip; 186*25202Skarels 187*25202Skarels m->m_off -= sizeof(struct ip); 188*25202Skarels m->m_len += sizeof(struct ip); 189*25202Skarels ip = mtod(m, struct ip *); 190*25202Skarels ip->ip_p = IPPROTO_ICMP; 191*25202Skarels ip->ip_tos = 0; 192*25202Skarels ip->ip_src = src; 193*25202Skarels ip->ip_dst = dst; 194*25202Skarels } 195*25202Skarels 196*25202Skarels NOPCB_IPSEND (m, (int)len, FALSE, error); 197*25202Skarels 198*25202Skarels #ifdef lint 199*25202Skarels error = error; 200*25202Skarels #endif 201*25202Skarels } 202*25202Skarels 203*25202Skarels #ifdef BBNPING 204*25202Skarels ping(gwaddr) 205*25202Skarels struct in_addr gwaddr; 206*25202Skarels { 207*25202Skarels register struct mbuf *m; 208*25202Skarels 209*25202Skarels if ((m = m_get(M_DONTWAIT, MT_HEADER)) == NULL) 210*25202Skarels return; 211*25202Skarels m->m_off = MMAXOFF - ICMPSIZE; 212*25202Skarels m->m_len = ICMPSIZE; 213*25202Skarels { 214*25202Skarels register struct icmp *ic; 215*25202Skarels 216*25202Skarels ic = mtod (m, struct icmp *); 217*25202Skarels ic->ic_type = ICMP_ECHO; 218*25202Skarels ic->ic_code = 0; 219*25202Skarels ic->ic_id = MY_ECHO_ID; 220*25202Skarels ic->ic_sum = 0; 221*25202Skarels ic->ic_sum = in_cksum(m, ICMPSIZE); 222*25202Skarels } 223*25202Skarels 224*25202Skarels m->m_off -= sizeof(struct ip); 225*25202Skarels m->m_len += sizeof(struct ip); 226*25202Skarels { 227*25202Skarels register struct ip *ip; 228*25202Skarels 229*25202Skarels ip = mtod(m, struct ip *); 230*25202Skarels ip->ip_p = IPPROTO_ICMP; 231*25202Skarels ip->ip_tos = 0; 232*25202Skarels ip->ip_dst = gwaddr; 233*25202Skarels ip->ip_src = icmp_addr (ip); 234*25202Skarels } 235*25202Skarels 236*25202Skarels { 237*25202Skarels register int error; 238*25202Skarels 239*25202Skarels NOPCB_IPSEND (m, ICMPSIZE, FALSE, error); 240*25202Skarels #ifdef lint 241*25202Skarels error = error; 242*25202Skarels #endif 243*25202Skarels } 244*25202Skarels } 245*25202Skarels #endif 246