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 * from: @(#)raw_ip.c 7.8 (Berkeley) 7/25/90 34 * $Id: raw_ip.c,v 1.5 1993/05/22 11:42:37 cgd Exp $ 35 */ 36 37 #include "param.h" 38 #include "malloc.h" 39 #include "mbuf.h" 40 #include "socket.h" 41 #include "protosw.h" 42 #include "socketvar.h" 43 #include "errno.h" 44 45 #include "../net/if.h" 46 #include "../net/route.h" 47 #include "../net/raw_cb.h" 48 49 #include "in.h" 50 #include "in_systm.h" 51 #include "ip.h" 52 #include "ip_var.h" 53 #include "in_pcb.h" 54 55 /* 56 * Raw interface to IP protocol. 57 */ 58 59 struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET }; 60 struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; 61 struct sockproto ripproto = { PF_INET }; 62 /* 63 * Setup generic address and protocol structures 64 * for raw_input routine, then pass them along with 65 * mbuf chain. 66 */ 67 rip_input(m) 68 struct mbuf *m; 69 { 70 register struct ip *ip = mtod(m, struct ip *); 71 72 ripproto.sp_protocol = ip->ip_p; 73 ripdst.sin_addr = ip->ip_dst; 74 ripsrc.sin_addr = ip->ip_src; 75 if (raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 76 (struct sockaddr *)&ripdst) == 0) { 77 ipstat.ips_noproto++; 78 ipstat.ips_delivered--; 79 } 80 } 81 82 /* 83 * Generate IP header and pass packet to ip_output. 84 * Tack on options user may have setup with control call. 85 */ 86 #define satosin(sa) ((struct sockaddr_in *)(sa)) 87 rip_output(m, so) 88 register struct mbuf *m; 89 struct socket *so; 90 { 91 register struct ip *ip; 92 register struct raw_inpcb *rp = sotorawinpcb(so); 93 register struct sockaddr_in *sin; 94 95 /* 96 * If the user handed us a complete IP packet, use it. 97 * Otherwise, allocate an mbuf for a header and fill it in. 98 */ 99 if (rp->rinp_flags & RINPF_HDRINCL) { 100 ip = mtod(m, struct ip *); 101 if (ip->ip_len > m->m_pkthdr.len) 102 return EMSGSIZE; 103 ip->ip_len = m->m_pkthdr.len; 104 } else { 105 M_PREPEND(m, sizeof(struct ip), M_WAIT); 106 ip = mtod(m, struct ip *); 107 ip->ip_tos = 0; 108 ip->ip_off = 0; 109 ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol; 110 ip->ip_len = m->m_pkthdr.len; 111 if (sin = satosin(rp->rinp_rcb.rcb_laddr)) { 112 ip->ip_src = sin->sin_addr; 113 } else 114 ip->ip_src.s_addr = 0; 115 if (sin = satosin(rp->rinp_rcb.rcb_faddr)) 116 ip->ip_dst = sin->sin_addr; 117 ip->ip_ttl = MAXTTL; 118 } 119 return (ip_output(m, 120 (rp->rinp_flags & RINPF_HDRINCL)? (struct mbuf *)0: rp->rinp_options, 121 &rp->rinp_route, 122 (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 123 } 124 125 /* 126 * Raw IP socket option processing. 127 */ 128 rip_ctloutput(op, so, level, optname, m) 129 int op; 130 struct socket *so; 131 int level, optname; 132 struct mbuf **m; 133 { 134 int error = 0; 135 register struct raw_inpcb *rp = sotorawinpcb(so); 136 137 if (level != IPPROTO_IP) 138 error = EINVAL; 139 else switch (op) { 140 141 case PRCO_SETOPT: 142 switch (optname) { 143 144 case IP_OPTIONS: 145 return (ip_pcbopts(&rp->rinp_options, *m)); 146 147 case IP_HDRINCL: 148 if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) { 149 error = EINVAL; 150 break; 151 } 152 if (*mtod(*m, int *)) 153 rp->rinp_flags |= RINPF_HDRINCL; 154 else 155 rp->rinp_flags &= ~RINPF_HDRINCL; 156 break; 157 158 default: 159 error = EINVAL; 160 break; 161 } 162 break; 163 164 case PRCO_GETOPT: 165 *m = m_get(M_WAIT, MT_SOOPTS); 166 switch (optname) { 167 168 case IP_OPTIONS: 169 if (rp->rinp_options) { 170 (*m)->m_len = rp->rinp_options->m_len; 171 bcopy(mtod(rp->rinp_options, caddr_t), 172 mtod(*m, caddr_t), (unsigned)(*m)->m_len); 173 } else 174 (*m)->m_len = 0; 175 break; 176 177 case IP_HDRINCL: 178 (*m)->m_len = sizeof (int); 179 *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL; 180 break; 181 182 default: 183 error = EINVAL; 184 m_freem(*m); 185 *m = 0; 186 break; 187 } 188 break; 189 } 190 if (op == PRCO_SETOPT && *m) 191 (void)m_free(*m); 192 return (error); 193 } 194 195 /*ARGSUSED*/ 196 rip_usrreq(so, req, m, nam, control) 197 register struct socket *so; 198 int req; 199 struct mbuf *m, *nam, *control; 200 { 201 register int error = 0; 202 register struct raw_inpcb *rp = sotorawinpcb(so); 203 204 switch (req) { 205 206 case PRU_ATTACH: 207 if (rp) 208 panic("rip_attach"); 209 MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK); 210 if (rp == 0) 211 return (ENOBUFS); 212 bzero((caddr_t)rp, sizeof *rp); 213 so->so_pcb = (caddr_t)rp; 214 break; 215 216 case PRU_DETACH: 217 if (rp == 0) 218 panic("rip_detach"); 219 if (rp->rinp_options) 220 m_freem(rp->rinp_options); 221 if (rp->rinp_route.ro_rt) 222 RTFREE(rp->rinp_route.ro_rt); 223 if (rp->rinp_rcb.rcb_laddr) 224 rp->rinp_rcb.rcb_laddr = 0; 225 break; 226 227 case PRU_BIND: 228 { 229 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 230 231 if (nam->m_len != sizeof(*addr)) 232 return (EINVAL); 233 if ((ifnet == 0) || 234 ((addr->sin_family != AF_INET) && 235 (addr->sin_family != AF_IMPLINK)) || 236 (addr->sin_addr.s_addr && 237 ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 238 return (EADDRNOTAVAIL); 239 rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr; 240 rp->rinp_laddr = *addr; 241 return (0); 242 } 243 case PRU_CONNECT: 244 { 245 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 246 247 if (nam->m_len != sizeof(*addr)) 248 return (EINVAL); 249 if (ifnet == 0) 250 return (EADDRNOTAVAIL); 251 if ((addr->sin_family != AF_INET) && 252 (addr->sin_family != AF_IMPLINK)) 253 return (EAFNOSUPPORT); 254 rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr; 255 rp->rinp_faddr = *addr; 256 soisconnected(so); 257 return (0); 258 } 259 } 260 error = raw_usrreq(so, req, m, nam, control); 261 262 if (error && (req == PRU_ATTACH) && so->so_pcb) 263 free(so->so_pcb, M_PCB); 264 return (error); 265 } 266