1 /* 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)raw_ip.c 7.8 (Berkeley) 7/25/90 34 * 35 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE 36 * -------------------- ----- ---------------------- 37 * CURRENT PATCH LEVEL: 1 00020 38 * -------------------- ----- ---------------------- 39 * 40 * 03 Nov 92 Julian Elischer Fixed memory leak that caused ping 41 * and traceroute to cause panic 42 */ 43 44 #include "param.h" 45 #include "malloc.h" 46 #include "mbuf.h" 47 #include "socket.h" 48 #include "protosw.h" 49 #include "socketvar.h" 50 #include "errno.h" 51 52 #include "../net/if.h" 53 #include "../net/route.h" 54 #include "../net/raw_cb.h" 55 56 #include "in.h" 57 #include "in_systm.h" 58 #include "ip.h" 59 #include "ip_var.h" 60 #include "in_pcb.h" 61 62 /* 63 * Raw interface to IP protocol. 64 */ 65 66 struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET }; 67 struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; 68 struct sockproto ripproto = { PF_INET }; 69 /* 70 * Setup generic address and protocol structures 71 * for raw_input routine, then pass them along with 72 * mbuf chain. 73 */ 74 rip_input(m) 75 struct mbuf *m; 76 { 77 register struct ip *ip = mtod(m, struct ip *); 78 79 ripproto.sp_protocol = ip->ip_p; 80 ripdst.sin_addr = ip->ip_dst; 81 ripsrc.sin_addr = ip->ip_src; 82 if (raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 83 (struct sockaddr *)&ripdst) == 0) { 84 ipstat.ips_noproto++; 85 ipstat.ips_delivered--; 86 } 87 } 88 89 /* 90 * Generate IP header and pass packet to ip_output. 91 * Tack on options user may have setup with control call. 92 */ 93 #define satosin(sa) ((struct sockaddr_in *)(sa)) 94 rip_output(m, so) 95 register struct mbuf *m; 96 struct socket *so; 97 { 98 register struct ip *ip; 99 register struct raw_inpcb *rp = sotorawinpcb(so); 100 register struct sockaddr_in *sin; 101 102 /* 103 * If the user handed us a complete IP packet, use it. 104 * Otherwise, allocate an mbuf for a header and fill it in. 105 */ 106 if (rp->rinp_flags & RINPF_HDRINCL) 107 ip = mtod(m, struct ip *); 108 else { 109 M_PREPEND(m, sizeof(struct ip), M_WAIT); 110 ip = mtod(m, struct ip *); 111 ip->ip_tos = 0; 112 ip->ip_off = 0; 113 ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol; 114 ip->ip_len = m->m_pkthdr.len; 115 if (sin = satosin(rp->rinp_rcb.rcb_laddr)) { 116 ip->ip_src = sin->sin_addr; 117 } else 118 ip->ip_src.s_addr = 0; 119 if (sin = satosin(rp->rinp_rcb.rcb_faddr)) 120 ip->ip_dst = sin->sin_addr; 121 ip->ip_ttl = MAXTTL; 122 } 123 return (ip_output(m, 124 (rp->rinp_flags & RINPF_HDRINCL)? (struct mbuf *)0: rp->rinp_options, 125 &rp->rinp_route, 126 (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 127 } 128 129 /* 130 * Raw IP socket option processing. 131 */ 132 rip_ctloutput(op, so, level, optname, m) 133 int op; 134 struct socket *so; 135 int level, optname; 136 struct mbuf **m; 137 { 138 int error = 0; 139 register struct raw_inpcb *rp = sotorawinpcb(so); 140 141 if (level != IPPROTO_IP) 142 error = EINVAL; 143 else switch (op) { 144 145 case PRCO_SETOPT: 146 switch (optname) { 147 148 case IP_OPTIONS: 149 return (ip_pcbopts(&rp->rinp_options, *m)); 150 151 case IP_HDRINCL: 152 if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) { 153 error = EINVAL; 154 break; 155 } 156 if (*mtod(*m, int *)) 157 rp->rinp_flags |= RINPF_HDRINCL; 158 else 159 rp->rinp_flags &= ~RINPF_HDRINCL; 160 break; 161 162 default: 163 error = EINVAL; 164 break; 165 } 166 break; 167 168 case PRCO_GETOPT: 169 *m = m_get(M_WAIT, MT_SOOPTS); 170 switch (optname) { 171 172 case IP_OPTIONS: 173 if (rp->rinp_options) { 174 (*m)->m_len = rp->rinp_options->m_len; 175 bcopy(mtod(rp->rinp_options, caddr_t), 176 mtod(*m, caddr_t), (unsigned)(*m)->m_len); 177 } else 178 (*m)->m_len = 0; 179 break; 180 181 case IP_HDRINCL: 182 (*m)->m_len = sizeof (int); 183 *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL; 184 break; 185 186 default: 187 error = EINVAL; 188 m_freem(*m); 189 *m = 0; 190 break; 191 } 192 break; 193 } 194 if (op == PRCO_SETOPT && *m) 195 (void)m_free(*m); 196 return (error); 197 } 198 199 /*ARGSUSED*/ 200 rip_usrreq(so, req, m, nam, control) 201 register struct socket *so; 202 int req; 203 struct mbuf *m, *nam, *control; 204 { 205 register int error = 0; 206 register struct raw_inpcb *rp = sotorawinpcb(so); 207 208 switch (req) { 209 210 case PRU_ATTACH: 211 if (rp) 212 panic("rip_attach"); 213 MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK); 214 if (rp == 0) 215 return (ENOBUFS); 216 bzero((caddr_t)rp, sizeof *rp); 217 so->so_pcb = (caddr_t)rp; 218 break; 219 220 case PRU_DETACH: 221 if (rp == 0) 222 panic("rip_detach"); 223 if (rp->rinp_options) 224 m_freem(rp->rinp_options); 225 if (rp->rinp_route.ro_rt) 226 RTFREE(rp->rinp_route.ro_rt); 227 if (rp->rinp_rcb.rcb_laddr) 228 rp->rinp_rcb.rcb_laddr = 0; 229 break; 230 231 case PRU_BIND: 232 { 233 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 234 235 if (nam->m_len != sizeof(*addr)) 236 return (EINVAL); 237 if ((ifnet == 0) || 238 ((addr->sin_family != AF_INET) && 239 (addr->sin_family != AF_IMPLINK)) || 240 (addr->sin_addr.s_addr && 241 ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 242 return (EADDRNOTAVAIL); 243 rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr; 244 rp->rinp_laddr = *addr; 245 return (0); 246 } 247 case PRU_CONNECT: 248 { 249 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 250 251 if (nam->m_len != sizeof(*addr)) 252 return (EINVAL); 253 if (ifnet == 0) 254 return (EADDRNOTAVAIL); 255 if ((addr->sin_family != AF_INET) && 256 (addr->sin_family != AF_IMPLINK)) 257 return (EAFNOSUPPORT); 258 rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr; 259 rp->rinp_faddr = *addr; 260 soisconnected(so); 261 return (0); 262 } 263 } 264 error = raw_usrreq(so, req, m, nam, control); 265 266 if (error && (req == PRU_ATTACH) && so->so_pcb) 267 free(so->so_pcb, M_PCB); 268 return (error); 269 } 270