* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* from: @(#)raw_ip.c 7.8 (Berkeley) 7/25/90
#include "../net/route.h"
#include "../net/raw_cb.h"
* Raw interface to IP protocol.
struct sockaddr_in ripdst
= { sizeof(ripdst
), AF_INET
};
struct sockaddr_in ripsrc
= { sizeof(ripsrc
), AF_INET
};
struct sockproto ripproto
= { PF_INET
};
* Setup generic address and protocol structures
* for raw_input routine, then pass them along with
register struct ip
*ip
= mtod(m
, struct ip
*);
ripproto
.sp_protocol
= ip
->ip_p
;
ripdst
.sin_addr
= ip
->ip_dst
;
ripsrc
.sin_addr
= ip
->ip_src
;
if (raw_input(m
, &ripproto
, (struct sockaddr
*)&ripsrc
,
(struct sockaddr
*)&ripdst
) == 0) {
* Generate IP header and pass packet to ip_output.
* Tack on options user may have setup with control call.
#define satosin(sa) ((struct sockaddr_in *)(sa))
register struct raw_inpcb
*rp
= sotorawinpcb(so
);
register struct sockaddr_in
*sin
;
* If the user handed us a complete IP packet, use it.
* Otherwise, allocate an mbuf for a header and fill it in.
if (rp
->rinp_flags
& RINPF_HDRINCL
)
ip
= mtod(m
, struct ip
*);
M_PREPEND(m
, sizeof(struct ip
), M_WAIT
);
ip
= mtod(m
, struct ip
*);
ip
->ip_p
= rp
->rinp_rcb
.rcb_proto
.sp_protocol
;
ip
->ip_len
= m
->m_pkthdr
.len
;
if (sin
= satosin(rp
->rinp_rcb
.rcb_laddr
)) {
ip
->ip_src
= sin
->sin_addr
;
if (sin
= satosin(rp
->rinp_rcb
.rcb_faddr
))
ip
->ip_dst
= sin
->sin_addr
;
(rp
->rinp_flags
& RINPF_HDRINCL
)? (struct mbuf
*)0: rp
->rinp_options
,
(so
->so_options
& SO_DONTROUTE
) | IP_ALLOWBROADCAST
));
* Raw IP socket option processing.
rip_ctloutput(op
, so
, level
, optname
, m
)
register struct raw_inpcb
*rp
= sotorawinpcb(so
);
return (ip_pcbopts(&rp
->rinp_options
, *m
));
if (m
== 0 || *m
== 0 || (*m
)->m_len
< sizeof (int)) {
rp
->rinp_flags
|= RINPF_HDRINCL
;
rp
->rinp_flags
&= ~RINPF_HDRINCL
;
*m
= m_get(M_WAIT
, MT_SOOPTS
);
(*m
)->m_len
= rp
->rinp_options
->m_len
;
bcopy(mtod(rp
->rinp_options
, caddr_t
),
mtod(*m
, caddr_t
), (unsigned)(*m
)->m_len
);
(*m
)->m_len
= sizeof (int);
*mtod(*m
, int *) = rp
->rinp_flags
& RINPF_HDRINCL
;
if (op
== PRCO_SETOPT
&& *m
)
rip_usrreq(so
, req
, m
, nam
, control
)
register struct socket
*so
;
struct mbuf
*m
, *nam
, *control
;
register struct raw_inpcb
*rp
= sotorawinpcb(so
);
MALLOC(rp
, struct raw_inpcb
*, sizeof *rp
, M_PCB
, M_WAITOK
);
bzero((caddr_t
)rp
, sizeof *rp
);
so
->so_pcb
= (caddr_t
)rp
;
m_freem(rp
->rinp_options
);
if (rp
->rinp_route
.ro_rt
)
RTFREE(rp
->rinp_route
.ro_rt
);
if (rp
->rinp_rcb
.rcb_laddr
)
rp
->rinp_rcb
.rcb_laddr
= 0;
struct sockaddr_in
*addr
= mtod(nam
, struct sockaddr_in
*);
if (nam
->m_len
!= sizeof(*addr
))
((addr
->sin_family
!= AF_INET
) &&
(addr
->sin_family
!= AF_IMPLINK
)) ||
(addr
->sin_addr
.s_addr
&&
ifa_ifwithaddr((struct sockaddr
*)addr
) == 0))
rp
->rinp_rcb
.rcb_laddr
= (struct sockaddr
*)&rp
->rinp_laddr
;
struct sockaddr_in
*addr
= mtod(nam
, struct sockaddr_in
*);
if (nam
->m_len
!= sizeof(*addr
))
if ((addr
->sin_family
!= AF_INET
) &&
(addr
->sin_family
!= AF_IMPLINK
))
rp
->rinp_rcb
.rcb_faddr
= (struct sockaddr
*)&rp
->rinp_faddr
;
error
= raw_usrreq(so
, req
, m
, nam
, control
);
if (error
&& (req
== PRU_ATTACH
) && so
->so_pcb
)