home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netinet / raw_ip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  6.8 KB  |  262 lines

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