* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)raw_ip.c 7.5 (Berkeley) %G%
#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
;
raw_input(m
, &ripproto
, (struct sockaddr
*)&ripsrc
,
(struct sockaddr
*)&ripdst
);
* 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
, rights
, control
)
register struct socket
*so
;
struct mbuf
*m
, *nam
, *rights
, *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
, rights
, control
);
if (error
&& (req
== PRU_ATTACH
) && so
->so_pcb
)