* Copyright (c) 1980, 1986 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_usrreq.c 7.4 (Berkeley) 6/27/88
#include "../machine/mtpr.h"
* Initialize raw connection block q.
rawcb
.rcb_next
= rawcb
.rcb_prev
= &rawcb
;
rawintrq
.ifq_maxlen
= IFQ_MAXLEN
;
* Raw protocol interface.
raw_input(m0
, proto
, src
, dst
)
struct sockaddr
*src
, *dst
;
* Rip off an mbuf for a generic header.
m
= m_get(M_DONTWAIT
, MT_HEADER
);
m
->m_len
= sizeof(struct raw_header
);
rh
= mtod(m
, struct raw_header
*);
* Header now contains enough info to decide
* which socket to place packet in (if any).
* Queue it up for the raw protocol process
* running at software interrupt level.
IF_ENQUEUE(&rawintrq
, m
);
* Raw protocol input routine. Process packets entered
* into the queue at interrupt time. Find the socket
* associated with the packet(s) and move them over. If
* nothing exists for this packet, drop it.
register struct rawcb
*rp
;
register struct raw_header
*rh
;
IF_DEQUEUE(&rawintrq
, m
);
rh
= mtod(m
, struct raw_header
*);
for (rp
= rawcb
.rcb_next
; rp
!= &rawcb
; rp
= rp
->rcb_next
) {
if (rp
->rcb_proto
.sp_family
!= rh
->raw_proto
.sp_family
)
if (rp
->rcb_proto
.sp_protocol
&&
rp
->rcb_proto
.sp_protocol
!= rh
->raw_proto
.sp_protocol
)
* We assume the lower level routines have
* placed the address in a canonical format
* suitable for a structure comparison.
(bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0)
if ((rp
->rcb_flags
& RAW_LADDR
) &&
!equal(rp
->rcb_laddr
, rh
->raw_dst
))
if ((rp
->rcb_flags
& RAW_FADDR
) &&
!equal(rp
->rcb_faddr
, rh
->raw_src
))
if (n
= m_copy(m
->m_next
, 0, (int)M_COPYALL
)) {
if (sbappendaddr(&last
->so_rcv
, &rh
->raw_src
,
n
, (struct mbuf
*)0) == 0)
/* should notify about lost packet */
if (sbappendaddr(&last
->so_rcv
, &rh
->raw_src
,
m
->m_next
, (struct mbuf
*)0) == 0)
(void) m_free(m
); /* header */
if (cmd
< 0 || cmd
> PRC_NCMDS
)
raw_usrreq(so
, req
, m
, nam
, rights
)
struct mbuf
*m
, *nam
, *rights
;
register struct rawcb
*rp
= sotorawcb(so
);
if (rights
&& rights
->m_len
) {
if (rp
== 0 && req
!= PRU_ATTACH
) {
* Allocate a raw control block and fill in the
* necessary info to allow packets to be routed to
* the appropriate raw interface routine.
if ((so
->so_state
& SS_PRIV
) == 0) {
error
= raw_attach(so
, (int)nam
);
* Destroy state just before socket deallocation.
* Flush data or not depending on the options.
* If a socket isn't bound to a single address,
* the raw input routine will hand it anything
* within that protocol family (assuming there's
* nothing else around it should go to).
if (rp
->rcb_flags
& RAW_FADDR
) {
if (rp
->rcb_flags
& RAW_LADDR
) {
error
= EINVAL
; /* XXX */
error
= raw_bind(so
, nam
);
if ((rp
->rcb_flags
& RAW_FADDR
) == 0) {
* Mark the connection as being incapable of further input.
* Ship a packet out. The appropriate raw output
* routine handles any massaging necessary.
if (rp
->rcb_flags
& RAW_FADDR
) {
} else if ((rp
->rcb_flags
& RAW_FADDR
) == 0) {
error
= (*so
->so_proto
->pr_output
)(m
, so
);
rp
->rcb_flags
&= ~RAW_FADDR
;
* stat: don't bother with a blocksize.
bcopy((caddr_t
)&rp
->rcb_laddr
, mtod(nam
, caddr_t
),
sizeof (struct sockaddr
));
nam
->m_len
= sizeof (struct sockaddr
);
bcopy((caddr_t
)&rp
->rcb_faddr
, mtod(nam
, caddr_t
),
sizeof (struct sockaddr
));
nam
->m_len
= sizeof (struct sockaddr
);