/* raw_usrreq.c 4.7 82/02/02 */
#include "../h/protosw.h"
#include "../h/socketvar.h"
#include "../net/in_systm.h"
#include "../net/raw_cb.h"
#include "/usr/include/errno.h"
* Initialize raw connection block q.
rawcb
.rcb_next
= rawcb
.rcb_prev
= &rawcb
;
* Raw protocol interface.
raw_input(m0
, pf
, daf
, saf
)
struct sockaddr
*daf
, *saf
;
* Rip off an mbuf for a generic 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 socket
*so
;
register struct protosw
*pr
;
register struct sockproto
*sp
;
register struct sockaddr
*sa
;
IF_DEQUEUE(&rawintrq
, m
);
rawp
= mtod(m
, struct raw_header
*);
sp
= &rawp
->raw_protocol
;
* Find the appropriate socket(s) in which to place this
* packet. This is done by matching the protocol and
* address information prepended by raw_input against
* the info stored in the control block structures.
for (rp
= rawcb
.rcb_next
; rp
!= &rawcb
; rp
= rp
->rcb_next
) {
if (pr
->pr_family
!= sp
->sp_family
||
pr
->pr_protocol
!= sp
->sp_protocol
)
if (sa
->sa_family
!= so
->so_addr
.sa_family
)
* We assume the lower level routines have
* placed the address in a canonical format
* suitable for a structure comparison. Packets
* are duplicated for each receiving socket.
* SHOULD HAVE A NUMBER OF MECHANISMS FOR
* MATCHING BASED ON rcb_flags
if ((rp
->rcb_flags
& RAW_ADDR
) &&
bcmp(sa
->sa_data
, so
->so_addr
.sa_data
, 14) != 0)
* To avoid extraneous packet copies, we keep
* track of the last socket the packet should be
* placed in, and make copies only after finding a
* socket which "collides".
if (n
= m_copy(m
->m_next
, 0, M_COPYALL
))
if (sbappendaddr(&last
->so_rcv
, &rawp
->raw_src
, n
) == 0) {
* Should drop notification of lost packet
* into this guy's queue, but...
if (sbappendaddr(&last
->so_rcv
, &rawp
->raw_src
, m
->m_next
) == 0)
(void) m_free(m
); /* generic header */
raw_usrreq(so
, req
, m
, addr
)
register struct rawcb
*rp
= sotorawcb(so
);
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.
error
= raw_attach(so
, (struct sockaddr
*)addr
);
* 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_ADDR
)
raw_connaddr(rp
, (struct sockaddr
*)addr
);
if ((rp
->rcb_flags
& RAW_ADDR
) == 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_ADDR
)
raw_connaddr(rp
, (struct sockaddr
*)addr
);
} else if ((rp
->rcb_flags
& RAW_ADDR
) == 0)
(void) (*so
->so_proto
->pr_output
)(m
, so
);
rp
->rcb_flags
&= ~RAW_ADDR
;