123186Smckusick /* 2*37322Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 332787Sbostic * All rights reserved. 423186Smckusick * 532787Sbostic * Redistribution and use in source and binary forms are permitted 634854Sbostic * provided that the above copyright notice and this paragraph are 734854Sbostic * duplicated in all such forms and that any documentation, 834854Sbostic * advertising materials, and other materials related to such 934854Sbostic * distribution and use acknowledge that the software was developed 1034854Sbostic * by the University of California, Berkeley. The name of the 1134854Sbostic * University may not be used to endorse or promote products derived 1234854Sbostic * from this software without specific prior written permission. 1334854Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434854Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534854Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1632787Sbostic * 17*37322Skarels * @(#)raw_ip.c 7.5 (Berkeley) 04/08/89 1823186Smckusick */ 195123Swnj 2017062Sbloom #include "param.h" 21*37322Skarels #include "malloc.h" 2217062Sbloom #include "mbuf.h" 2317062Sbloom #include "socket.h" 2417062Sbloom #include "protosw.h" 2517062Sbloom #include "socketvar.h" 2617062Sbloom #include "errno.h" 2710894Ssam 286509Ssam #include "../net/if.h" 2913455Ssam #include "../net/route.h" 3010894Ssam #include "../net/raw_cb.h" 3110894Ssam 3217062Sbloom #include "in.h" 3317062Sbloom #include "in_systm.h" 3417062Sbloom #include "ip.h" 3517062Sbloom #include "ip_var.h" 36*37322Skarels #include "in_pcb.h" 375123Swnj 385123Swnj /* 395612Swnj * Raw interface to IP protocol. 405123Swnj */ 415612Swnj 42*37322Skarels struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET }; 43*37322Skarels struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; 4413455Ssam struct sockproto ripproto = { PF_INET }; 455612Swnj /* 465612Swnj * Setup generic address and protocol structures 475612Swnj * for raw_input routine, then pass them along with 485612Swnj * mbuf chain. 495612Swnj */ 505123Swnj rip_input(m) 515123Swnj struct mbuf *m; 525123Swnj { 535612Swnj register struct ip *ip = mtod(m, struct ip *); 545123Swnj 555612Swnj ripproto.sp_protocol = ip->ip_p; 565646Ssam ripdst.sin_addr = ip->ip_dst; 575646Ssam ripsrc.sin_addr = ip->ip_src; 586529Ssam raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 596529Ssam (struct sockaddr *)&ripdst); 605123Swnj } 615123Swnj 625612Swnj /* 635612Swnj * Generate IP header and pass packet to ip_output. 645612Swnj * Tack on options user may have setup with control call. 655612Swnj */ 66*37322Skarels #define satosin(sa) ((struct sockaddr_in *)(sa)) 67*37322Skarels rip_output(m, so) 68*37322Skarels register struct mbuf *m; 695612Swnj struct socket *so; 705123Swnj { 715612Swnj register struct ip *ip; 72*37322Skarels register struct raw_inpcb *rp = sotorawinpcb(so); 73*37322Skarels register struct sockaddr_in *sin; 745123Swnj 755612Swnj /* 76*37322Skarels * If the user handed us a complete IP packet, use it. 77*37322Skarels * Otherwise, allocate an mbuf for a header and fill it in. 785612Swnj */ 79*37322Skarels if (rp->rinp_flags & RINPF_HDRINCL) 80*37322Skarels ip = mtod(m, struct ip *); 81*37322Skarels else { 82*37322Skarels M_PREPEND(m, sizeof(struct ip), M_WAIT); 83*37322Skarels ip = mtod(m, struct ip *); 84*37322Skarels ip->ip_tos = 0; 85*37322Skarels ip->ip_off = 0; 86*37322Skarels ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol; 87*37322Skarels ip->ip_len = m->m_pkthdr.len; 88*37322Skarels if (sin = satosin(rp->rinp_rcb.rcb_laddr)) { 89*37322Skarels ip->ip_src = sin->sin_addr; 90*37322Skarels } else 91*37322Skarels ip->ip_src.s_addr = 0; 92*37322Skarels if (sin = satosin(rp->rinp_rcb.rcb_faddr)) 93*37322Skarels ip->ip_dst = sin->sin_addr; 94*37322Skarels ip->ip_ttl = MAXTTL; 955612Swnj } 96*37322Skarels return (ip_output(m, 97*37322Skarels (rp->rinp_flags & RINPF_HDRINCL)? (struct mbuf *)0: rp->rinp_options, 98*37322Skarels &rp->rinp_route, 9926037Skarels (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 1005123Swnj } 10126037Skarels 10226037Skarels /* 10326037Skarels * Raw IP socket option processing. 10426037Skarels */ 10526037Skarels rip_ctloutput(op, so, level, optname, m) 10626037Skarels int op; 10726037Skarels struct socket *so; 10826037Skarels int level, optname; 10926037Skarels struct mbuf **m; 11026037Skarels { 11126037Skarels int error = 0; 112*37322Skarels register struct raw_inpcb *rp = sotorawinpcb(so); 11326037Skarels 11426037Skarels if (level != IPPROTO_IP) 11526037Skarels error = EINVAL; 11626037Skarels else switch (op) { 11726037Skarels 11826037Skarels case PRCO_SETOPT: 11926037Skarels switch (optname) { 120*37322Skarels 12126037Skarels case IP_OPTIONS: 122*37322Skarels return (ip_pcbopts(&rp->rinp_options, *m)); 12326037Skarels 124*37322Skarels case IP_HDRINCL: 125*37322Skarels if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) { 126*37322Skarels error = EINVAL; 127*37322Skarels break; 128*37322Skarels } 129*37322Skarels if (*mtod(*m, int *)) 130*37322Skarels rp->rinp_flags |= RINPF_HDRINCL; 131*37322Skarels else 132*37322Skarels rp->rinp_flags &= ~RINPF_HDRINCL; 133*37322Skarels break; 134*37322Skarels 13526037Skarels default: 13626037Skarels error = EINVAL; 13726037Skarels break; 13826037Skarels } 13926037Skarels break; 14026037Skarels 14126037Skarels case PRCO_GETOPT: 142*37322Skarels *m = m_get(M_WAIT, MT_SOOPTS); 14326037Skarels switch (optname) { 144*37322Skarels 14526037Skarels case IP_OPTIONS: 146*37322Skarels if (rp->rinp_options) { 147*37322Skarels (*m)->m_len = rp->rinp_options->m_len; 148*37322Skarels bcopy(mtod(rp->rinp_options, caddr_t), 14926386Skarels mtod(*m, caddr_t), (unsigned)(*m)->m_len); 15026037Skarels } else 15126037Skarels (*m)->m_len = 0; 15226037Skarels break; 153*37322Skarels 154*37322Skarels case IP_HDRINCL: 155*37322Skarels (*m)->m_len = sizeof (int); 156*37322Skarels *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL; 157*37322Skarels break; 158*37322Skarels 15926037Skarels default: 16026037Skarels error = EINVAL; 161*37322Skarels m_freem(*m); 162*37322Skarels *m = 0; 16326037Skarels break; 16426037Skarels } 16526037Skarels break; 16626037Skarels } 16731649Smckusick if (op == PRCO_SETOPT && *m) 16826386Skarels (void)m_free(*m); 16926037Skarels return (error); 17026037Skarels } 171*37322Skarels 172*37322Skarels /*ARGSUSED*/ 173*37322Skarels rip_usrreq(so, req, m, nam, rights, control) 174*37322Skarels register struct socket *so; 175*37322Skarels int req; 176*37322Skarels struct mbuf *m, *nam, *rights, *control; 177*37322Skarels { 178*37322Skarels register int error = 0; 179*37322Skarels register struct raw_inpcb *rp = sotorawinpcb(so); 180*37322Skarels 181*37322Skarels switch (req) { 182*37322Skarels 183*37322Skarels case PRU_ATTACH: 184*37322Skarels if (rp) 185*37322Skarels panic("rip_attach"); 186*37322Skarels MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK); 187*37322Skarels if (rp == 0) 188*37322Skarels return (ENOBUFS); 189*37322Skarels bzero((caddr_t)rp, sizeof *rp); 190*37322Skarels so->so_pcb = (caddr_t)rp; 191*37322Skarels break; 192*37322Skarels 193*37322Skarels case PRU_DETACH: 194*37322Skarels if (rp == 0) 195*37322Skarels panic("rip_detach"); 196*37322Skarels if (rp->rinp_options) 197*37322Skarels m_freem(rp->rinp_options); 198*37322Skarels if (rp->rinp_route.ro_rt) 199*37322Skarels RTFREE(rp->rinp_route.ro_rt); 200*37322Skarels if (rp->rinp_rcb.rcb_laddr) 201*37322Skarels rp->rinp_rcb.rcb_laddr = 0; 202*37322Skarels break; 203*37322Skarels 204*37322Skarels case PRU_BIND: 205*37322Skarels { 206*37322Skarels struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 207*37322Skarels 208*37322Skarels if (nam->m_len != sizeof(*addr)) 209*37322Skarels return (EINVAL); 210*37322Skarels if ((ifnet == 0) || 211*37322Skarels ((addr->sin_family != AF_INET) && 212*37322Skarels (addr->sin_family != AF_IMPLINK)) || 213*37322Skarels (addr->sin_addr.s_addr && 214*37322Skarels ifa_ifwithaddr((struct sockaddr *)addr) == 0)) 215*37322Skarels return (EADDRNOTAVAIL); 216*37322Skarels rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr; 217*37322Skarels rp->rinp_laddr = *addr; 218*37322Skarels return (0); 219*37322Skarels } 220*37322Skarels case PRU_CONNECT: 221*37322Skarels { 222*37322Skarels struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 223*37322Skarels 224*37322Skarels if (nam->m_len != sizeof(*addr)) 225*37322Skarels return (EINVAL); 226*37322Skarels if (ifnet == 0) 227*37322Skarels return (EADDRNOTAVAIL); 228*37322Skarels if ((addr->sin_family != AF_INET) && 229*37322Skarels (addr->sin_family != AF_IMPLINK)) 230*37322Skarels return (EAFNOSUPPORT); 231*37322Skarels rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr; 232*37322Skarels rp->rinp_laddr = *addr; 233*37322Skarels soisconnected(so); 234*37322Skarels return (0); 235*37322Skarels } 236*37322Skarels } 237*37322Skarels error = raw_usrreq(so, req, m, nam, rights, control); 238*37322Skarels 239*37322Skarels if (error && (req == PRU_ATTACH) && so->so_pcb) 240*37322Skarels free(so->so_pcb, M_PCB); 241*37322Skarels return (error); 242*37322Skarels } 243