* Copyright (c) 1985, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)ns_ip.c 7.1 (Berkeley) %G%
* 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 "../netns/ns_if.h"
#include "../netns/idp.h"
int nsipoutput(), nsipioctl();
#define LOMTU (1024+512);
struct mbuf
*nsip_list
; /* list of all hosts and gateways or
register struct mbuf
*m
= m_getclr(M_DONTWAIT
, MT_PCB
);
register struct ifnet
*ifp
;
if (m
== NULL
) return (NULL
);
m
->m_len
= sizeof(struct ifnet_en
);
ifp
= mtod(m
, struct ifnet
*);
ifp
->if_ioctl
= nsipioctl
;
ifp
->if_output
= nsipoutput
;
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_copy(m
, 0, (int)M_COPYALL
);
* Get IP and IDP header together in first mbuf.
s
= sizeof (struct ip
) + sizeof (struct idp
);
if ((m
->m_off
> MMAXOFF
|| 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_off
+= sizeof (struct ip
);
m
->m_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.
if (m
->m_off
>= MMINOFF
+ sizeof(struct ifnet
*)) {
m
->m_off
-= sizeof(struct ifnet
*);
m
->m_len
+= sizeof(struct ifnet
*);
n
= m_get(M_DONTWAIT
, MT_HEADER
);
if (n
== (struct mbuf
*)0)
n
->m_len
= sizeof(struct ifnet
*);
*(mtod(m
, struct ifnet
**)) = ifp
;
register struct mbuf
*m
= dtom(ifn
);
register struct route
*ro
= &(ifn
->ifen_route
);
register struct idp
*idp
= mtod(m0
, struct idp
*);
if (m
->m_len
!= sizeof(struct ifnet_en
)) {
printf("nsipoutput: bad dst ifp %x\n", ifn
);
ifn
->ifen_ifnet
.if_opackets
++;
* Calculate data length and make space
len
= ntohs(idp
->idp_len
);
if (len
& 1) len
++; /* Preserve Garbage Byte */
if (m
->m_off
< MMINOFF
+ sizeof (struct ip
)) {
m
= m_get(M_DONTWAIT
, MT_HEADER
);
m
->m_off
= MMAXOFF
- sizeof (struct ip
);
m
->m_len
= sizeof (struct ip
);
m
->m_off
-= sizeof (struct ip
);
m
->m_len
+= sizeof (struct ip
);
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
;
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 (m
= nsip_list
; m
; m
= m
->m_next
) {
struct ifnet
*ifp
= mtod(m
, struct ifnet
*);
if ((ifp
->if_flags
& IFF_UP
) == 0)
if (m
== (struct mbuf
*) 0)
ifn
= mtod(m
, struct ifnet_en
*);
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 (m
= nsip_list
; m
; m
= m
->m_next
) {
ifn
= mtod(m
, struct ifnet_en
*);
if (ifn
->ifen_dst
.s_addr
== dst
->s_addr
&&
RTFREE(ifn
->ifen_route
.ro_rt
);
ifn
->ifen_route
.ro_rt
= 0;