* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
* @(#)raw_ip.c 8.2 (Berkeley) %G%
#include <sys/socketvar.h>
#include <netinet/in_systm.h>
#include <netinet/ip_var.h>
#include <netinet/ip_mroute.h>
#include <netinet/in_pcb.h>
* Nominal space allocated to a raw ip socket.
* Raw interface to IP protocol.
* Initialize raw connection block q.
rawinpcb
.inp_next
= rawinpcb
.inp_prev
= &rawinpcb
;
struct sockaddr_in ripsrc
= { sizeof(ripsrc
), AF_INET
};
* Setup generic address and protocol structures
* for raw_input routine, then pass them along with
register struct ip
*ip
= mtod(m
, struct ip
*);
register struct inpcb
*inp
;
ripsrc
.sin_addr
= ip
->ip_src
;
for (inp
= rawinpcb
.inp_next
; inp
!= &rawinpcb
; inp
= inp
->inp_next
) {
if (inp
->inp_ip
.ip_p
&& inp
->inp_ip
.ip_p
!= ip
->ip_p
)
if (inp
->inp_laddr
.s_addr
&&
inp
->inp_laddr
.s_addr
== ip
->ip_dst
.s_addr
)
if (inp
->inp_faddr
.s_addr
&&
inp
->inp_faddr
.s_addr
== ip
->ip_src
.s_addr
)
if (n
= m_copy(m
, 0, (int)M_COPYALL
)) {
if (sbappendaddr(&last
->so_rcv
, &ripsrc
,
n
, (struct mbuf
*)0) == 0)
/* should notify about lost packet */
if (sbappendaddr(&last
->so_rcv
, &ripsrc
,
m
, (struct mbuf
*)0) == 0)
* Generate IP header and pass packet to ip_output.
* Tack on options user may have setup with control call.
register struct inpcb
*inp
= sotoinpcb(so
);
int flags
= (so
->so_options
& SO_DONTROUTE
) | IP_ALLOWBROADCAST
;
* If the user handed us a complete IP packet, use it.
* Otherwise, allocate an mbuf for a header and fill it in.
if ((inp
->inp_flags
& INP_HDRINCL
) == 0) {
M_PREPEND(m
, sizeof(struct ip
), M_WAIT
);
ip
= mtod(m
, struct ip
*);
ip
->ip_p
= inp
->inp_ip
.ip_p
;
ip
->ip_len
= m
->m_pkthdr
.len
;
ip
->ip_src
= inp
->inp_laddr
;
ip
= mtod(m
, struct ip
*);
ip
->ip_id
= htons(ip_id
++);
/* XXX prevent ip_output from overwriting header fields */
return (ip_output(m
, opts
, &inp
->inp_route
, flags
, inp
->inp_moptions
));
* Raw IP socket option processing.
rip_ctloutput(op
, so
, level
, optname
, m
)
register struct inpcb
*inp
= sotoinpcb(so
);
if (op
== PRCO_SETOPT
|| op
== PRCO_GETOPT
) {
if (m
== 0 || *m
== 0 || (*m
)->m_len
< sizeof (int))
inp
->inp_flags
|= INP_HDRINCL
;
inp
->inp_flags
&= ~INP_HDRINCL
;
(*m
)->m_len
= sizeof (int);
*mtod(*m
, int *) = inp
->inp_flags
& INP_HDRINCL
;
error
= ip_mrouter_cmd(optname
, so
, *m
);
if (op
== PRCO_SETOPT
&& *m
)
return (ip_ctloutput(op
, so
, level
, optname
, m
));
u_long rip_sendspace
= RIPSNDQ
;
u_long rip_recvspace
= RIPRCVQ
;
rip_usrreq(so
, req
, m
, nam
, control
)
register struct socket
*so
;
struct mbuf
*m
, *nam
, *control
;
register struct inpcb
*inp
= sotoinpcb(so
);
extern struct socket
*ip_mrouter
;
if ((so
->so_state
& SS_PRIV
) == 0) {
if ((error
= soreserve(so
, rip_sendspace
, rip_recvspace
)) ||
(error
= in_pcballoc(so
, &rawinpcb
)))
inp
= (struct inpcb
*)so
->so_pcb
;
inp
->inp_ip
.ip_p
= (int)nam
;
if ((so
->so_state
& SS_ISCONNECTED
) == 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)) {
inp
->inp_laddr
= addr
->sin_addr
;
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
)) {
inp
->inp_faddr
= addr
->sin_addr
;
* Mark the connection as being incapable of further input.
* Ship a packet out. The appropriate raw output
* routine handles any massaging necessary.
if (so
->so_state
& SS_ISCONNECTED
) {
dst
= inp
->inp_faddr
.s_addr
;
dst
= mtod(nam
, struct sockaddr_in
*)->sin_addr
.s_addr
;
error
= rip_output(m
, so
, dst
);
* stat: don't bother with a blocksize.
in_setsockaddr(inp
, nam
);
in_setpeeraddr(inp
, nam
);