* Copyright (c) 1984, 1985, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)idp_usrreq.c 7.1 (Berkeley) %G%
#include "../net/route.h"
* IDP protocol implementation.
struct sockaddr_ns idp_ns
= { AF_NS
};
* This may also be called for raw listeners.
register struct nspcb
*nsp
;
register struct idp
*idp
= mtod(m
, struct idp
*);
* Construct sockaddr format source address.
* Stuff source address and datagram in user buffer.
idp_ns
.sns_addr
= idp
->idp_sna
;
if (ns_neteqnn(idp
->idp_sna
.x_net
, ns_zeronet
) && ifp
) {
register struct ifaddr
*ia
;
for (ia
= ifp
->if_addrlist
; ia
; ia
= ia
->ifa_next
) {
if (ia
->ifa_addr
.sa_family
== AF_NS
) {
IA_SNS(ia
)->sns_addr
.x_net
;
nsp
->nsp_rpt
= idp
->idp_pt
;
if ( ! (nsp
->nsp_flags
& NSP_RAWIN
) ) {
m
->m_len
-= sizeof (struct idp
);
m
->m_off
+= sizeof (struct idp
);
if (sbappendaddr(&nsp
->nsp_socket
->so_rcv
, (struct sockaddr
*)&idp_ns
,
m
, (struct mbuf
*)0) == 0)
sorwakeup(nsp
->nsp_socket
);
struct socket
*so
= nsp
->nsp_socket
;
* Drop connection, reporting
register struct nspcb
*nsp
;
struct socket
*so
= nsp
->nsp_socket
;
* someday, in the xerox world
* we will generate error protocol packets
* announcing that the socket has gone away.
/*if (TCPS_HAVERCVDSYN(tp->t_state)) {
tp->t_state = TCPS_CLOSED;
register struct idp
*idp
;
register struct socket
*so
;
register struct route
*ro
;
for (m
= m0
; m
; m
= m
->m_next
) {
* Make sure packet is actually of even length.
if (m
->m_len
+ m
->m_off
< MMAXOFF
) {
struct mbuf
*m1
= m_get(M_DONTWAIT
, MT_DATA
);
* Fill in mbuf with extended IDP header
* and addresses and length put into network format.
if (nsp
->nsp_flags
& NSP_RAWOUT
) {
idp
= mtod(m
, struct idp
*);
m
= m_get(M_DONTWAIT
, MT_HEADER
);
m
->m_off
= MMAXOFF
- sizeof (struct idp
) - 2;
/* adjust to start on longword bdry
m
->m_len
= sizeof (struct idp
);
idp
= mtod(m
, struct idp
*);
idp
->idp_pt
= nsp
->nsp_dpt
;
idp
->idp_sna
= nsp
->nsp_laddr
;
idp
->idp_dna
= nsp
->nsp_faddr
;
len
+= sizeof (struct idp
);
idp
->idp_len
= htons((u_short
)len
);
len
= ((len
- 1) | 1) + 1;
idp
->idp_sum
= ns_cksum(m
, len
);
if (so
->so_options
& SO_DONTROUTE
)
return (ns_output(m
, (struct route
*)0,
(so
->so_options
& SO_BROADCAST
) | NS_ROUTETOIF
));
* Use cached route for previous datagram if
* possible. If the previous net was the same
* and the interface was a broadcast medium, or
* if the previous destination was identical,
* NB: We don't handle broadcasts because that
* would require 3 subroutine calls.
* I think that this will all be handled in ns_pcbconnect!
if(ns_neteq(nsp
->nsp_lastdst
, idp
->idp_dna
)) {
* This assumes we have no GH type routes
if (ro
->ro_rt
->rt_flags
& RTF_HOST
) {
if (!ns_hosteq(nsp
->nsp_lastdst
, idp
->idp_dna
))
if ((ro
->ro_rt
->rt_flags
& RTF_GATEWAY
) == 0) {
register struct ns_addr
*dst
=
&satons_addr(ro
->ro_dst
);
dst
->x_host
= idp
->idp_dna
.x_host
;
* Otherwise, we go through the same gateway
* and dst is already set up.
ro
->ro_rt
= (struct rtentry
*)0;
nsp
->nsp_lastdst
= idp
->idp_dna
;
return (ns_output(m
, ro
, so
->so_options
& SO_BROADCAST
));
idp_ctloutput(req
, so
, level
, name
, value
)
struct nspcb
*nsp
= sotonspcb(so
);
m
= m_get(M_DONTWAIT
, MT_DATA
);
case SO_HEADERS_ON_INPUT
:
case SO_HEADERS_ON_OUTPUT
:
m
->m_len
= sizeof(short);
m
->m_off
= MMAXOFF
- sizeof(short);
*mtod(m
, short *) = nsp
->nsp_flags
& mask
;
m
->m_len
= sizeof(struct idp
);
m
->m_off
= MMAXOFF
- sizeof(struct idp
);
register struct idp
*idp
= mtod(m
, struct idp
*);
idp
->idp_pt
= nsp
->nsp_dpt
;
idp
->idp_dna
= nsp
->nsp_faddr
;
idp
->idp_sna
= nsp
->nsp_laddr
;
m
->m_off
= MMAXOFF
- sizeof(long);
*mtod(m
, long *) = ns_pexseq
++;
case SO_HEADERS_ON_INPUT
:
case SO_HEADERS_ON_OUTPUT
:
ok
= mtod(*value
, int *);
= mtod(*value
, struct idp
*);
nsp
->nsp_dpt
= idp
->idp_pt
;
error
= nsip_route(*value
);
idp_usrreq(so
, req
, m
, nam
, rights
)
struct mbuf
*m
, *nam
, *rights
;
struct nspcb
*nsp
= sotonspcb(so
);
return (ns_control(so
, (int)m
, (caddr_t
)nam
,
(struct ifnet
*)rights
));
if (rights
&& rights
->m_len
) {
if (nsp
== NULL
&& req
!= PRU_ATTACH
) {
error
= ns_pcballoc(so
, &nspcb
);
error
= soreserve(so
, 2048, 2048);
error
= ns_pcbbind(nsp
, nam
);
if (!ns_nullhost(nsp
->nsp_faddr
)) {
error
= ns_pcbconnect(nsp
, nam
);
if (ns_nullhost(nsp
->nsp_faddr
)) {
if (!ns_nullhost(nsp
->nsp_faddr
)) {
* Must block input while temporarily connected.
error
= ns_pcbconnect(nsp
, nam
);
if (ns_nullhost(nsp
->nsp_faddr
)) {
error
= idp_output(nsp
, m
);
nsp
->nsp_laddr
.x_host
= laddr
.x_host
;
nsp
->nsp_laddr
.x_port
= laddr
.x_port
;
ns_setsockaddr(nsp
, nam
);
ns_setpeeraddr(nsp
, nam
);
* stat: don't bother with a blocksize.
return (EOPNOTSUPP
); /* do not free mbuf's */
idp_raw_usrreq(so
, req
, m
, nam
, rights
)
struct mbuf
*m
, *nam
, *rights
;
struct nspcb
*nsp
= sotonspcb(so
);
extern struct nspcb nsrawpcb
;
if (!suser() || (nsp
!= NULL
)) {
error
= ns_pcballoc(so
, &nsrawpcb
);
error
= soreserve(so
, 2048, 2048);
nsp
->nsp_faddr
.x_host
= ns_broadhost
;
nsp
->nsp_flags
= NSP_RAWIN
| NSP_RAWOUT
;
error
= idp_usrreq(so
, req
, m
, nam
, rights
);