* Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)ns_ip.c 7.6 (Berkeley) 6/28/90
* Software interface driver for encapsulating ns in ip.
#include "../net/netisr.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
#include "../netinet/in_var.h"
#include "../netinet/ip.h"
#include "../netinet/ip_var.h"
#include "machine/mtpr.h"
#include "../netns/ns_if.h"
#include "../netns/idp.h"
struct ifnet_en
*ifen_next
;
int nsipoutput(), nsipioctl(), nsipstart();
#define LOMTU (1024+512);
struct ifnet_en
*nsip_list
; /* list of all hosts and gateways or
register struct ifnet_en
*m
;
register struct ifnet
*ifp
;
if (nsipif
.if_mtu
== 0) {
ifp
->if_ioctl
= nsipioctl
;
ifp
->if_output
= nsipoutput
;
ifp
->if_start
= nsipstart
;
ifp
->if_flags
= IFF_POINTOPOINT
;
MALLOC((m
), struct ifnet_en
*, sizeof(*m
), M_PCB
, M_NOWAIT
);
if (m
== NULL
) return (NULL
);
m
->ifen_next
= nsip_list
;
ifp
->if_ioctl
= nsipioctl
;
ifp
->if_output
= nsipoutput
;
ifp
->if_start
= nsipstart
;
ifp
->if_flags
= IFF_POINTOPOINT
;
ifp
->if_unit
= nsipif
.if_unit
++;
* Process an ioctl request.
nsipioctl(ifp
, cmd
, data
)
register struct ifnet
*ifp
;
* Everything else is done at a higher level.
ifr
= (struct ifreq
*)data
;
if ((ifr
->ifr_flags
& IFF_UP
) == 0)
struct mbuf
*nsip_badlen
;
struct mbuf
*nsip_lastin
;
register struct idp
*idp
;
register struct ifqueue
*ifq
= &nsintrq
;
nsip_lastin
= m_copym(m
, 0, (int)M_COPYALL
, M_DONTWAIT
);
* Get IP and IDP header together in first mbuf.
s
= sizeof (struct ip
) + sizeof (struct idp
);
if (((m
->m_flags
& M_EXT
) || m
->m_len
< s
) &&
(m
= m_pullup(m
, s
)) == 0) {
ip
= mtod(m
, struct ip
*);
if (ip
->ip_hl
> (sizeof (struct ip
) >> 2)) {
ip_stripoptions(ip
, (struct mbuf
*)0);
if ((m
= m_pullup(m
, s
)) == 0) {
ip
= mtod(m
, struct ip
*);
* Make mbuf data length reflect IDP length.
* If not enough data to reflect IDP length, drop.
m
->m_data
+= sizeof (struct ip
);
m
->m_len
-= sizeof (struct ip
);
m
->m_pkthdr
.len
-= sizeof (struct ip
);
idp
= mtod(m
, struct idp
*);
len
= ntohs(idp
->idp_len
);
if (len
& 1) len
++; /* Preserve Garbage Byte */
if (nsip_badlen
) m_freem(nsip_badlen
);
/* Any extra will be trimmed off by the NS routines */
* Place interface pointer before the data
* for the receiving protocol.
register struct route
*ro
= &(ifn
->ifen_route
);
register struct idp
*idp
= mtod(m
, struct idp
*);
ifn
->ifen_ifnet
.if_opackets
++;
* Calculate data length and make space
len
= ntohs(idp
->idp_len
);
if (len
& 1) len
++; /* Preserve Garbage Byte */
/* following clause not necessary on vax */
if (3 & (int)m
->m_data
) {
/* force longword alignment of ip hdr */
struct mbuf
*m0
= m_gethdr(MT_HEADER
, M_DONTWAIT
);
MH_ALIGN(m0
, sizeof (struct ip
));
m0
->m_flags
= m
->m_flags
& M_COPYFLAGS
;
m0
->m_len
= sizeof (struct ip
);
m0
->m_pkthdr
.len
= m0
->m_len
+ m
->m_len
;
M_PREPEND(m
, sizeof (struct ip
), M_DONTWAIT
);
ip
= mtod(m
, struct ip
*);
ip
->ip_src
= ifn
->ifen_src
;
ip
->ip_dst
= ifn
->ifen_dst
;
ip
->ip_len
= (u_short
)len
+ sizeof (struct ip
);
error
= (ip_output(m
, (struct mbuf
*)0, ro
, SO_BROADCAST
));
ifn
->ifen_ifnet
.if_oerrors
++;
ifn
->ifen_ifnet
.if_ierrors
= error
;
panic("nsip_start called\n");
struct ifreq ifr
= {"nsip0"};
register struct nsip_req
*rq
= mtod(m
, struct nsip_req
*);
struct sockaddr_ns
*ns_dst
= (struct sockaddr_ns
*)&rq
->rq_ns
;
struct sockaddr_in
*ip_dst
= (struct sockaddr_in
*)&rq
->rq_ip
;
* First, make sure we already have an ns address:
if (ns_hosteqnh(ns_thishost
, ns_zerohost
))
* Now, determine if we can get to the destination
bzero((caddr_t
)&ro
, sizeof (ro
));
ro
.ro_dst
= *(struct sockaddr
*)ip_dst
;
if (ro
.ro_rt
== 0 || ro
.ro_rt
->rt_ifp
== 0) {
* And see how he's going to get back to us:
* i.e., what return ip address do we use?
register struct in_ifaddr
*ia
;
struct ifnet
*ifp
= ro
.ro_rt
->rt_ifp
;
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
src
= (struct sockaddr_in
*)&ia
->ia_addr
;
* Is there a free (pseudo-)interface or space?
for (ifn
= nsip_list
; ifn
; ifn
= ifn
->ifen_next
) {
if ((ifn
->ifen_ifnet
.if_flags
& IFF_UP
) == 0)
ifn
->ifen_dst
= ip_dst
->sin_addr
;
ifn
->ifen_src
= src
->sin_addr
;
* now configure this as a point to point link
ifr
.ifr_name
[4] = '0' + nsipif
.if_unit
- 1;
ifr
.ifr_dstaddr
= * (struct sockaddr
*) ns_dst
;
(void)ns_control((struct socket
*)0, (int)SIOCSIFDSTADDR
, (caddr_t
)&ifr
,
satons_addr(ifr
.ifr_addr
).x_host
= ns_thishost
;
return (ns_control((struct socket
*)0, (int)SIOCSIFADDR
, (caddr_t
)&ifr
,
register struct ifnet_en
*ifn
= (struct ifnet_en
*)ifp
;
struct route
*ro
= & ifn
->ifen_route
;
ifp
->if_flags
&= ~IFF_UP
;
extern u_char inetctlerrmap
[];
if ((unsigned)cmd
>= PRC_NCMDS
)
if (sa
->sa_family
!= AF_INET
&& sa
->sa_family
!= AF_IMPLINK
)
sin
= (struct sockaddr_in
*)sa
;
if (sin
->sin_addr
.s_addr
== INADDR_ANY
)
case PRC_REDIRECT_TOSNET
:
case PRC_REDIRECT_TOSHOST
:
nsip_rtchange(&sin
->sin_addr
);
register struct in_addr
*dst
;
register struct ifnet_en
*ifn
;
for (ifn
= nsip_list
; ifn
; ifn
= ifn
->ifen_next
) {
if (ifn
->ifen_dst
.s_addr
== dst
->s_addr
&&
RTFREE(ifn
->ifen_route
.ro_rt
);
ifn
->ifen_route
.ro_rt
= 0;